///////////////////////////////////////////////////////////////////////////// // Deterministically generate new public key using a chaincode SecureBinaryData CryptoECDSA::ComputeChainedPublicKey( SecureBinaryData const & binPubKey, SecureBinaryData const & chainCode, SecureBinaryData* multiplierOut) { if(CRYPTO_DEBUG) { cout << "ComputeChainedPUBLICKey:" << endl; cout << " BinPub: " << binPubKey.toHexStr() << endl; cout << " BinChn: " << chainCode.toHexStr() << endl; } static SecureBinaryData SECP256K1_ORDER_BE = SecureBinaryData::CreateFromHex( "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141"); // Added extra entropy to chaincode by xor'ing with hash256 of pubkey BinaryData chainMod = binPubKey.getHash256(); BinaryData chainOrig = chainCode.getRawCopy(); BinaryData chainXor(32); for(uint8_t i=0; i<8; i++) { uint8_t offset = 4*i; *(uint32_t*)(chainXor.getPtr()+offset) = *(uint32_t*)( chainMod.getPtr()+offset) ^ *(uint32_t*)(chainOrig.getPtr()+offset); } // Parse the chaincode as a big-endian integer CryptoPP::Integer mult; mult.Decode(chainXor.getPtr(), chainXor.getSize(), UNSIGNED); // "new" init as "old", to make sure it's initialized on the correct curve BTC_PUBKEY oldPubKey = ParsePublicKey(binPubKey); BTC_PUBKEY newPubKey = ParsePublicKey(binPubKey); // Let Crypto++ do the EC math for us, serialize the new public key newPubKey.SetPublicElement( oldPubKey.ExponentiatePublicElement(mult) ); if(multiplierOut != NULL) (*multiplierOut) = SecureBinaryData(chainXor); //LOGINFO << "Computed new chained public key using:"; //LOGINFO << " Public key: " << binPubKey.toHexStr().c_str(); //LOGINFO << " PubKeyHash: " << chainMod.toHexStr().c_str(); //LOGINFO << " Chaincode: " << chainOrig.toHexStr().c_str(); //LOGINFO << " Multiplier: " << chainXor.toHexStr().c_str(); return CryptoECDSA::SerializePublicKey(newPubKey); }
bool CryptoECDSA::CheckPubPrivKeyMatch(SecureBinaryData const & privKey32, SecureBinaryData const & pubKey65) { if(CRYPTO_DEBUG) { cout << "CheckPubPrivKeyMatch:" << endl; cout << " BinPrv: " << privKey32.toHexStr() << endl; cout << " BinPub: " << pubKey65.toHexStr() << endl; } BTC_PRIVKEY privKey = ParsePrivateKey(privKey32); BTC_PUBKEY pubKey = ParsePublicKey(pubKey65); return CheckPubPrivKeyMatch(privKey, pubKey); }
bool CryptoECDSA::VerifyData(SecureBinaryData const & binMessage, SecureBinaryData const & binSignature, SecureBinaryData const & pubkey65B) { if(CRYPTO_DEBUG) { cout << "VerifyData:" << endl; cout << " BinMsg: " << binMessage.toHexStr() << endl; cout << " BinSig: " << binSignature.toHexStr() << endl; cout << " BinPub: " << pubkey65B.toHexStr() << endl; } BTC_PUBKEY cppPubKey = ParsePublicKey(pubkey65B); return VerifyData(binMessage, binSignature, cppPubKey); }
BTC_PUBKEY CryptoECDSA::ParsePublicKey(SecureBinaryData const & pubKey65B) { SecureBinaryData pubXbin(pubKey65B.getSliceRef( 1,32)); SecureBinaryData pubYbin(pubKey65B.getSliceRef(33,32)); return ParsePublicKey(pubXbin, pubYbin); }
/** * Main function. * * Checks certificate and certificate revocation list * * @param[in] argc An integer argument count of the command line arguments * @param[in] argv An argument vector of the command line arguments * * @return[out] an integer 0 upon exit success */ int main(int argc, char *argv[]) { int isCrt = 0; const char *testedFileName = 0; const char *caCrtFileName = 0; // Parse command line arguments int opt; while ((opt = getopt(argc, argv, "c:f:s:")) != -1) { switch (opt) { case 'c': if (!strcmp(COMMAND_CRT, optarg)) { isCrt = 1; } else if (!strcmp(COMMAND_CRL, optarg)) { isCrt = 0; } else { printf("Wrong command(-c)!\n"); Usage(); exit(0); } break; case 'f': testedFileName = optarg; break; case 's': caCrtFileName = optarg; break; default: Usage(); exit(0); } } if (testedFileName == NULL || caCrtFileName == NULL) { printf("Wrong file name\n"); Usage(); exit(0); } // main ByteArray testedCrtCrl = BYTE_ARRAY_INITIALIZER; // Could contain either Certificate or CRL ByteArray caCrt = BYTE_ARRAY_INITIALIZER; // Copy DER files, specified in command line to ByteArray structure FileToByteArray(testedFileName, &testedCrtCrl); FileToByteArray(caCrtFileName, &caCrt); // Decoding CA certificate CertificateX509 caCrtStuct = CERTIFICATE_X509_INITIALIZER; PKIError errorCode = DecodeCertificate(caCrt, &caCrtStuct); if (errorCode != PKI_SUCCESS) { printf("Unable to decode CA Certificate!\n"); printf("Error code: %d\n", errorCode); } ByteArray caPublicKey = BYTE_ARRAY_INITIALIZER; // Verifies Certificate or CRL depending on request if (isCrt) { errorCode = CheckCertificate(testedCrtCrl, caCrtStuct.pubKey); } else { caPublicKey.data = caCrtStuct.pubKey.data; caPublicKey.len = caCrtStuct.pubKey.len; ParsePublicKey(&caPublicKey); CertificateList crlStruct = CRL_INITIALIZER; errorCode = DecodeCertificateList(testedCrtCrl, &crlStruct, caPublicKey); } if (errorCode == PKI_SUCCESS) { printf("Verification SUCCESS!\n"); } else { printf("Verification FAILED!\n"); printf("Error code: %d\n", errorCode); } // Free the allocated memory OICFree(testedCrtCrl.data); OICFree(caCrt.data); return 0; }