2015-03-14 22 views
5

Có thể lưu trữ khóa cá nhân/khóa công khai RSA trong nguồn ví dụ: byte[] hoặc string hoặc bất kỳ container nào khác và sử dụng khóa để mã hóa/giải mã?Làm cách nào để tải Khóa cá nhân/khóa công khai từ mảng chuỗi/byte hoặc bất kỳ vùng chứa nào khác

Một chức năng giải mã từ file sẽ như thế nào:

void Decode(const string& filename, BufferedTransformation& bt) 
{ 
    // http://www.cryptopp.com/docs/ref/class_file_source.html 
    FileSource file(filename.c_str(), true /*pumpAll*/); 

    file.TransferTo(bt); 
    bt.MessageEnd(); 
} 

Đó tải trọng từ tập tin mà không phải là những gì tôi muốn.

Tôi biết điều đó có thể thực hiện được vì tôi có thể tạo khóa với AutoSeededRandomPool.

Tôi chỉ không biết cách sử dụng ứng dụng hiện có.

Có thể tôi đang xem phần này trong tài liệu.

+0

Trên thực tế , Tôi chỉ tự hỏi liệu vấn đề đã được chọn một nguồn/sink thích hợp (ví dụ 'ArraySink' /' ArraySource'instead của 'FileSource' /' FileSink'), không phải là mã hóa/giải mã của tài liệu chính như tôi đã đã trả lời. Bạn có thể làm rõ? – softwariness

+0

@softwariness câu trả lời của bạn là thực sự tốt nhưng có nó là nhiều hơn về việc lựa chọn một nguồn thích hợp/sink: D Tôi không biết về ArraySink mặc dù O.o có thể giúp đỡ. Nếu bạn có thể bao gồm một cái gì đó về bồn cũng như trong câu trả lời của bạn tôi sẽ chấp nhận nó – deW1

+0

Trả lời ngay bây giờ được cập nhật với một ví dụ cho thấy tài liệu chính vòng tròn thông qua một bộ nhớ đệm, và một số khác cho thấy các tài liệu quan trọng được lưu trữ trong một std :: string với StringSink/StringSource tránh một số việc quản lý bộ đệm. – softwariness

Trả lời

9

Các trang Crypto++ Keys and FormatsCrypto++ RSA Cryptography có thể được quan tâm.

Nếu bạn đang tạo ra các thông số RSA như thế này:

AutoSeededRandomPool rng; 

InvertibleRSAFunction params; 
params.GenerateRandomWithKeySize(rng, 2048); 

Bạn có thể sử dụng việc sử dụng các DEREncodeBERDecode phương pháp InvertibleRSAFunction để mã hóa và giải mã tất cả các thông số tương ứng:

{ 
    FileSink output("rsaparams.dat"); 
    params.DEREncode(output); 
} 

InvertibleRSAFunction params2; 
{ 
    FileSource input("rsaparams.dat", true); 
    params2.BERDecode(input); 
} 

Để mã hóa/giải mã riêng tư và tài liệu công khai một cách riêng biệt, hãy sử dụng các phương pháp DEREncodeBERDecode trên RSA::PrivateKeyRSA::PublicKey đối tượng bản thân:

// Initialize keys from generated params 
RSA::PrivateKey rsaPrivate(params); 
RSA::PublicKey rsaPublic(params); 

// Write keys to file 
{ 
    FileSink output("rsaprivate.dat"); 
    rsaPrivate.DEREncode(output); 
} 
{ 
    FileSink output("rsapublic.dat"); 
    rsaPublic.DEREncode(output); 
} 

// Read keys from file into new objects 
RSA::PrivateKey rsaPrivate2; 
RSA::PublicKey rsaPublic2; 
{ 
    FileSource input("rsaprivate.dat", true); 
    rsaPrivate2.BERDecode(input); 
} 
{ 
    FileSource input("rsapublic.dat", true); 
    rsaPublic2.BERDecode(input); 
} 

FileSourceFileSink chỉ là ví dụ nguồn và chìm đối tượng mà bạn có thể sử dụng. Các thủ tục mã hóa/giải mã mất BufferedTransformation các đối tượng làm tham số, vì vậy bạn có thể sử dụng bất kỳ triển khai phù hợp nào khác của giao diện đó.

Ví dụ: ArraySink có thể được sử dụng để ghi dữ liệu vào bộ đệm bộ nhớ mà bạn cung cấp và StringSource (also aliased as ArraySource) có thể được sử dụng để đọc từ bộ đệm.

Dưới đây là một số mã cho thấy sử dụng ArraySinkArraySource để khứ hồi vật liệu private key thông qua một std::vector<byte>:

RSA::PrivateKey rsaPrivate(params); 
std::vector<byte> buffer(8192 /* buffer size */); 

ArraySink arraySink(&buffer[0], buffer.size()); 
rsaPrivate.DEREncode(arraySink); 

