Add support for Ed25519 seeds encoded using ripple-lib:

When Ed25519 support was added to ripple-lib, a way to specify
whether a seed should be used to derive a "classic" secp256k1
keypair or a "new" Ed25519 keypair was needed, and the
requirements were that:

1. previously seeds would, correctly, generate a secp256k1
   keypair.
2. users would not have to know about whether the seed was
   used to generate a secp256k1 or an Ed25519 keypair.

To address these requirements, the decision was made to encode
the type of key within the seed and a custom encoding was
designed.

The encoding uses a token type of 1 and prefixes the actual
seed with a 2 byte header, selected to ensure that all such
keypairs will, when encoded, begin with the string "sEd".

This custom encoding is non-standard and was not previously
documented; as a result, it is not widely supported and other
sofware may treat such keys as invalid. This can make it
difficult for users that have stored such a seed to use
wallets or other tooling that is not based on ripple-lib.

This commit adds support to rippled for automatically
detecting and properly handling such seeds.
This commit is contained in:
Nik Bougalis
2018-10-22 23:30:37 -07:00
parent 77462b8f72
commit 513b1dd194
8 changed files with 221 additions and 83 deletions

View File

@@ -107,7 +107,6 @@ public:
BEAST_EXPECT(! contains_error (result));
BEAST_EXPECT(result.isMember (jss::account_id));
BEAST_EXPECT(result.isMember (jss::master_key));
BEAST_EXPECT(result.isMember (jss::master_seed));
BEAST_EXPECT(result.isMember (jss::master_seed_hex));
BEAST_EXPECT(result.isMember (jss::public_key));
@@ -133,7 +132,6 @@ public:
BEAST_EXPECT(! contains_error (result));
expectEquals (result[jss::account_id], s.account_id);
expectEquals (result[jss::master_key], s.master_key);
expectEquals (result[jss::master_seed], s.master_seed);
expectEquals (result[jss::master_seed_hex], s.master_seed_hex);
expectEquals (result[jss::public_key], s.public_key);
@@ -709,6 +707,86 @@ public:
}
}
void testRippleLibEd25519()
{
testcase ("ripple-lib encoded Ed25519 keys");
auto test = [this](char const* seed, char const* addr)
{
{
Json::Value params;
Json::Value error;
params[jss::passphrase] = seed;
auto ret = keypairForSignature(params, error);
BEAST_EXPECT(!contains_error(error));
BEAST_EXPECT(ret.first.size() != 0);
BEAST_EXPECT(toBase58(calcAccountID(ret.first)) == addr);
}
{
Json::Value params;
Json::Value error;
params[jss::key_type] = "secp256k1";
params[jss::passphrase] = seed;
auto ret = keypairForSignature(params, error);
BEAST_EXPECT(contains_error(error));
BEAST_EXPECT(error[jss::error_message] ==
"Specified seed is for an Ed25519 wallet.");
}
{
Json::Value params;
Json::Value error;
params[jss::key_type] = "ed25519";
params[jss::seed] = seed;
auto ret = keypairForSignature(params, error);
BEAST_EXPECT(!contains_error(error));
BEAST_EXPECT(ret.first.size() != 0);
BEAST_EXPECT(toBase58(calcAccountID(ret.first)) == addr);
}
{
Json::Value params;
Json::Value error;
params[jss::key_type] = "secp256k1";
params[jss::seed] = seed;
auto ret = keypairForSignature(params, error);
BEAST_EXPECT(contains_error(error));
BEAST_EXPECT(error[jss::error_message] ==
"Specified seed is for an Ed25519 wallet.");
}
};
test("sEdVWZmeUDgQdMEFKTK9kYVX71FKB7o", "r34XnDB2zS11NZ1wKJzpU1mjWExGVugTaQ");
test("sEd7zJoVnqg1FxB9EuaHC1AB5UPfHWz", "rDw51qRrBEeMw7Na1Nh79LN7HYZDo7nZFE");
test("sEdSxVntbihdLyabbfttMCqsaaucVR9", "rwiyBDfAYegXZyaQcN2L1vAbKRYn2wNFMq");
test("sEdSVwJjEXTYCztqDK4JD9WByH3otDX", "rQJ4hZzNGkLQhLtKPCmu1ywEw1ai2vgUJN");
test("sEdV3jXjKuUoQTSr1Rb4yw8Kyn9r46U", "rERRw2Pxbau4tevE61V5vZUwD7Rus5Y6vW");
test("sEdVeUZjuYT47Uy51FQCnzivsuWyiwB", "rszewT5gRjUgWNEmnfMjvVYzJCkhvWY32i");
test("sEd7MHTewdw4tFYeS7rk7XT4qHiA9jH", "rBB2rvnf4ztwjgNhinFXQJ91nAZjkFgR3p");
test("sEd7A5jFBSdWbNeKGriQvLr1thBScJh", "rLAXz8Nz7aDivz7PwThsLFqaKrizepNCdA");
test("sEdVPU9M2uyzVNT4Yb5Dn4tUtYjbFAw", "rHbHRFPCxD5fnn98TBzsQHJ7SsRq7eHkRj");
test("sEdVfF2zhAmS8gfMYzJ4yWBMeR4BZKc", "r9PsneKHcAE7kUfiTixomM5Mnwi28tCc7h");
test("sEdTjRtcsQkwthDXUSLi9DHNyJcR8GW", "rM4soF4XS3wZrmLurvE6ZmudG16Lk5Dur5");
test("sEdVNKeu1Lhpfh7Nf6tRDbxnmMyZ4Dv", "r4ZwJxq6FDtWjapDtCGhjG6mtNm1nWdJcD");
test("sEd7bK4gf5BHJ1WbaEWx8pKMA9MLHpC", "rD6tnn51m4o1uXeEK9CFrZ3HR7DcFhiYnp");
test("sEd7jCh3ppnQMsLdGcZ6TZayZaHhBLg", "rTcBkiRQ1EfFQ4FCCwqXNHpn1yUTAACkj");
test("sEdTFJezurQwSJAbkLygj2gQXBut2wh", "rnXaMacNbRwcJddbbPbqdcpSUQcfzFmrR8");
test("sEdSWajfQAAWFuDvVZF3AiGucReByLt", "rBJtow6V3GTdsWMamrxetRDwWs6wwTxcKa");
}
void run() override
{
testKeyType (boost::none, secp256k1_strings);
@@ -721,6 +799,9 @@ public:
testKeypairForSignature (std::string("secp256k1"), secp256k1_strings);
testKeypairForSignature (std::string("ed25519"), ed25519_strings);
testKeypairForSignature (std::string("secp256k1"), strong_brain_strings);
testRippleLibEd25519();
testKeypairForSignatureErrors ();
}
};