MatrixAI / Polykey

Polykey Core Library
https://polykey.com
GNU General Public License v3.0
31 stars 4 forks source link

Replace node-forge RSA Keypair With ed25519/x25519 Keypair #168

Closed joshuakarp closed 1 year ago

joshuakarp commented 3 years ago

Created by robert-cronin

This issue is about specifying how we actually intend to use asymmetric crypto to:

The 2 modern algorithms for signing and encryption/decryption are:

AKA: "Ed25519" or "X25519".

See: https://crypto.stackexchange.com/questions/27866/why-curve25519-for-encryption-but-ed25519-for-signatures


We currently use node-forge's implementation of RSA keys, with a 4096 bit keypair. In doing so, we're limited in how transferable our public keys are. For example, the node ID of a keynode is required to be translated to a 'public key fingerprint' (a base64 encoding of a sha256 sum of the ASN.1 SubjectPublicKeyInfo encoding of the RSA public key) in order to be transferable as an ID Once we transition to ed25519, we can simply use the public key (256 bits) as the node ID. This would also simplify the process of #148.


Requires more research, in particular how to turn an existing ed25519 keypair (signing/verification only) into an x25519 key (encryption/decryption). There are articles to explain this process, we just need to research how best to do this in nodejs

joshuakarp commented 3 years ago

There's a current open PR on the node-forge repo regarding ed25519 in PEM: https://github.com/digitalbazaar/forge/pull/851. This will make this transition much easier.

CMCDragonkai commented 3 years ago

Resolving this issue requires us to fully plan out #155. Because if we modify or change our underlying crypto library which is currently node-forge, we have to be aware of cross-platform deployments in the future. No point swapping libraries if it just preventing us from being able to use it on mobile phones.

CMCDragonkai commented 3 years ago

Webcrypto issue has been moved to #270.

CMCDragonkai commented 2 years ago

Another library worth checking out noble-ed25519.

Other libraries here: https://paulmillr.com/noble/

CMCDragonkai commented 2 years ago

We successfully did this in several stages:

  1. Ed25519 keys with WebCrypto API in NodeJS 16.17
    • Required update to the pkgs.nix
    • This was an experimental API as part of the webcrypto interface, it is not part of the official web crypto standard, this means it also produces a warning message when it is being used
    • The web crypto API uses opaque key objects that have be marshalled in and out if you are using other libraries that work on key buffers
    • The API was limited to doing signing & verification with ed25519 keys, there was no facility to convert from ed25519 to x25519 keys for encryption/decryption
    • As a high level API it didn't allow us to do things like ECIES easily
  2. Ed25519 keys with https://github.com/paulmillr/noble-ed25519
    • This works directly with key buffers, making it easier to customise functionality
    • Provided ways of converting from ed25519 to x25519 keys
    • Provided a way of doing ECIES by doing diffie hellman exchange
    • Relies on webcrypto or node crypto which ever is in the global environment
  3. Ed25519 keys with @peculiar/webcrypto polyfill
    • This polyfilled webcrypto to support new features such as ed25519 signing and verification
    • This meant this can work without upgrading to NodeJS 16.17
    • Its ed25519 implementation is not compatible with NodeJS's implementation
    • When combined with the @peculiar/x509 library, it's not possible to use ed25519 keys from node's webcrypto API, because the API that the @peculiar/x509 expects is the interface provided by the @peculiar/webcrypto polyfill
  4. Ed25519 keys with https://github.com/sodium-friends/sodium-native
    • libsodium is cross platform C library that works on all platforms including mobile
    • the crypto library is designed around ed25519 and x25519 keys... it's part of the elliptic curve ecosystem, asymmetric and symmetric are all designed around it
    • it is a solid implementation of ECIES, thus not requiring our own crypto schemes
    • it provides symmetric algorithms as well
    • it cannot fulfill the entire webcrypto interface, because the webcrypto interface has RSA support, but libsodium does not have any RSA support, this means libsodium alone cannot be used as a backing implementation of the webcrypto interface

After exploring each of the 4 stages above. At this point we have a fully implemented src/keys/utils using a combination of 2., 3.

However after realising libsodium is the standard for ECIES and other elliptic curve algos (the non-NIST ones), I've come to the decision to revisit the keys/utils and replace 2. with 4. We still have to use webcrypto for the moment in order to support @peculiar/x509 and panva/jose. These 2 libraries still expect webcrypto interfaces and capabilities. Later in the future we can replace jose with something more minimal, a hand-selected set of algorithms specific to our usecases, which can allow us to use libsodium directly instead of jose. (Note that PASETO and PASERK is like JOSE but on top of libsodium, but I don't want to use these because they are not very web-popular). While for @peculiar/x509 it will be limited to signing and verification over ed25519 keys, therefore it should be possible to monkey patch a webcrypto object that satisfies these specifically just for @peculiar/x509. At that point we would have no need of webcrypto, nor node's crypto, and we would only have libsodium which is a cross platform library.

Due to our initial work on integration 2., 3. into src/keys/utils, we have already refactored the tests/keys/utils to test the new interface (it has changed quite a bit from node-forge). Moving to libsodium will not impact the API significantly, in fact it is likely to simplify the interface because we are not going to be using CryptoKey much.

In terms of work, it should 2 days to migrate the existing src/keys/utils in #446 to using the libsodium algorithms. I have already spent 1 day prototyping many of the changes in test-sodium.ts.

Downstream impact is on KeyRing and CertificateManager. These will be addressed in a separate issue #472.

CMCDragonkai commented 2 years ago

I suspect only 2 points of ETA left here.