STValidation::STValidation (SerialIter& sit, bool checkSignature) : STObject (getFormat (), sit, sfValidation) { mNodeID = calcNodeID( PublicKey(makeSlice (getFieldVL (sfSigningPubKey)))); assert (mNodeID.isNonZero ()); if (checkSignature && !isValid ()) { JLOG (debugLog().error()) << "Invalid validation" << getJson (0); Throw<std::runtime_error> ("Invalid validation"); } }
STValidation::STValidation ( uint256 const& ledgerHash, NetClock::time_point signTime, PublicKey const& publicKey, bool isFull) : STObject (getFormat (), sfValidation) , mSeen (signTime) { // Does not sign setFieldH256 (sfLedgerHash, ledgerHash); setFieldU32 (sfSigningTime, signTime.time_since_epoch().count()); setFieldVL (sfSigningPubKey, publicKey.slice()); mNodeID = calcNodeID(publicKey); assert (mNodeID.isNonZero ()); if (isFull) setFlag (kFullFlag); }
void testKeypairGenerationAndSigning () { std::string const message1 = "http://www.ripple.com"; std::string const message2 = "https://www.ripple.com"; { testcase ("Node keypair generation & signing (secp256k1)"); auto const secretKey = generateSecretKey ( KeyType::secp256k1, generateSeed ("masterpassphrase")); auto const publicKey = derivePublicKey ( KeyType::secp256k1, secretKey); BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PUBLIC, publicKey) == "n94a1u4jAz288pZLtw6yFWVbi89YamiC6JBXPVUj5zmExe5fTVg9"); BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PRIVATE, secretKey) == "pnen77YEeUd4fFKG7iycBWcwKpTaeFRkW2WFostaATy1DSupwXe"); BEAST_EXPECT(to_string(calcNodeID(publicKey)) == "7E59C17D50F5959C7B158FEC95C8F815BF653DC8"); auto sig = sign (publicKey, secretKey, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); BEAST_EXPECT(verify (publicKey, makeSlice(message1), sig)); // Correct public key but wrong message BEAST_EXPECT(!verify (publicKey, makeSlice(message2), sig)); // Verify with incorrect public key { auto const otherPublicKey = derivePublicKey ( KeyType::secp256k1, generateSecretKey ( KeyType::secp256k1, generateSeed ("otherpassphrase"))); BEAST_EXPECT(!verify (otherPublicKey, makeSlice(message1), sig)); } // Correct public key but wrong signature { // Slightly change the signature: if (auto ptr = sig.data()) ptr[sig.size() / 2]++; BEAST_EXPECT(!verify (publicKey, makeSlice(message1), sig)); } } { testcase ("Node keypair generation & signing (ed25519)"); auto const secretKey = generateSecretKey ( KeyType::ed25519, generateSeed ("masterpassphrase")); auto const publicKey = derivePublicKey ( KeyType::ed25519, secretKey); BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PUBLIC, publicKey) == "nHUeeJCSY2dM71oxM8Cgjouf5ekTuev2mwDpc374aLMxzDLXNmjf"); BEAST_EXPECT(toBase58(TokenType::TOKEN_NODE_PRIVATE, secretKey) == "paKv46LztLqK3GaKz1rG2nQGN6M4JLyRtxFBYFTw4wAVHtGys36"); BEAST_EXPECT(to_string(calcNodeID(publicKey)) == "AA066C988C712815CC37AF71472B7CBBBD4E2A0A"); auto sig = sign (publicKey, secretKey, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); BEAST_EXPECT(verify (publicKey, makeSlice(message1), sig)); // Correct public key but wrong message BEAST_EXPECT(!verify (publicKey, makeSlice(message2), sig)); // Verify with incorrect public key { auto const otherPublicKey = derivePublicKey ( KeyType::ed25519, generateSecretKey ( KeyType::ed25519, generateSeed ("otherpassphrase"))); BEAST_EXPECT(!verify (otherPublicKey, makeSlice(message1), sig)); } // Correct public key but wrong signature { // Slightly change the signature: if (auto ptr = sig.data()) ptr[sig.size() / 2]++; BEAST_EXPECT(!verify (publicKey, makeSlice(message1), sig)); } } { testcase ("Account keypair generation & signing (secp256k1)"); auto const keyPair = generateKeyPair ( KeyType::secp256k1, generateSeed ("masterpassphrase")); BEAST_EXPECT(toBase58(calcAccountID(keyPair.first)) == "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh"); BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, keyPair.first) == "aBQG8RQAzjs1eTKFEAQXr2gS4utcDiEC9wmi7pfUPTi27VCahwgw"); BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_SECRET, keyPair.second) == "p9JfM6HHi64m6mvB6v5k7G2b1cXzGmYiCNJf6GHPKvFTWdeRVjh"); auto sig = sign (keyPair.first, keyPair.second, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); BEAST_EXPECT(verify (keyPair.first, makeSlice(message1), sig)); // Correct public key but wrong message BEAST_EXPECT(!verify (keyPair.first, makeSlice(message2), sig)); // Verify with incorrect public key { auto const otherKeyPair = generateKeyPair ( KeyType::secp256k1, generateSeed ("otherpassphrase")); BEAST_EXPECT(!verify (otherKeyPair.first, makeSlice(message1), sig)); } // Correct public key but wrong signature { // Slightly change the signature: if (auto ptr = sig.data()) ptr[sig.size() / 2]++; BEAST_EXPECT(!verify (keyPair.first, makeSlice(message1), sig)); } } { testcase ("Account keypair generation & signing (ed25519)"); auto const keyPair = generateKeyPair ( KeyType::ed25519, generateSeed ("masterpassphrase")); BEAST_EXPECT(to_string(calcAccountID(keyPair.first)) == "rGWrZyQqhTp9Xu7G5Pkayo7bXjH4k4QYpf"); BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_PUBLIC, keyPair.first) == "aKGheSBjmCsKJVuLNKRAKpZXT6wpk2FCuEZAXJupXgdAxX5THCqR"); BEAST_EXPECT(toBase58(TokenType::TOKEN_ACCOUNT_SECRET, keyPair.second) == "pwDQjwEhbUBmPuEjFpEG75bFhv2obkCB7NxQsfFxM7xGHBMVPu9"); auto sig = sign (keyPair.first, keyPair.second, makeSlice(message1)); BEAST_EXPECT(sig.size() != 0); BEAST_EXPECT(verify (keyPair.first, makeSlice(message1), sig)); // Correct public key but wrong message BEAST_EXPECT(!verify (keyPair.first, makeSlice(message2), sig)); // Verify with incorrect public key { auto const otherKeyPair = generateKeyPair ( KeyType::ed25519, generateSeed ("otherpassphrase")); BEAST_EXPECT(!verify (otherKeyPair.first, makeSlice(message1), sig)); } // Correct public key but wrong signature { // Slightly change the signature: if (auto ptr = sig.data()) ptr[sig.size() / 2]++; BEAST_EXPECT(!verify (keyPair.first, makeSlice(message1), sig)); } } }
void run() override { beast::Journal j; // Keys/ID when using [validation_seed] SecretKey const seedSecretKey = generateSecretKey(KeyType::secp256k1, *parseBase58<Seed>(seed)); PublicKey const seedPublicKey = derivePublicKey(KeyType::secp256k1, seedSecretKey); NodeID const seedNodeID = calcNodeID(seedPublicKey); // Keys when using [validation_token] auto const tokenSecretKey = *parseBase58<SecretKey>( TokenType::NodePrivate, tokenSecretStr); auto const tokenPublicKey = derivePublicKey(KeyType::secp256k1, tokenSecretKey); auto const m = Manifest::make_Manifest( base64_decode(tokenManifest)); BEAST_EXPECT(m); NodeID const tokenNodeID = calcNodeID(m->masterKey); { // No config -> no key but valid Config c; ValidatorKeys k{c, j}; BEAST_EXPECT(k.publicKey.size() == 0); BEAST_EXPECT(k.manifest.empty()); BEAST_EXPECT(!k.configInvalid()); } { // validation seed section -> empty manifest and valid seeds Config c; c.section(SECTION_VALIDATION_SEED).append(seed); ValidatorKeys k{c, j}; BEAST_EXPECT(k.publicKey == seedPublicKey); BEAST_EXPECT(k.secretKey == seedSecretKey); BEAST_EXPECT(k.nodeID == seedNodeID); BEAST_EXPECT(k.manifest.empty()); BEAST_EXPECT(!k.configInvalid()); } { // validation seed bad seed -> invalid Config c; c.section(SECTION_VALIDATION_SEED).append("badseed"); ValidatorKeys k{c, j}; BEAST_EXPECT(k.configInvalid()); BEAST_EXPECT(k.publicKey.size() == 0); BEAST_EXPECT(k.manifest.empty()); } { // validator token Config c; c.section(SECTION_VALIDATOR_TOKEN).append(tokenBlob); ValidatorKeys k{c, j}; BEAST_EXPECT(k.publicKey == tokenPublicKey); BEAST_EXPECT(k.secretKey == tokenSecretKey); BEAST_EXPECT(k.nodeID == tokenNodeID); BEAST_EXPECT(k.manifest == tokenManifest); BEAST_EXPECT(!k.configInvalid()); } { // invalid validator token Config c; c.section(SECTION_VALIDATOR_TOKEN).append("badtoken"); ValidatorKeys k{c, j}; BEAST_EXPECT(k.configInvalid()); BEAST_EXPECT(k.publicKey.size() == 0); BEAST_EXPECT(k.manifest.empty()); } { // Cannot specify both Config c; c.section(SECTION_VALIDATION_SEED).append(seed); c.section(SECTION_VALIDATOR_TOKEN).append(tokenBlob); ValidatorKeys k{c, j}; BEAST_EXPECT(k.configInvalid()); BEAST_EXPECT(k.publicKey.size() == 0); BEAST_EXPECT(k.manifest.empty()); } { // Token manifest and private key must match Config c; c.section(SECTION_VALIDATOR_TOKEN).append(invalidTokenBlob); ValidatorKeys k{c, j}; BEAST_EXPECT(k.configInvalid()); BEAST_EXPECT(k.publicKey.size() == 0); BEAST_EXPECT(k.manifest.empty()); } }