I tried to do that by base58
encoding ed255191
public key bytes. Consider a following code sample:
const seed = crypto.randomBytes(32);
const keyPair = ed25519.MakeKeypair(seed);
const base58encoded = base58.encode(keyPair.publicKey);
console.log('ed25519 pub key bytes len: ' + keyPair.publicKey.length);
console.log('base58 pub key: ' + base58encoded);
console.log('base58 pub key len: ' + base58encoded.length);
console.log('actual key: edpktx799pgw7M4z8551URER52VcENNCSZwE9f9cst4v6h5vCrQmJE');
console.log('actual key len: ' + 'edpktx799pgw7M4z8551URER52VcENNCSZwE9f9cst4v6h5vCrQmJE'.length);
It prints:
ed25519 pub key bytes len: 32
base58 pub key: 6jRoreKb7RXAQZBuKZs7WDzsFHHrg62GkMmkXuiWqtKm
base58 pub key len: 44
actual key: edpktx799pgw7M4z8551URER52VcENNCSZwE9f9cst4v6h5vCrQmJE
actual key len: 54
A base58
string that I got is 10 characters shorter than an actual Tezos public key. This, and also that topic suggests I need to prefix my ed25519
data with some magical bytes before encoding it with base58
. What are those magical bytes? Is there a documentation about that?
Thanks.
EDIT after Arthur B's answer:
I tried appending prefix bytes: \013\015\037\217
to ed25519
bytes before base58
encoding them. Still, I got 49 characters when a real Tezos public key has 54 characters. After appending additional 4 random bytes, I got desired 54 chars and a value that starts with edpk
. Clearly this means that prefix is correct - but where do I get remaining 4 bytes from?
EDIT after discussion in comments:
4 bytes were missing due to me using base58
instead of base58check
that has additional 4 bytes as a checksum. After using base58check
I got 55 bytes starting with 1edpk
- so something looking like a valid public Tezos address prepended with a 1
.
Current problem is: when working with the key (specifically - computing its hash) I removed a leading 1
and got 54 characters. As a result, a library I'm using to hash a key threw an Invalid checksum
error. Clearly, 1
is a part of base58check
checksum. Still, if not removed the key is going to have an invalid prefix. An updated code sample looks like this:
const realKey = 'edpktx799pgw7M4z8551URER52VcENNCSZwE9f9cst4v6h5vCrQmJE';
const seed = crypto.randomBytes(32);
const keyPair = ed25519.MakeKeypair(seed);
const directPubKeyBytes = keyPair.publicKey;
const tezosPublicKeyPrefix = Buffer.from([13, 15, 37, 217]);
const prefixedPublicKey = Buffer.concat([tezosPublicKeyPrefix, directPubKeyBytes]);
const base58checkEncoded = base58check.encode(prefixedPublicKey).substr(1);
console.log('ed25519 pub key bytes len: ' + prefixedPublicKey.length);
console.log('base58 pub key: ' + base58checkEncoded);
console.log('base58 pub key len: ' + base58checkEncoded.length);
console.log('actual key len: ' + realKey.length);
const publicKey = new Key({ key: base58checkEncoded });
await publicKey.ready;
return publicKey.publicKeyHash();
It prints:
ed25519 pub key bytes len: 36
base58 pub key: edpkvCRxvpVG6FYAevL5Kqf4cQhaVAdyovGqrSCezHhNnav5BwjhuZ
base58 pub key len: 54
actual key len: 54
(node:12395) UnhandledPromiseRejectionWarning: Error: Invalid checksum
at Object.decode (/home/kspisacki/coding/wallets/node_modules/bs58check/base.js:41:25)
at Object.b58cdecode (/home/kspisacki/coding/wallets/node_modules/sotez/dist/node/index.js:1:12743)
at z.<anonymous> (/home/kspisacki/coding/wallets/node_modules/sotez/dist/node/index.js:1:15122)
at Generator.next (<anonymous>)
at o (/home/kspisacki/coding/wallets/node_modules/sotez/dist/node/index.js:1:13324)
Any further help with that would be greatly appreciated as I don't understand how to get this to work despite reading up A LOT on the topic ;)