-
Notifications
You must be signed in to change notification settings - Fork 463
Web Crypto Signature Provider and conversion methods #937
Conversation
Must use already constructed CryptoKey private keys
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. This has been tested out in cornea
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Just one comment for clarification.
const derHex = Buffer.from(extractedDecoded, 'binary').toString('hex'); | ||
const publicKeyHex = derHex.replace('3059301306072a8648ce3d020106082a8648ce3d030107034200', ''); | ||
const publicKeyEc = ec.keyFromPublic(publicKeyHex, 'hex'); | ||
return PublicKey.fromElliptic(publicKeyEc, KeyType.r1, ec); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to confirm, could ec
be initially passed non-empty and of type secp256k1
, or only p256 is supported here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only p256 is supported for the Web Crypto API but it is possible that someone could put a k1 ec
object and the code would break. I think a check is likely needed, I'll add it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, turns out the elliptic
library does not easily label the curve utilized in the object. It would not be as simple as checking ec.curve.label = 'p256';
. I will remove the ability of providing an ec
object to the functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! This looks more clear too me.
let recoveredKey: any; | ||
for (let i = 0; i < 4; i++) { | ||
try { | ||
const keyPair = ec.recoverPubKey(digest, signature, i); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name keyPair
is a bit confusing as private key is not here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually the recoverPubKey
function will return an ec
keyPair
object, although the private will be empty and the public will be non-empty.
CI/CD changes for PRs #937/#963/#964 - merging per a request from Brad this is a bug with github actions, version 12.14.1 has been replaced by the v15.14.0 ones, can you override and merge it? It also might be because I have to copy the workflow files to master but I won't be certain until this one is merged Will be verified and can be reverted if something else breaks.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per BLU-20451 this is now ready for merge. Please address the docs change requested.
docs/basic-usage/index.md
Outdated
@@ -14,3 +14,6 @@ The SignatureProvider object must contain the private keys corresponding to the | |||
The Api constructor requires a SignatureProvider. SignatureProviders implement the `dist/eosjs-api-interfaces.SignatureProvider` interface. For development purpose only, a `JsSignatureProvider` object is also provided via the `dist/eosjs-jssig` import to stand-in for an easy option for a signature provider during development, but should only be used in development, as it is not secure. | |||
|
|||
In production code, it is recommended that you use a secure vault outside of the context of the webpage (which will also implement the `eosjs-api-interfaces.SignatureProvider` interface) to ensure security when signing transactions. | |||
|
|||
## WebCryptoSignatureProvider | |||
Additionally, `WebCryptoSignatureProvider` is available in `eosjs` as a more secure built-in `SignatureProvider` than `JsSignatureProvider`. Utilizing the [SubtleCrypto interface of the Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto), the `WebCryptoSignatureProvider` provides functionality for signing transactions utilizing CryptoKeys created by Web Crypto. There are several methods available as well to convert extractable CryptoKeys into PrivateKey/PublicKey `eosjs` formats, which can then be converted into string or `elliptic` keypairs. The method `generateWebCryptoKeyPair` is also available to create a CryptoKeyPair where the private CryptoKey is non-extractable and the public CryptoKey is extractable. This is intentional as an extractable private key is more insecure than a non-extractable private key. There are several more security concerns that you will need to address when it comes to utilizing the Web Crypto API, such as secure key management, so only utilize the `WebCryptoSignatureProvider` if you are aware of these security requirements and the risks involved in insecure environments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove this section and provide a stub in its place and once the documentation is created and signed off by Product and Developer Relations - they can PR those changes in via a separate PR. Other than that this PR is now ready to merge per BLU-20451
@bradlhart What is the status of this PR? |
Change Description
The Web Crypto API, or otherwise referred as SubtleCrypto, has the ability to construct or import both public and private keys as well as sign data using the private key CryptoKey. The format of the CryptoKey and Signature are different than eosjs built-in format and elliptic format. This code adds functionality to convert from eosjs built-in format to CryptoKeys as well as CryptoKeys and Signature to eosjs format.
Lastly, this code also includes a Web Crypto Signature Provider that can be used to store keys and sign transactions before sending to nodeos.
API Changes
Added:
PrivateKey.toWebCrypto()
: converts PrivateKey to private CryptoKeyPrivateKey.fromWebCrypto()
: converts private CryptoKey to PrivateKeyPrivateKey.webCryptoSign()
: signs data in Web Crypto method (sha256 hashing is done within Web Crypto method)PublicKey.toWebCrypto()
: converts PublicKey to public CryptoKeyPublicKey.fromWebCrypto()
: converts public CryptoKey to PublicKeySignature.fromWebCrypto()
: converts Web Crypto-created signature to SignatureNew:
WebCryptoSignatureProvider
signature provideraddCryptoKeyPair
: convenient method to add a CryptoKeyPair to the signature provider, rather than populatingkeys
andavailableKeys
manuallysign
: creates a buffer to sign utilizing Web Crypto's sign method and converts the outputted signature to a Signature classDocumentation Additions
Added a concise section about the new WebCryptoSignatureProvider