// Initialize variable with the encoded key material 
// (excluding unwritten bytes at the end of our buffer object) 
std::vector<byte> rsaPrivateMaterial(
    &buffer[0], 
    &buffer[0] + arraySink.TotalPutLength()); 

RSA::PrivateKey rsaPrivate2; 
ArraySource arraySource(
    &rsaPrivateMaterial[0], 
    rsaPrivateMaterial.size(), 
    true); 
rsaPrivate2.BERDecode(arraySource); 

(Xem thêm @jww's answer cho một ví dụ mà tránh bộ đệm kích thước cố định bằng cách sử dụng một ByteQueue).

Và một ví dụ khác sử dụng std::string để lưu trữ tài liệu chính và sử dụng lớp StringSink để ghi điều này, tránh một số thao tác quản lý bộ đệm (chuỗi sẽ được tự động thay đổi kích thước để khớp với lượng dữ liệu được mã hóa). Lưu ý rằng đây vẫn là dữ liệu nhị phân mặc dù nó nằm trong đối tượng std::string.

RSA::PrivateKey rsaPrivate(params); 

std::string rsaPrivateMaterial; 
StringSink stringSink(rsaPrivateMaterial); 
rsaPrivate.DEREncode(stringSink); 

RSA::PrivateKey rsaPrivate2; 
StringSource stringSource(rsaPrivateMaterial, true); 
rsaPrivate2.BERDecode(stringSource); 

Ngoài ra, nếu bạn muốn kiểm soát các định dạng chính mình, bạn có thể sử dụng các phương pháp của đối tượng InvertibleRSAFunction hoặc các đối tượng chủ chốt để trích xuất các thông số cá nhân (như thể hiện trong "Crypto ++ RSA Cryptography" liên kết ở trên) và sử dụng để trích xuất các giá trị cho việc lưu trữ ở định dạng của riêng bạn:

const Integer& n = params.GetModulus(); 
const Integer& p = params.GetPrime1(); 
const Integer& q = params.GetPrime2(); 
const Integer& d = params.GetPrivateExponent(); 
const Integer& e = params.GetPublicExponent(); 

Chất này có thể được phục hồi vào một mới InvertibleRSAFunction hoặc RSA::*Key dụ khi đọc từ tập tin hoặc container, bằng cách sử dụng các phương pháp setter tương ứng (SetModulus(), SetPrime1() , v.v.)

3

Làm thế nào tôi có thể tải một Private/Public Key từ một mảng chuỗi/byte hoặc bất kỳ container khác

thư viện Các Crypto ++ đã được xây dựng trong hỗ trợ cho std:strings. Nhưng các thùng chứa C++ khác sẽ phức tạp hơn. ArraySource đã được thêm tại Crypto ++ 5.6, nhưng chỉ có một số typedef cho StringSource.

Nếu bạn đang sử dụng tài liệu nhạy cảm, bạn cũng nên cân nhắc sử dụng SecByteBlock. Nó sẽ xóa hoặc zeroize các vật liệu nhạy cảm khi destructor chạy.

chuỗi và StringSource (load)

string spki = ...; 
StringSource ss(spki, true /*pumpAll*/); 

RSA::PublicKey publicKey; 
publicKey.Load(ss); 

vector và ArraySource (load)

vector<byte> spki = ...; 
ArraySource as(&spki[0], spki.length(), true /*pumpAll*/); 

RSA::PublicKey publicKey; 
publicKey.Load(as); 

chuỗi và StringSink (tiết kiệm)

string spki; 
StringSink ss(spki); 

RSA::PublicKey publicKey(...); 
publicKey.Save(ss); 

vectơ (lưu)

Xem mã bên dưới.


Dưới đây là một ví dụ về tiết kiệm đến và tải từ một std::vector. Bạn phải sử dụng một số trung gian ByteQueue để tiết kiệm vì bạn không thể dễ dàng tạo một VectorSink.

AutoSeededRandomPool prng; 
RSA::PrivateKey pk1, pk2; 

pk1.Initialize(prng, 1024); 
ByteQueue queue; 
pk1.Save(queue); 

vector<byte> spki; 
spki.resize(queue.MaxRetrievable()); 

ArraySink as1(&spki[0], spki.size()); 
queue.CopyTo(as1); 

ArraySource as2(&spki[0], spki.size(), true); 
pk2.Load(as2); 

bool valid = pk2.Validate(prng, 3); 
if(valid) 
    cout << "Validated private key" << endl; 
else 
    cout << "Failed to validate private key" << endl; 

Chúng tôi không có một rõ ràng VectorSink, và chúng ta không thể dễ dàng tạo ra một vì một kỳ vọng tiềm ẩn của traits_type::char_type. Ví dụ:

using CryptoPP::StringSinkTemplate; 
typedef StringSinkTemplate< std::vector<byte> > VectorSink; 

In file included from cryptopp-test.cpp:65: 
In file included from /usr/local/include/cryptopp/files.h:5: 
/usr/local/include/cryptopp/filters.h:590:22: error: no member named 
     'traits_type' in 'std::vector<unsigned char, std::allocator<unsigned char> 
     >' 
     typedef typename T::traits_type::char_type char_type; 
         ~~~^ 
cryptopp-test.cpp:243:20: note: in instantiation of template class 
     'CryptoPP::StringSinkTemplate<std::vector<unsigned char, 
     std::allocator<unsigned char> > >' requested here 
     VectorSink vs(spki); 

Bạn có thể tạo các VectorSourceVectorSink, nó chỉ sẽ mất một số công việc. Bạn có thể có ý tưởng về công việc có liên quan bằng cách xem mã số StringSourceStringSink trong filters.hfilters.cpp.

+0

không nên dòng này là 'publicKey.Save (ss);' thay vì 'publicKey.Save (spki);' kể từ 'Save()' mất một buffered chuyển đổi? – deW1

+0

tương tự nên áp dụng cho Tải() – deW1

+0

@ deW1 - Có, dọn dẹp. Cảm ơn (và xin lỗi về điều đó). – jww

0

Nếu bạn tạo khóa DSA như sau, bạn sẽ kết thúc với hai tệp, một tệp có chứa khóa cá nhân và khóa còn lại là khóa công khai.

void CreateDsaKeys(std::string folder) 
{ 
    AutoSeededRandomPool rng; 
    // Generate Private Key 
    DSA::PrivateKey privateKey; 
    privateKey.GenerateRandomWithKeySize(rng, 1024); 

    // Generate Public Key 
    DSA::PublicKey publicKey; 
    publicKey.AssignFrom(privateKey); 
    if (!privateKey.Validate(rng, 3) || !publicKey.Validate(rng, 3)) 
    { 
     throw runtime_error("DSA key generation failed"); 
    } 
    std::string publicPath = folder + "/publickey.txt"; 
    std::string privatePath = folder + "/privatekey.txt"; 
    SaveHexPublicKey(publicPath, publicKey); 
    SaveHexPrivateKey(privatePath, privateKey); 
} 

Sao chép nội dung của hai tập tin này vào mã nguồn của bạn và đặt chúng vào chuỗi:

std :: string PublicKey ("308201B73082012C ... F752BB791");

std :: string privatekey ("3082014C0201003 ... 0B8E805D83E9708");

Sau đó, bạn có thể sử dụng HexDecoder để chuyển đổi chuỗi thành byte và tạo ra các phím công cộng và tư nhân sử dụng các byte:

bool LoadDsaKeysFromStringsAndTest() 
{ 
    AutoSeededRandomPool rng; 
    HexDecoder decoderPublic; 
    decoderPublic.Put((byte*)publickey.data(), publickey.size()); 
    decoderPublic.MessageEnd(); 
    HexDecoder decoderPrivate; 
    decoderPrivate.Put((byte*)privatekey.data(), privatekey.size()); 
    decoderPrivate.MessageEnd(); 
    DSA::PublicKey publicKey; 
    publicKey.Load(decoderPublic); 
    DSA::PrivateKey privateKey; 
    privateKey.Load(decoderPrivate); 
    string message = "DSA Signature"; 
    string signature; 
    try { 
     DSA::Signer signer(privateKey); 
     StringSource ss1(message, true, 
      new SignerFilter(rng, signer, 
       new StringSink(signature) 
      ) // SignerFilter 
     ); // StringSource 

     bool result = false; 
     DSA::Verifier verifier1(publicKey); 
     StringSource ss(message+signature, true, 
       new SignatureVerificationFilter(verifier1, 
         new ArraySink((uint8_t*)&result, sizeof(result)), 
         SignatureVerificationFilter::PUT_RESULT | SignatureVerificationFilter::SIGNATURE_AT_END) 
       ); 
     return result; 
    } 
    catch(const CryptoPP::Exception& e) 
    { 
     std::cerr << e.what() << std::endl; 
    } 
    return false; 
} 

Đây là những thói quen khác cần thiết để tiết kiệm các phím

void Save(const string& filename, const BufferedTransformation& bt) 
{ 
    FileSink file(filename.c_str()); 
    bt.CopyTo(file); 
    file.MessageEnd(); 
} 

void SaveHex(const string& filename, const BufferedTransformation& bt) 
{ 
    HexEncoder encoder; 
    bt.CopyTo(encoder); 
    encoder.MessageEnd(); 
    Save(filename, encoder); 
} 

void SaveHexPrivateKey(const string& filename, const PrivateKey& key) 
{ 
    ByteQueue queue; 
    key.Save(queue); 
    SaveHex(filename, queue); 
} 

void SaveHexPublicKey(const string& filename, const PublicKey& key) 
{ 
    ByteQueue queue; 
    key.Save(queue); 
    SaveHex(filename, queue); 
} 
Các vấn đề liên quan