From 3eedd13894897111a9bebf5c6d299531a3f47bbf Mon Sep 17 00:00:00 2001 From: chuck-h Date: Thu, 25 Apr 2024 21:21:48 -0700 Subject: [PATCH] fix eosdart serialize/deserialize of public keys (#1935) * fix eosdart serialize/deserialize of public keys * eosdart: serialize/deserialize methods for all key types; add unit test * eosdart deserialize: fix bug in signature type (note: not in unit test) * eosdart deserialize signature oops! --------- Co-authored-by: NIK --- lib/crypto/eosdart/src/numeric.dart | 25 +++- lib/crypto/eosdart/src/serialize.dart | 6 +- test/utils/serialize_test.dart | 160 ++++++++++++++++++++++++++ 3 files changed, 185 insertions(+), 6 deletions(-) create mode 100644 test/utils/serialize_test.dart diff --git a/lib/crypto/eosdart/src/numeric.dart b/lib/crypto/eosdart/src/numeric.dart index baa4c911f..c9c2e17e4 100644 --- a/lib/crypto/eosdart/src/numeric.dart +++ b/lib/crypto/eosdart/src/numeric.dart @@ -234,10 +234,25 @@ Uint8List digestSuffixRipemd160(Uint8List data, String suffix) { return dg.process(d); } +Uint8List digestSha256X2(Uint8List data) { + var dg = Digest("SHA-256"); + var d1 = dg.process(data); + dg.reset(); + return dg.process(d1); +} + IKey stringToKey(String s, KeyType type, int size, String suffix) { var whole = base58ToBinary(size + 4, s); - var result = IKey(type, whole); - var digest = digestSuffixRipemd160(result.data, suffix); + + var result; + var digest; + if (suffix == '') { + result = IKey(type, whole.sublist(1,size)); + digest = digestSha256X2(whole.sublist(0,size)); + } else { + result = IKey(type, whole.sublist(0,size)); + digest = digestSuffixRipemd160(result.data, suffix).toList(); + } if (digest[0] != whole[size + 0] || digest[1] != whole[size + 1] || digest[2] != whole[size + 2] || @@ -314,8 +329,10 @@ List convertLegacyPublicKeys(List keys) => IKey stringToPrivateKey(String s) { if (s.substring(0, 7) == 'PVT_R1_') { return stringToKey(s.substring(7), KeyType.r1, privateKeyDataSize, 'R1'); + } else if (s.substring(0, 7) == 'PVT_K1_') { + return stringToKey(s.substring(7), KeyType.k1, privateKeyDataSize, 'K1'); } else { - throw 'unrecognized private key format'; + return stringToKey(s, KeyType.k1, privateKeyDataSize+1, ''); } } @@ -323,6 +340,8 @@ IKey stringToPrivateKey(String s) { String privateKeyToString(IKey key) { if (key.type == KeyType.r1) { return keyToString(key, 'R1', 'PVT_R1_'); + } else if (key.type == KeyType.k1) { + return keyToString(key, 'K1', 'PVT_K1_'); } else { throw 'unrecognized private key format'; } diff --git a/lib/crypto/eosdart/src/serialize.dart b/lib/crypto/eosdart/src/serialize.dart index e3e7eac0e..8fd2b7218 100644 --- a/lib/crypto/eosdart/src/serialize.dart +++ b/lib/crypto/eosdart/src/serialize.dart @@ -406,7 +406,7 @@ class SerialBuffer { String getPublicKey() { var type = get(); var data = getUint8List(numeric.publicKeyDataSize); - return numeric.publicKeyToString(numeric.IKey(type as numeric.KeyType, data)); + return numeric.publicKeyToString(numeric.IKey(numeric.KeyType.values[type], data)); } /// Append a private key */ @@ -420,7 +420,7 @@ class SerialBuffer { String getPrivateKey() { var type = get(); var data = getUint8List(numeric.privateKeyDataSize); - return numeric.privateKeyToString(numeric.IKey(type as numeric.KeyType, data)); + return numeric.privateKeyToString(numeric.IKey(numeric.KeyType.values[type], data)); } /// Append a signature */ @@ -434,7 +434,7 @@ class SerialBuffer { String getSignature() { var type = get(); var data = getUint8List(numeric.signatureDataSize); - return numeric.signatureToString(numeric.IKey(type as numeric.KeyType, data)); + return numeric.signatureToString(numeric.IKey(numeric.KeyType.values[type], data)); } } // SerialBuffer diff --git a/test/utils/serialize_test.dart b/test/utils/serialize_test.dart new file mode 100644 index 000000000..87ae5c151 --- /dev/null +++ b/test/utils/serialize_test.dart @@ -0,0 +1,160 @@ +import 'dart:typed_data'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:seeds/crypto/eosdart/src/serialize.dart'; + +const verbose = false; +void main() { + + group('public keys', () { + test('serialize k1 old style', () { + final keystring = 'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPublicKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [0, 2, 192, 222, 210, 188, 31, 19, 5, 251, 15, 170, 197, 230, 192, 62, + 227, 161, 146, 66, 52, 152, 84, 39, 182, 22, 124, 165, 105, 209, 61, + 244, 53, 207]); + }); + test('serialize k1 new style', () { + final keystring = 'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPublicKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [0, 2, 192, 222, 210, 188, 31, 19, 5, 251, 15, 170, 197, 230, 192, 62, + 227, 161, 146, 66, 52, 152, 84, 39, 182, 22, 124, 165, 105, 209, 61, + 244, 53, 207]); + }); + test('deserialize k1 new style', () { + final serialized = Uint8List.fromList([0, 2, 192, 222, 210, 188, 31, 19, + 5, 251, 15, 170, 197, 230, 192, 62, 227, 161, 146, 66, 52, 152, 84, 39, + 182, 22, 124, 165, 105, 209, 61, 244, 53, 207]); + final sb = new SerialBuffer(serialized); + final keystring = sb.getPublicKey(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(keystring, 'PUB_K1_6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5BoDq63'); + }); + test('serialize r1 new style', () { + final keystring = 'PUB_R1_6eMzJfDVWvzMTYAUWQ95JcpoY8vFL62pTFm6spim25n5wqtVWP'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPublicKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [1, 2, 231, 80, 174, 4, 190, 33, 189, 1, 48, 165, 223, 203, 242, + 125, 16, 95, 97, 223, 20, 206, 120, 17, 207, 107, 49, 24, 30, + 7, 140, 39, 8, 36]); + }); + test('deserialize r1 new style', () { + final serialized = Uint8List.fromList( + [1, 2, 231, 80, 174, 4, 190, 33, 189, 1, 48, 165, 223, 203, 242, + 125, 16, 95, 97, 223, 20, 206, 120, 17, 207, 107, 49, 24, 30, + 7, 140, 39, 8, 36]); + final sb = new SerialBuffer(serialized); + final keystring = sb.getPublicKey(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(keystring, 'PUB_R1_6eMzJfDVWvzMTYAUWQ95JcpoY8vFL62pTFm6spim25n5wqtVWP'); + }); + + }); + + group('private keys', () { + test('serialize k1 old style', () { + final keystring = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPrivateKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [0, 210, 101, 63, 247, 203, 178, 216, 255, 18, 154, 194, 126, 245, + 120, 28, 230, 139, 37, 88, 196, 26, 116, 175, 31, 45, 220, 166, 53, + 203, 238, 240, 125]); + }); + test('serialize k1 new style', () { + final keystring = 'PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPrivateKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [0, 210, 101, 63, 247, 203, 178, 216, 255, 18, 154, 194, 126, 245, + 120, 28, 230, 139, 37, 88, 196, 26, 116, 175, 31, 45, 220, 166, 53, + 203, 238, 240, 125]); + }); + test('deserialize k1 new style', () { + final serialized = Uint8List.fromList([0, 210, 101, 63, 247, 203, 178, + 216, 255, 18, 154, 194, 126, 245, 120, 28, 230, 139, 37, 88, 196, + 26, 116, 175, 31, 45, 220, 166, 53, 203, 238, 240, 125]); + final sb = new SerialBuffer(serialized); + final keystring = sb.getPrivateKey(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(keystring, 'PVT_K1_2bfGi9rYsXQSXXTvJbDAPhHLQUojjaNLomdm3cEJ1XTzMqUt3V'); + }); + test('serialize r1 new style', () { + final keystring = 'PVT_R1_2JrJRQXEagWobhJbHWtP11muTWi5pgCJ6uXWhGKd2KcFBGF7mT'; + final sb = new SerialBuffer(new Uint8List(0)); + sb.pushPrivateKey(keystring); + final serialized = sb.asUint8List(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(serialized, + [1, 172, 58, 10, 48, 178, 188, 37, 15, 234, 129, 216, 243, 182, + 68, 115, 41, 18, 206, 91, 223, 230, 199, 84, 66, 41, 110, 159, + 117, 45, 189, 67, 43]); + }); + test('deserialize r1 new style', () { + final serialized = Uint8List.fromList( + [1, 172, 58, 10, 48, 178, 188, 37, 15, 234, 129, 216, 243, 182, + 68, 115, 41, 18, 206, 91, 223, 230, 199, 84, 66, 41, 110, 159, + 117, 45, 189, 67, 43]); + final sb = new SerialBuffer(serialized); + final keystring = sb.getPrivateKey(); + + if(verbose) { + print("keystring: $keystring"); + print("serialized: $serialized\n"+" ${arrayToHex(serialized)}"); + } + expect(keystring, 'PVT_R1_2JrJRQXEagWobhJbHWtP11muTWi5pgCJ6uXWhGKd2KcFBGF7mT'); + }); + + }); + +}