Как декодировать неключевые данные ASN1?

Можно ли использовать библиотеку crypto ++ для декодирования произвольных данных ASN1 (которые имеют пару последовательностей и целых чисел), которые у меня есть в байтовом массиве. ash.h содержит методы, которые все принимают BufferedTransformation в качестве входных данных, но этот класс является интерфейсом для различных шифров и хэшей, что на самом деле, похоже, вообще не связано с моим простым случаем. Я также нашел ASN1Object в cryptlib.h, но это другой интерфейс, и мне не удалось найти какие-либо реализующие классы.

Я думал, что это слишком сложно для меня, или это действительно трудно декодировать произвольные данные ASN1?

Я на самом деле использую это в iOS-приложении Swift / target-c, поэтому, если у кого-то есть простое решение с любым другим инструментом, дайте мне знать.

РЕДАКТИРОВАТЬ: Добавление примера структуры данных

SEQUENCE
SEQUENCE
INTEGER
INTEGER
SEQUENCE
INTEGER
INTEGER

Всегда есть родительская последовательность, которая содержит от 1 до n последовательностей, каждая из которых содержит 2 целых числа (пара шифрования elgamal (g ^ r, mh ^ r)).

2

Решение

SEQUENCE
SEQUENCE
INTEGER
INTEGER
SEQUENCE
INTEGER
INTEGER

Для этого вы хотели бы что-то вроде:

ArraySource as(data, size);
Integer i1, i2, i3, i4;

BERSequenceDecoder d1(as);
BERSequenceDecoder d2(d1);
i1.BERDecode(d2);
i2.BERDecode(d2);
d2.MessageEnd();
BERSequenceDecoder d3(d2);
i3.BERDecode(d3);
i4.BERDecode(d3);
d3.MessageEnd();
d1.MessageEnd();

которые содержат 2 целых числа (пара шифрования elgamal (g ^ r, mh ^ r)) каждое.

Когда у вас есть параметры (см. Ниже), вы должны вызвать один из Initialize функции с параметрами. не Назовите тех, кто принимает PRNG, потому что они создают параметры и ключи.

Увидеть gfpcrypt.h для некоторых из соответствующих определений классов. Также см ElGamal — Crypto ++ Wiki.


Вот пример, который генерирует пары целых чисел и упаковывает их в структуры ASN.1, как вы хотите. Затем он считывает их обратно и останавливается, когда не осталось ничего для потребления (то есть внутренние пары Integer являются необязательными).

Вы бы запустить его как ./asn1-test.exe или же ./asn1-test.exe 3 или же ./asn1-test.exe 6 или же ./asn1-test.exe 128, Размер всего 48 бит, поэтому вы не тратите время на создание целых чисел, которые вам не нужны.

static const unsigned int BIT_COUNT = 48;

int main(int argc, char* argv[])
{
unsigned int count = 2;
if(argc >= 2 && argv[1] != NULL)
{
istringstream iss(argv[1]);
iss >> count;

if(iss.fail()) count = 2;
}

cout << "Testing " << count << " integer pairs" << endl;

// Count to pairs
count *= 2;

try
{
AutoSeededRandomPool prng;

vector<Integer> vv;
vv.resize(count);

for(unsigned int i = 0; i < count; i += 2)
{
vv[i] = Integer(prng, BIT_COUNT);
vv[i + 1] = Integer(prng, BIT_COUNT);
}

// Scratch for holding ASN.1 encoded structures in Crypto++
ByteQueue queue;

// Encode them
{
DERSequenceEncoder outer(queue);

for(unsigned int i = 0; i < count; i += 2)
{
DERSequenceEncoder inner(outer);

vv[i].DEREncode(inner);
vv[i + 1].DEREncode(inner);

inner.MessageEnd();
}

outer.MessageEnd();
}

// Save it to file (use dumpasn1 to view it)
FileSink fs("sequences.der", true);
queue.CopyTo(fs);
fs.MessageEnd();

// Decode them
{
BERSequenceDecoder outer(queue);

// Ensure we break from the loop based on EndReached()
for( ; ; )
{
if(outer.EndReached()) break;

BERSequenceDecoder inner(outer);

Integer i1, i2;

i1.BERDecode(inner);
i2.BERDecode(inner);

cout << "Pair" << endl;
cout << std::hex << "  Integer: " << i1 << endl;
cout << std::hex << "  Integer: " << i2 << endl;

inner.MessageEnd();
}

outer.MessageEnd();
}

} catch (const Exception& ex) {
cerr << std::dec << ex.what() << endl;
exit (1);
}

return 0;
}

А вот как выглядит run and dump:

$ ./asn1-test.exe 3
Testing 3 integer pairs
Pair
Integer: 301818b3c631h
Integer: 1ff0ebf1ca4bh
Pair
Integer: f97e9d28e9cah
Integer: 94813cab125fh
Pair
Integer: 8a146ea68e7ch
Integer: 60d48ef2462fh

$ dumpasn1 sequences.der
0  57: SEQUENCE {
2  16:   SEQUENCE {
4   6:     INTEGER 30 18 18 B3 C6 31
12   6:     INTEGER 1F F0 EB F1 CA 4B
:     }
20  18:   SEQUENCE {
22   7:     INTEGER 00 F9 7E 9D 28 E9 CA
31   7:     INTEGER 00 94 81 3C AB 12 5F
:     }
40  17:   SEQUENCE {
42   7:     INTEGER 00 8A 14 6E A6 8E 7C
51   6:     INTEGER 60 D4 8E F2 46 2F
:     }
:   }

0 warnings, 0 errors.

Вот некоторые из них, чтобы избавить вас от необходимости искать их:

#include <iostream>
using std::ostream;
using std::cin;
using std::cout;
using std::cerr;
using std::endl;

#include <string>
using std::string;

#include <vector>
using std::vector;

#include <sstream>
using std::istringstream;

#include <cryptopp/cryptlib.h>
using CryptoPP::Exception;

#include <cryptopp/filters.h>
using CryptoPP::StringSource;
using CryptoPP::StringSink;

#include <cryptopp/files.h>
using CryptoPP::FileSink;

#include <cryptopp/integer.h>
using CryptoPP::Integer;

#include <cryptopp/osrng.h>
using CryptoPP::AutoSeededRandomPool;

#include <cryptopp/asn.h>
#include <cryptopp/oids.h>
namespace ASN1 = CryptoPP::ASN1;
using CryptoPP::DERSequenceEncoder;
using CryptoPP::BERSequenceDecoder;

#include <cryptopp/queue.h>
using CryptoPP::ByteQueue;
4

Другие решения