string RNEncryptor::encrypt(string plaintext, string password, RNCryptorSchema schemaVersion) { this->configureSettings(schemaVersion); RNCryptorPayloadComponents components; components.schema = (char)schemaVersion; components.options = (char)this->options; components.salt = this->generateSalt(); components.hmacSalt = this->generateSalt(); components.iv = this->generateIv(this->ivLength); SecByteBlock key = this->generateKey(components.salt, password); switch (this->aesMode) { case MODE_CTR: { CTR_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV((const byte *)key.data(), key.size(), (const byte *)components.iv.data()); StringSource(plaintext, true, // StreamTransformationFilter adds padding as required. new StreamTransformationFilter(encryptor, new StringSink(components.ciphertext) ) ); break; } case MODE_CBC: { CBC_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key.BytePtr(), key.size(), (const byte *)components.iv.data()); StringSource(plaintext, true, // StreamTransformationFilter adds padding as required. new StreamTransformationFilter(encryptor, new StringSink(components.ciphertext) ) ); break; } } stringstream binaryData; binaryData << components.schema; binaryData << components.options; binaryData << components.salt; binaryData << components.hmacSalt; binaryData << components.iv; binaryData << components.ciphertext; std::cout << "Hex encoded: " << this->hex_encode(binaryData.str()) << std::endl; binaryData << this->generateHmac(components, password); return this->base64_encode(binaryData.str()); }
void PEM_StripEncapsulatedBoundary(BufferedTransformation& bt, const SecByteBlock& pre, const SecByteBlock& post) { ByteQueue temp; SecByteBlock::const_iterator it; int n = 1, prePos = -1, postPos = -1; while(bt.AnyRetrievable() && n++) { SecByteBlock line, unused; PEM_ReadLine(bt, line, unused); // The write associated with an empty line must to occur. Otherwise, we loose the CR or LF // in an ecrypted private key between the control fields and the encapsulated text. //if(line.empty()) // continue; it = Search(line, pre); if(it != line.end()) { prePos = n; continue; } it = Search(line, post); if(it != line.end()) { postPos = n; continue; } PEM_WriteLine(temp, line); } if(prePos == -1) { string msg = "PEM_StripEncapsulatedBoundary: '"; msg += string((char*)pre.data(), pre.size()) + "' not found"; throw InvalidDataFormat(msg); } if(postPos == -1) { string msg = "PEM_StripEncapsulatedBoundary: '"; msg += string((char*)post.data(), post.size()) + "' not found"; throw InvalidDataFormat(msg); } if(prePos > postPos) throw InvalidDataFormat("PEM_StripEncapsulatedBoundary: header boundary follows footer boundary"); temp.TransferTo(bt); }
bool encryptFile(string filename, SecByteBlock key, byte* iv){ ifstream file; file.open(filename); if(file.is_open()){ string line; ofstream encFile; encFile.open("encText.txt", ios::app); CBC_Mode<AES>::Encryption enc; enc.SetKeyWithIV(key, key.size(), iv); while(getline(file, line)){ string cipher; //cout << line << endl; StringSource ss(line, true, new StreamTransformationFilter(enc, new StringSink(cipher))); if(encFile.is_open()){ encFile.write(cipher.c_str(), cipher.size()); encFile << '\r\n'; } else cout << "couldn't write" << endl; //cout << cipher << endl; } cout << "finished encrypting" << endl; encFile.close(); file.close(); return true; } else{ cout << "Unable to open file." << endl; return false; } }
void AES_CTR_Encrypt(const char *hexKey, const char *hexIV, const char *infile, const char *outfile) { SecByteBlock key = HexDecodeString(hexKey); SecByteBlock iv = HexDecodeString(hexIV); CTR_Mode<AES>::Encryption aes(key, key.size(), iv); FileSource(infile, true, new StreamTransformationFilter(aes, new FileSink(outfile))); }
ECP::Point ECP::BERDecodePoint(BufferedTransformation &bt) const { SecByteBlock str; BERDecodeOctetString(bt, str); Point P; if (!DecodePoint(P, str, str.size())) BERDecodeError(); return P; }
bool decryptFile(string filename, SecByteBlock key, byte* iv){ ifstream file; file.open(filename); if(file.is_open()){ string line; CBC_Mode<AES>::Decryption dec; dec.SetKeyWithIV(key, key.size(), iv); while(getline(file, line)){ string plain; //cout << line << endl; StringSource ss(line, true, new StreamTransformationFilter(dec, new StringSink(plain))); //cout << plain << endl; } file.close(); return true; } else{ cout << "Unable to open file." << endl; return false; } }
int main(int argc, char* argv[]) { if (!((argc == 5 && strcmp(argv[1], "-e") == 0) || (argc == 4 && strcmp(argv[1], "-d") == 0))) { printf("To encrypt: %s -e <mp3 file> <key> <content id>\n" "To decrypt: %s -d <mp3 file> <key>\n", argv[0], argv[0]); exit(1); } const char * str_op = argv[1]; const char * mp3_file_name = argv[2]; const char * str_key = argv[3]; const char * str_cid = ((argc == 5) ? argv[4] : NULL); if (strlen(mp3_file_name) < 4 || strcmp(&mp3_file_name[strlen(mp3_file_name) - 4], ".mp3") != 0) { printf("File must be \".mp3\".\n"); exit(-1); } if (strlen(str_key) != 32) { printf("The key must be 16 bytes (32 hexachars) long.\n"); exit(-1); } if (str_cid != NULL && strlen(str_cid) != 32) { printf("Content id must be 16 bytes (32 hexachars) long.\n"); exit(-1); } for (int i = 0; i < 32; ++i) { if (!(str_key[i] >= '0' && str_key[i] <= '9' || str_key[i] >= 'a' && str_key[i] <= 'f' || str_key[i] >= 'A' && str_key[i] <= 'F')) { printf("The key must be hexadecimal.\n"); exit(-1); } if (str_cid != NULL && !(str_key[i] >= '0' && str_key[i] <= '9' || str_key[i] >= 'a' && str_key[i] <= 'f' || str_key[i] >= 'A' && str_key[i] <= 'F')) { printf("The key must be hexadecimal.\n"); exit(-1); } } FILE * mp3_file; // Open the file mp3_file = fopen(mp3_file_name, "rb"); if (mp3_file == NULL) { printf("MP3 file not found: \"%s\"\n", mp3_file_name); } else { printf("\n"); // Get total mp3 file length long file_length = filelength(fileno(mp3_file)); // Check for ID3v1 or ID3v1.1 header bool hasID3v1 = false; long id3v1_pos = file_length - 128; ID3v1 id3v1; if (file_length >= 128) { fseek(mp3_file, id3v1_pos, SEEK_SET); hasID3v1 = readID3v1(mp3_file, &id3v1) && checkID3v1(&id3v1); } // Check for ID3v2 bool hasID3v2 = false; long id3v2_pos = 0; long id3v2_len = 0; if (file_length >= 10) { unsigned char id3v2_header[10]; fseek(mp3_file, 0, SEEK_SET); if (fread(id3v2_header, 10, 1, mp3_file) == 1 && memcmp(id3v2_header, "ID3", 3) == 0) { hasID3v2 = true; id3v2_len = 10 + (((unsigned int)(id3v2_header[6])) << 21) + (((unsigned int)(id3v2_header[7])) << 14) + (((unsigned int)(id3v2_header[8])) << 7) + ((unsigned int)(id3v2_header[9])); if (id3v2_header[5] & 0x10) id3v2_len += 10; } } // Check for Lyrics3 v1 bool hasLyrics3v1 = false; long lyrics3v1_pos = 0; long lyrics3v1_len = 0; if (hasID3v1 && file_length >= 148) { char lyricsEnd[9]; fseek(mp3_file, id3v1_pos - 9, SEEK_SET); if (fread(lyricsEnd, 9, 1, mp3_file) == 1 && memcmp(lyricsEnd, "LYRICSEND", 9) == 0) { // Found the end of a Lyrics3 field. Now, look backwards for LYRICSBEGIN. long maxLyricsLength = 11 + 5100; if (maxLyricsLength > file_length - 128 - 9) { maxLyricsLength = file_length - 128 - 9; } char * pLyrics = new char[maxLyricsLength]; long searchPos = file_length - 128 - 9 - maxLyricsLength; fseek(mp3_file, searchPos, SEEK_SET); fread(pLyrics, maxLyricsLength, 1, mp3_file); char * pSearch = pLyrics; char * pPlace; do { pPlace = (char*)memchr(pSearch, 'L', maxLyricsLength - 11 + 1); if (memcmp(pPlace, "LYRICSBEGIN", 11) == 0) { hasLyrics3v1 = true; lyrics3v1_pos = searchPos + (pPlace - pLyrics); lyrics3v1_len = file_length - 128 - 9 - lyrics3v1_pos; break; } else { maxLyricsLength -= (long)(pPlace - pSearch) + 1; pSearch = pPlace + 1; } } while (pPlace != NULL); delete [] pLyrics; } } // Check for Lyrics3 v2 bool hasLyrics3v2 = false; long lyrics3v2_pos = 0; long lyrics3v2_len = 0; if (hasID3v1 && file_length >= 148) { char lyricsEnd[9]; fseek(mp3_file, id3v1_pos - 9, SEEK_SET); if (fread(lyricsEnd, 9, 1, mp3_file) == 1 && memcmp(lyricsEnd, "LYRICS200", 9) == 0) { // Found the end of a Lyrics3 field. Now, read the length of the lyrics. char lyricsLength[6]; fseek(mp3_file, id3v1_pos - 9 - 6, SEEK_SET); if (fread(lyricsLength, 6, 1, mp3_file) == 1) { lyrics3v2_len = atol(lyricsLength); lyrics3v2_pos = id3v1_pos - 9 - 6 - lyrics3v2_len; // Confirm there's a LYRICSBEGIN tag. if (lyrics3v2_pos > 0) { char lyricsBegin[11]; fseek(mp3_file, lyrics3v2_pos, SEEK_SET); if (fread(lyricsBegin, 11, 1, mp3_file) == 1 && memcmp(lyricsBegin, "LYRICSBEGIN", 11) == 0) { hasLyrics3v2 = true; } } } } } // Look for the first frame in the file fseek(mp3_file, 0, SEEK_SET); if (!synchronize(mp3_file)) { printf("Is this a real mp3 file?\n"); } else { char * aes_file_name = new char[strlen(mp3_file_name) + 4 + 1]; strcpy(aes_file_name, mp3_file_name); strcat(aes_file_name, ".aes"); FILE * aes_file = fopen(aes_file_name, "wb"); if (aes_file == NULL) { printf("Couldn't open the destination file \"%s\".\n", aes_file_name); } else { char buffer[4096]; size_t nbToRead; size_t nbRead; // Save the current position (1st frame) long pos_1st_frame = ftell(mp3_file); fseek(mp3_file, 0, SEEK_SET); // Copy ID3v2 if (hasID3v2) { long nbID3v2ToGo = id3v2_len; while (nbID3v2ToGo > 0) { nbToRead = ((nbID3v2ToGo >= sizeof(buffer)) ? sizeof(buffer) : nbID3v2ToGo); nbRead = fread(buffer, 1, nbToRead, mp3_file); fwrite(buffer, 1, nbRead, aes_file); nbID3v2ToGo -= (long)nbRead; } } byte iv_buf[16]; // The buffer for AES's IV. DoRM_Box dormBox; bool hasDoRMBox = false; fread(buffer, 1, 4, mp3_file); if (memcmp(buffer, "DoRM", 4) == 0) { // This is a protected file. Read the Dorm_Box e decrypt the file. if (strcmp(str_op, "-e") == 0) { printf("This file is already protected.\n"); fclose(aes_file); unlink(aes_file_name); delete [] aes_file_name; fclose(mp3_file); exit(-1); } hasDoRMBox = true; fseek(mp3_file, -4, SEEK_CUR); fread(&dormBox, sizeof(DoRM_Box), 1, mp3_file); // Get the IV from the DoRM_Box. memcpy(iv_buf, dormBox.iv, 16); } else { // This is an unprotected file. Write the DoRM_Box and encrypt the file. if (strcmp(str_op, "-d") == 0) { printf("No DoRM box.\n"); fclose(aes_file); unlink(aes_file_name); delete [] aes_file_name; fclose(mp3_file); exit(-1); } fseek(mp3_file, -4, SEEK_CUR); // Generate an IV (with no FFs) srand((unsigned)time(NULL)); for (int i = 0; i < 16; ++i) { do { iv_buf[i] = rand(); } while (iv_buf[i] == 0xff); } // Write the DoRM box DoRM_Box dormBox; memcpy(dormBox.dorm, "DoRM", 4); memset(dormBox.version, 0, 2); memset(dormBox.reserved, 0, 2); size_t dormBoxLen = sizeof(DoRM_Box) - 10; dormBox.length[3] = (dormBoxLen & 0x0000007f); dormBox.length[2] = (dormBoxLen & 0x00003f80) >> 7; dormBox.length[1] = (dormBoxLen & 0x001fc000) >> 14; dormBox.length[0] = (dormBoxLen & 0x0fe00000) >> 21; unsigned dormProtId = 0x010000E0; // 0xE0000001 in big endian memcpy(dormBox.prot_id, &dormProtId, 4); //memset(dormBox.cid, 0, 16); // cid is 0 for now for (int i = 0; i < 16; ++i) { dormBox.cid[i] = (hex2bin(str_cid[i * 2 + 0]) << 4) | (hex2bin(str_cid[i * 2 + 1])); } memcpy(dormBox.iv, iv_buf, 16); fwrite(&dormBox, sizeof(DoRM_Box), 1, aes_file); } // Instantiate AES SecByteBlock key = HexDecodeString(str_key); SecByteBlock iv(iv_buf, 16); OFB_Mode<AES>::Encryption aes(key, key.size(), iv); // Write whatever exists between ID3v2 and the 1st frame { long nbPreambleToGo = pos_1st_frame - id3v2_len - (hasDoRMBox ? sizeof(DoRM_Box) : 0); while (nbPreambleToGo > 0) { nbToRead = ((nbPreambleToGo >= sizeof(buffer)) ? sizeof(buffer) : nbPreambleToGo); nbRead = fread(buffer, 1, nbToRead, mp3_file); fwrite(buffer, 1, nbRead, aes_file); nbPreambleToGo -= (long)nbRead; } } assert(ftell(mp3_file) == pos_1st_frame); long last_pos = 0; size_t buf_size = 4096; char * pBuffer = new char[buf_size]; int frame_length = 0; MP3Header mp3_header, mp3_nextHeader; for (;;) { for (;;) { last_pos = ftell(mp3_file); if (!readHeader(mp3_file, &mp3_header, true) || !checkHeader(&mp3_header)) { fseek(mp3_file, last_pos, SEEK_SET); break; } frame_length = getFrameLength(&mp3_header); if (!(frame_length > 0)) break; // Check if the next header is correct. If not, don't // cipher this block. It may ruin some unsupported field. fseek(mp3_file, last_pos + frame_length, SEEK_SET); if (!readHeader(mp3_file, &mp3_nextHeader, true) || !checkHeader(&mp3_nextHeader)) break; fseek(mp3_file, last_pos, SEEK_SET); if (frame_length < 4) { break; } else { nbToRead = frame_length; if (nbToRead > buf_size) { delete [] pBuffer; pBuffer = new char[nbToRead]; } nbRead = fread(pBuffer, 1, nbToRead, mp3_file); if ((((*(int*)(void*)(&mp3_header)) ^ (*(int*)(void*)(&mp3_nextHeader))) & 0xFFFFFDFF) == 0) { //printf("."); aes.ProcessData(((byte *)pBuffer) + 4, ((const byte *)pBuffer) + 4, nbRead - 4); } else { //printf("-"); } fwrite(pBuffer, 1, nbRead, aes_file); } } // Did we get to the end of the file or to a known extension? if ((last_pos == file_length) || (hasID3v1 && (last_pos == id3v1_pos)) || (hasLyrics3v2 && (last_pos == lyrics3v2_pos)) || (hasLyrics3v1 && (last_pos == lyrics3v1_pos))) break; // Something odd happened. Either the file is broken or // it has some unknown extension. As I can't probe for // the existence of an unknown extension (that's forbidden // in my religion) I'll assume the file is broken and // try to resynchronize. if (!synchronize(mp3_file)) { fseek(mp3_file, last_pos, SEEK_SET); break; } else { // We managed to resynchronize. Let's save the broken // part in clear (!) and continue ciphering. long sync_pos = ftell(mp3_file); fseek(mp3_file, last_pos, SEEK_SET); long nbToGo = sync_pos - last_pos; while (nbToGo > 0) { nbToRead = (((unsigned)nbToGo > buf_size) ? buf_size : (unsigned)nbToGo); nbRead = fread(pBuffer, 1, nbToRead, mp3_file); fwrite(pBuffer, 1, nbRead, aes_file); if (nbRead < nbToRead) { printf("Error reading file.\n"); goto exit; } nbToGo -= (long)nbRead; } } } exit: long nbToGo = file_length - last_pos; nbToRead = buf_size; while (nbToGo > 0) { nbRead = fread(pBuffer, 1, nbToRead, mp3_file); fwrite(pBuffer, 1, nbRead, aes_file); if (nbToRead <= (unsigned)nbToGo && nbRead < nbToRead) { printf("Error reading file.\n"); break; } nbToGo -= (long)nbRead; } delete [] pBuffer; fclose(aes_file); } if (aes_file_name != NULL) { delete [] aes_file_name; aes_file_name = NULL; } } fclose(mp3_file); } return 0; }
bool SecTpm::importPrivateKeyPkcs5IntoTpm(const Name& keyName, const uint8_t* buf, size_t size, const std::string& passwordStr) { using namespace CryptoPP; Oid pbes2Id; Oid pbkdf2Id; SecByteBlock saltBlock; uint32_t iterationCount; Oid pbes2encsId; SecByteBlock ivBlock; SecByteBlock encryptedDataBlock; try { // decode some decoding processes are not necessary for now, // because we assume only one encryption scheme. StringSource source(buf, size, true); // EncryptedPrivateKeyInfo ::= SEQUENCE { // encryptionAlgorithm EncryptionAlgorithmIdentifier, // encryptedData OCTET STRING } BERSequenceDecoder encryptedPrivateKeyInfo(source); { // EncryptionAlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBES2-id}}, // parameters SEQUENCE {{PBES2-params}} } BERSequenceDecoder encryptionAlgorithm(encryptedPrivateKeyInfo); { pbes2Id.decode(encryptionAlgorithm); // PBES2-params ::= SEQUENCE { // keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, // encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} } BERSequenceDecoder pbes2Params(encryptionAlgorithm); { // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{PBKDF2-id}}, // parameters SEQUENCE {{PBKDF2-params}} } BERSequenceDecoder pbes2KDFs(pbes2Params); { pbkdf2Id.decode(pbes2KDFs); // AlgorithmIdentifier ::= SEQUENCE { // salt OCTET STRING, // iterationCount INTEGER (1..MAX), // keyLength INTEGER (1..MAX) OPTIONAL, // prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 } BERSequenceDecoder pbkdf2Params(pbes2KDFs); { BERDecodeOctetString(pbkdf2Params, saltBlock); BERDecodeUnsigned<uint32_t>(pbkdf2Params, iterationCount, INTEGER); } pbkdf2Params.MessageEnd(); } pbes2KDFs.MessageEnd(); // AlgorithmIdentifier ::= SEQUENCE { // algorithm OBJECT IDENTIFIER {{DES-EDE3-CBC-PAD}}, // parameters OCTET STRING} {{iv}} } BERSequenceDecoder pbes2Encs(pbes2Params); { pbes2encsId.decode(pbes2Encs); BERDecodeOctetString(pbes2Encs, ivBlock); } pbes2Encs.MessageEnd(); } pbes2Params.MessageEnd(); } encryptionAlgorithm.MessageEnd(); BERDecodeOctetString(encryptedPrivateKeyInfo, encryptedDataBlock); } encryptedPrivateKeyInfo.MessageEnd(); } catch (const CryptoPP::Exception& e) { return false; } PKCS5_PBKDF2_HMAC<SHA1> keyGenerator; size_t derivedLen = 24; //For DES-EDE3-CBC-PAD byte derived[24] = {0}; byte purpose = 0; try { keyGenerator.DeriveKey(derived, derivedLen, purpose, reinterpret_cast<const byte*>(passwordStr.c_str()), passwordStr.size(), saltBlock.BytePtr(), saltBlock.size(), iterationCount); } catch (const CryptoPP::Exception& e) { return false; } //decrypt CBC_Mode< DES_EDE3 >::Decryption d; d.SetKeyWithIV(derived, derivedLen, ivBlock.BytePtr()); OBufferStream privateKeyOs; try { StringSource encryptedSource(encryptedDataBlock.BytePtr(), encryptedDataBlock.size(), true, new StreamTransformationFilter(d, new FileSink(privateKeyOs))); } catch (const CryptoPP::Exception& e) { return false; } if (!importPrivateKeyPkcs8IntoTpm(keyName, privateKeyOs.buf()->buf(), privateKeyOs.buf()->size())) return false; // determine key type StringSource privateKeySource(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size(), true); KeyType publicKeyType = KeyType::NONE; SecByteBlock rawKeyBits; // PrivateKeyInfo ::= SEQUENCE { // INTEGER, // SEQUENCE, // OCTECT STRING} BERSequenceDecoder privateKeyInfo(privateKeySource); { uint32_t versionNum; BERDecodeUnsigned<uint32_t>(privateKeyInfo, versionNum, INTEGER); BERSequenceDecoder sequenceDecoder(privateKeyInfo); { Oid keyTypeOid; keyTypeOid.decode(sequenceDecoder); if (keyTypeOid == oid::RSA) publicKeyType = KeyType::RSA; else if (keyTypeOid == oid::ECDSA) publicKeyType = KeyType::EC; else return false; // Unsupported key type; } } // derive public key OBufferStream publicKeyOs; try { switch (publicKeyType) { case KeyType::RSA: { RSA::PrivateKey privateKey; privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref()); RSAFunction publicKey(privateKey); FileSink publicKeySink(publicKeyOs); publicKey.DEREncode(publicKeySink); publicKeySink.MessageEnd(); break; } case KeyType::EC: { ECDSA<ECP, SHA256>::PrivateKey privateKey; privateKey.Load(StringStore(privateKeyOs.buf()->buf(), privateKeyOs.buf()->size()).Ref()); ECDSA<ECP, SHA256>::PublicKey publicKey; privateKey.MakePublicKey(publicKey); publicKey.AccessGroupParameters().SetEncodeAsOID(true); FileSink publicKeySink(publicKeyOs); publicKey.DEREncode(publicKeySink); publicKeySink.MessageEnd(); break; } default: return false; } } catch (const CryptoPP::Exception& e) { return false; } if (!importPublicKeyPkcs1IntoTpm(keyName, publicKeyOs.buf()->buf(), publicKeyOs.buf()->size())) return false; return true; }
const byte * CRYPTOPP_API GetActualMacAndLocation(unsigned int &macSize, unsigned int &fileLocation) { macSize = (unsigned int)g_actualMac.size(); fileLocation = g_macFileLocation; return g_actualMac; }
void DL_PrivateKey_EC<EC>::BERDecodeKey2(BufferedTransformation &bt, bool parametersPresent, unsigned int size) { BERSequenceDecoder seq(bt); word32 version; BERDecodeUnsigned<word32>(seq, version, INTEGER, 1, 1); // check version BERGeneralDecoder dec(seq, OCTET_STRING); if (!dec.IsDefiniteLength()) BERDecodeError(); Integer x; x.Decode(dec, dec.RemainingLength()); dec.MessageEnd(); if (!parametersPresent && seq.PeekByte() != (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) BERDecodeError(); if (!seq.EndReached() && seq.PeekByte() == (CONTEXT_SPECIFIC | CONSTRUCTED | 0)) { BERGeneralDecoder parameters(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 0); AccessGroupParameters().BERDecode(parameters); parameters.MessageEnd(); } if (!seq.EndReached()) { // skip over the public element SecByteBlock subjectPublicKey; unsigned int unusedBits; BERGeneralDecoder publicKey(seq, CONTEXT_SPECIFIC | CONSTRUCTED | 1); BERDecodeBitString(publicKey, subjectPublicKey, unusedBits); publicKey.MessageEnd(); Element Q; if (!(unusedBits == 0 && GetGroupParameters().GetCurve().DecodePoint(Q, subjectPublicKey, subjectPublicKey.size()))) BERDecodeError(); } seq.MessageEnd(); SetPrivateExponent(x); }
int main() { string key; unsigned int limit; int flag; cout << "Input key(32Byte from [0-9a-f]):"; cin >> key; cout << "Input upper limit:"; cin >> limit; StringSource ss(key, true, new HexDecoder); SecByteBlock bkey((size_t)ss.MaxRetrievable()); ss.Get(bkey, bkey.size()); ECB_Mode<AES>::Encryption aes(bkey, bkey.size()); ECB_Mode<AES>::Encryption aes1(bkey, bkey.size()); SecByteBlock *outputsbb; for(unsigned int i = 0; i < limit; i ++) { const byte *pi = (const byte *)&i; flag = 0; StreamTransformationFilter *stf = new StreamTransformationFilter(aes); StringSource outputss(pi, (size_t)sizeof(int)/sizeof(byte), true, stf); outputsbb = new SecByteBlock((size_t)outputss.MaxRetrievable()); outputss.Get(*outputsbb, outputsbb->size()); if(*((unsigned int *)(outputsbb->BytePtr())) < limit && *((unsigned int *)(outputsbb->BytePtr()) + 4) == 0 && *((unsigned int *)(outputsbb->BytePtr()) + 8) == 0 && *((unsigned int *)(outputsbb->BytePtr()) + 12) == 0) { flag = 1; } while(!flag) { StreamTransformationFilter *stf1 = new StreamTransformationFilter(aes1); StringSource outputss1(*outputsbb, outputsbb->size(), true, stf1); delete outputsbb; outputsbb = new SecByteBlock((size_t)outputss1.MaxRetrievable()); outputss1.Get(*outputsbb, outputsbb->size()); if(*((unsigned int *)(outputsbb->BytePtr())) < limit && *((unsigned int *)(outputsbb->BytePtr()) + 4) == 0 && *((unsigned int *)(outputsbb->BytePtr()) + 8) == 0 && *((unsigned int *)(outputsbb->BytePtr()) + 12) == 0) { flag = 1; cout << i << ": " << *((unsigned int *)(outputsbb->BytePtr())) << endl; } } delete outputsbb; } return 0; }
void PEM_NextObject(BufferedTransformation& src, BufferedTransformation& dest, bool trimTrailing) { if(!src.AnyRetrievable()) return; // We have four things to find: // 1. -----BEGIN (the leading begin) // 2. ----- (the trailing dashes) // 3. -----END (the leading end) // 4. ----- (the trailing dashes) // Once we parse something that purports to be PEM encoded, another routine // will have to look for something particular, like a RSA key. We *will* // inadvertently parse garbage, like -----BEGIN FOO BAR-----. It will // be caught later when a PEM_Load routine is called. static const size_t BAD_IDX = PEM_INVALID; // We use iterators for the search. However, an interator is invalidated // after each insert that grows the container. So we save indexes // from begin() to speed up searching. On each iteration, we simply // reinitialize them. SecByteBlock::const_iterator it; size_t idx1 = BAD_IDX, idx2 = BAD_IDX, idx3 = BAD_IDX, idx4 = BAD_IDX; // The idea is to read chunks in case there are multiple keys or // paramters in a BufferedTransformation. So we use CopyTo to // extract what we are interested in. We don't take anything // out of the BufferedTransformation (yet). // We also use indexes because the iterator will be invalidated // when we append to the ByteQueue. Even though the iterator // is invalid, `accum.begin() + index` will be valid. // Reading 8 or 10 lines at a time is an optimization from testing // against cacerts.pem. The file has 153 certs, so its a good test. // +2 to allow for CR + LF line endings. There's no guarantee a line // will be present, or it will be RFC1421_LINE_BREAK in size. static const size_t READ_SIZE = (RFC1421_LINE_BREAK + 1) * 10; static const size_t REWIND = max(SBB_PEM_BEGIN.size(), SBB_PEM_END.size()) + 2; SecByteBlock accum; size_t idx = 0, next = 0; size_t available = src.MaxRetrievable(); while(available) { // How much can we read? const size_t size = std::min(available, READ_SIZE); // Ideally, we would only scan the line we are reading. However, // we need to rewind a bit in case a token spans the previous // block and the block we are reading. But we can't rewind // into a previous index. Once we find an index, the variable // next is set to it. Hence the reason for the max() if(idx > REWIND) { const size_t x = idx - REWIND; next = max(next, x); } #if 0 // Next should be less than index by 10 or so std::cout << " Index: " << idx << std::endl; std::cout << " Next: " << next << std::endl; #endif // We need a temp queue to use CopyRangeTo. We have to use it // because there's no Peek that allows us to peek a range. ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(size)); const size_t offset = accum.size(); accum.Grow(offset + size); tq.Get(accum.data() + offset, size); // Adjust sizes idx += size; available -= size; // Locate '-----BEGIN' if(idx1 == BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_BEGIN.begin(), SBB_PEM_BEGIN.end()); if(it == accum.end()) continue; idx1 = it - accum.begin(); next = idx1 + SBB_PEM_BEGIN.size(); } // Locate '-----' if(idx2 == BAD_IDX && idx1 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end()); if(it == accum.end()) continue; idx2 = it - accum.begin(); next = idx2 + SBB_PEM_TAIL.size(); } // Locate '-----END' if(idx3 == BAD_IDX && idx2 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_END.begin(), SBB_PEM_END.end()); if(it == accum.end()) continue; idx3 = it - accum.begin(); next = idx3 + SBB_PEM_END.size(); } // Locate '-----' if(idx4 == BAD_IDX && idx3 != BAD_IDX) { it = search(accum.begin() + next, accum.end(), SBB_PEM_TAIL.begin(), SBB_PEM_TAIL.end()); if(it == accum.end()) continue; idx4 = it - accum.begin(); next = idx4 + SBB_PEM_TAIL.size(); } } // Did we find `-----BEGIN XXX-----` (RFC 1421 calls this pre-encapsulated boundary)? if(idx1 == BAD_IDX || idx2 == BAD_IDX) throw InvalidDataFormat("PEM_NextObject: could not locate boundary header"); // Did we find `-----END XXX-----` (RFC 1421 calls this post-encapsulated boundary)? if(idx3 == BAD_IDX || idx4 == BAD_IDX) throw InvalidDataFormat("PEM_NextObject: could not locate boundary footer"); // *IF* the trailing '-----' occurred in the last 5 bytes in accum, then we might miss the // End of Line. We need to peek 2 more bytes if available and append them to accum. if(available >= 2) { ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(2)); const size_t offset = accum.size(); accum.Grow(offset + 2); tq.Get(accum.data() + offset, 2); } else if(available == 1) { ByteQueue tq; src.CopyRangeTo(tq, static_cast<lword>(idx), static_cast<lword>(1)); const size_t offset = accum.size(); accum.Grow(offset + 1); tq.Get(accum.data() + offset, 1); } // Final book keeping const byte* ptr = accum.begin() + idx1; const size_t used = idx4 + SBB_PEM_TAIL.size(); const size_t len = used - idx1; // Include one CR/LF if its available in the accumulator next = idx1 + len; size_t adjust = 0; if(next < accum.size()) { byte c1 = accum[next]; byte c2 = 0; if(next + 1 < accum.size()) c2 = accum[next + 1]; // Longest match first if(c1 == '\r' && c2 == '\n') adjust = 2; else if(c1 == '\r' || c1 == '\n') adjust = 1; } dest.Put(ptr, len + adjust); dest.MessageEnd(); src.Skip(used + adjust); if(trimTrailing) { while (src.AnyRetrievable()) { byte b; src.Peek(b); if(!isspace(b)) break; src.Skip(1); } } }
void PEM_StripEncapsulatedHeader(BufferedTransformation& src, BufferedTransformation& dest, EncapsulatedHeader& header) { if(!src.AnyRetrievable()) return; SecByteBlock line, ending; size_t size = 0; // The first line *must* be Proc-Type. Ensure we read it before dropping into the loop. size = PEM_ReadLine(src, line, ending); if(size == 0 || line.empty()) throw InvalidDataFormat("PEM_StripEncapsulatedHeader: failed to locate Proc-Type"); SecByteBlock field = GetControlField(line); if(field.empty()) throw InvalidDataFormat("PEM_StripEncapsulatedHeader: failed to locate Proc-Type"); if(0 != CompareNoCase(field, SBB_PROC_TYPE)) throw InvalidDataFormat("PEM_StripEncapsulatedHeader: failed to locate Proc-Type"); line = GetControlFieldData(line); string tline(reinterpret_cast<const char*>(line.data()),line.size()); PEM_ParseVersion(tline, header.m_version); if(header.m_version != "4") throw NotImplemented("PEM_StripEncapsulatedHeader: encryption version " + header.m_version + " not supported"); PEM_ParseOperation(tline, header.m_operation); if(header.m_operation != "ENCRYPTED") throw NotImplemented("PEM_StripEncapsulatedHeader: operation " + header.m_operation + " not supported"); // Next, we have to read until the first empty line while(true) { if(!src.AnyRetrievable()) break; // End Of Buffer size = PEM_ReadLine(src, line, ending); if(size == 0) break; // End Of Buffer if(line.size() == 0) break; // size is non-zero; empty line field = GetControlField(line); if(0 == CompareNoCase(field, SBB_DEK_INFO)) { line = GetControlFieldData(line); tline = string(reinterpret_cast<const char*>(line.data()),line.size()); PEM_ParseAlgorithm(tline, header.m_algorithm); PEM_ParseIV(tline, header.m_iv); continue; } if(0 == CompareNoCase(field, SBB_CONTENT_DOMAIN)) { // Silently ignore // Content-Domain: RFC822 continue; } if(!field.empty()) { const char* ptr = (char*)field.begin(); size_t len = field.size(); string m(ptr, len); throw NotImplemented("PEM_StripEncapsulatedHeader: " + m + " not supported"); } } if(header.m_algorithm.empty()) throw InvalidArgument("PEM_StripEncapsulatedHeader: no encryption algorithm"); if(header.m_iv.empty()) throw InvalidArgument("PEM_StripEncapsulatedHeader: no IV present"); // After the empty line is the encapsulated text. Transfer it to the destination. src.TransferTo(dest); }
size_t PEM_ReadLine(BufferedTransformation& source, SecByteBlock& line, SecByteBlock& ending) { if(!source.AnyRetrievable()) { line.New(0); ending.New(0); return 0; } ByteQueue temp; while(source.AnyRetrievable()) { byte b; if(!source.Get(b)) throw Exception(Exception::OTHER_ERROR, "PEM_ReadLine: failed to read byte"); // LF ? if(b == '\n') { ending = LF; break; } // CR ? if(b == '\r') { // CRLF ? if(source.AnyRetrievable() && source.Peek(b)) { if(b == '\n') { source.Skip(1); ending = CRLF; break; } } ending = CR; break; } // Not End-of-Line, accumulate it. temp.Put(b); } if(temp.AnyRetrievable()) { line.Grow(temp.MaxRetrievable()); temp.Get(line.data(), line.size()); } else { line.New(0); ending.New(0); } // We return a line stripped of CRs and LFs. However, we return the actual number of // of bytes processed, including the CR and LF. A return of 0 means nothing was read. // A return of 1 means an empty line was read (CR or LF). A return of 2 could // mean an empty line was read (CRLF), or could mean 1 character was read. In // any case, line will hold whatever was parsed. return line.size() + ending.size(); }