Repository navigation
Export raw Ed25519 key? #3000
Description
Activity
I'm having the exact same issue and trouble figuring it out.
If i do:const { publicKey, privateKey } = crypto.generateKeyPairSync("ed25519") console.log(privateKey.export({ format: 'pem', type: 'pkcs8' }))I get:
-----BEGIN PRIVATE KEY----- MC4CAQAwBQYDK2VwBCIEICNhgbLqX0mBVyhVpkuxSFXZduLShA0mCrm7AT3TPete -----END PRIVATE KEY-----But if i try to just print the key with something like:
console.log(Buffer.from(privateKey.toString("base64")).toString("hex"))Then i get a 32 byte long string where i was expecting a 64 byte long one.
5b6f626a656374204f626a6563745dI'm assuming "we" are doing something wrong. But it's super difficult to figure out what. As there doesn't seem to be much information about it. I know for sure that i'm doing something wrong as that 5b6f626a656374204f626a6563745d stays the same over every run. Which is impossible given that i generate a new key every time. I assume it's the object name.
The alternative that i do know is string replacing the pem header from the export which does give just the key... But i have a hard time considering that the "right approach".
Help, please :)
Reacted by nexsodev@nodejs/crypto
@markg85 Your problem is different than the one @justablob posted. If you want to get the base64 without the BEGIN / END lines, you can export as DER and encode with base64:
console.log( privateKey.export({ format: 'der', type: 'pkcs8' }).toString('base64') )
Reacted by Mark Gaiser and e20dra1974@justablob We don't implement algorithm-specific APIs, so you can't access the individual parameters of a key, only serialize it. (This particular algorithm only has one parameter on the private key)
Your best bet to access key parameters is probably to parse the DER, here's a quick & dirty example:
function findDer(data, index, tagByte) { while (true) { if (data.length < 2) throw Error('unexpected EOF') const [ tag, length ] = data data = data.subarray(2) if ((tag & 31) === 31 || length >> 7) throw Error('not implemented') if (data.length < length) throw Error('unexpected EOF') if (index-- === 0) { if (tag !== tagByte) throw Error(`unexpected tag ${tag}`) return data.subarray(0, length) } data = data.subarray(length) } } let data = privateKey.export({ format: 'der', type: 'pkcs8' }) data = findDer(data, 0, (1 << 5) | 16) // SEQUENCE (PrivateKeyInfo) data = findDer(data, 2, 4) // OCTET STRING (PrivateKey) data = findDer(data, 0, 4) // OCTET STRING (CurvePrivateKey)
Reacted by sb2409Reacted by Gireesh Punathil and sb2409@markg85 Your problem is different than the one @justablob posted. If you want to get the base64 without the BEGIN / END lines, you can export as DER and encode with base64:
console.log( privateKey.export({ format: 'der', type: 'pkcs8' }).toString('base64') )
Awesome! That was the hint i needed to get it working. Thank you!
Reacted by Alba Mendezclosing as answered. feel free to reopen the issue if its still outstanding
Unfortunately, PKCS8 DER/PEM format is something completely strange and incompatible in Ed25519 world. You can't use this type of keys in libsodium or lots of other libraries that expect the raw data.
There should be Raw export through WebCrypto and just Crypto APIsReacted by Zeke Gabrielse, Piotr, Sebastian Tauchert, Peter Torelli, Steven Luscher, William Pride and Jozef IzsoI'm not super familiar with ASN1 edge cases, but this is working for me:
const { publicKey, privateKey } = generateKeyPairSync('ed25519'); const der = privateKey.export({ format: 'der', type: 'pkcs8' }).toString('hex'); const rawHex = der.substring(32); // can serialize this / use it with libsodium etc...
Reacted by Richard AyotteFYI: nodejs/node#62240
I'm trying to export an Ed25519 private key without any PEM/DER encoding around it but i'm kind of struggling:
gives me a 48-byte Buffer (which makes sense, it's ASN1, not the raw key), but that makes me wonder if there's any way to get the raw 32-byte private key. I could probably use some ASN1 library to get it from the DER Buffer but that's a little convoluted. It's possible that I'm completely missing something here.