ECDSA support #2

Closed
opened 2018-04-20 22:50:18 +00:00 by Ghost · 9 comments

I'd like to help out making Acme v2 support not only RSA compatible but also ECDSA.

As per coolaj86/greenlock.js#4

I'd like to help out making Acme v2 support not only RSA compatible but also ECDSA. As per https://git.coolaj86.com/coolaj86/greenlock.js/issues/4
Owner

You will find that quit a few places are hard-coded to use RS256:

https://git.coolaj86.com/coolaj86/acme-v2.js/src/branch/master/node.js#L142

Instead they could be handled like this:

{ ..., alg: options.accountKeypair.alg, ... }

And before the accountKeypair (or domainKeypair) is passed in, this could be done:

if (!options.accountKeypair.alg) { options.accountKeypair.alg = 'RS256'; }

Then you could start experimenting using ECDSA (ES256), probably using elliptic:
https://github.com/indutny/elliptic (or sepc256k1-node)

Next would be to create an alternate tests/index.js that passes in an object with the same function signatures as the RSA object (don't bother changing the name of it yet), but that is actually doing ECDSA functions.

Then would be to abstract the use of the ECDSA or RSA module based on the user input.

The spec uses 'RS256' and 'ES256', but normal implementations would simply specify the algorithm and then the bitlength of the algo as separate arguments.

So really it should probably look like this at the end:

options.accountKeypair.alg // RS256 or ES256
options.accountKeypair.type // RSA or ECDSA
options.accountKeypair.bitlength // 2048 or 256

Hopefully that's enough to get you started. Ask me questions.

You will find that quit a few places are hard-coded to use RS256: <https://git.coolaj86.com/coolaj86/acme-v2.js/src/branch/master/node.js#L142> Instead they could be handled like this: ``` { ..., alg: options.accountKeypair.alg, ... } ``` And before the `accountKeypair` (or `domainKeypair`) is passed in, this could be done: ``` if (!options.accountKeypair.alg) { options.accountKeypair.alg = 'RS256'; } ``` Then you could start experimenting using ECDSA (ES256), probably using elliptic: https://github.com/indutny/elliptic (or sepc256k1-node) Next would be to create an alternate tests/index.js that passes in an object with the same function signatures as the RSA object (don't bother changing the name of it yet), but that is actually doing ECDSA functions. Then would be to abstract the use of the ECDSA or RSA module based on the user input. The spec uses 'RS256' and 'ES256', but normal implementations would simply specify the algorithm and then the bitlength of the algo as separate arguments. So really it should probably look like this at the end: ``` options.accountKeypair.alg // RS256 or ES256 options.accountKeypair.type // RSA or ECDSA options.accountKeypair.bitlength // 2048 or 256 ``` Hopefully that's enough to get you started. Ask me questions.
Owner

Essentially:

First simply copy the interface of the RSA module and "hard code" its substitution.

Then once that's working begin abstracting and the object so that by type a simple if statement can pass it into the correct library under-the-hood.

It may require more than one library to be able to transition between jwk and pem.

Essentially: First simply copy the interface of the RSA module and "hard code" its substitution. Then once that's working begin abstracting and the object so that by `type` a simple if statement can pass it into the correct library under-the-hood. It may require more than one library to be able to transition between `jwk` and `pem`.
Author

I've managed to create the equivalent of your genkeypair.js using ecdsa, including writing it to the system.

I also have the basic structure of a function that returns a JWK in ECDSA format based on params you pass in, still needs a bit of work though. Doing this work in a practice repository for the time being, until I have it working.

https://github.com/travislavery/ecdsa-acme-practice

Going to work on cleaning up the code a bit more tomorrow.

I've managed to create the equivalent of your genkeypair.js using ecdsa, including writing it to the system. I also have the basic structure of a function that returns a JWK in ECDSA format based on params you pass in, still needs a bit of work though. Doing this work in a practice repository for the time being, until I have it working. https://github.com/travislavery/ecdsa-acme-practice Going to work on cleaning up the code a bit more tomorrow.
Owner

@travislavery We have all of the pieces except for one: signing a CSR. Let's get that done and then I'll spend some more time defining the abstraction for ECDSA and we can wrap it al up.

Here's four examples that I want you to create:

generateCsr(privateEcdsaJwk, ['example.com', 'www.example.com']).then(function (pemOrDer) {
  // in either format this will be very easy to translate to what we need
  console.log(pemOrDer);
});
generateCsr(privateEcdsaPem, ['example.com', 'www.example.com']).then(function (pemOrDer) {
  // in either format this will be very easy to translate to what we need
  console.log(pemOrDer);
});
signJson(privateEcdsaJwk, { foo: 'bar' }).then(function (jws) {
  // in either format this will be very easy to translate to what we need
  console.log(jws);
});
signJson(privateEcdsaPem, { foo: 'bar' }).then(function (jws) {
  // in either format this will be very easy to translate to what we need
  console.log(jws);
});

Think you can do that?

@travislavery We have all of the pieces except for one: signing a CSR. Let's get that done and then I'll spend some more time defining the abstraction for ECDSA and we can wrap it al up. Here's four examples that I want you to create: ``` generateCsr(privateEcdsaJwk, ['example.com', 'www.example.com']).then(function (pemOrDer) { // in either format this will be very easy to translate to what we need console.log(pemOrDer); }); ``` ``` generateCsr(privateEcdsaPem, ['example.com', 'www.example.com']).then(function (pemOrDer) { // in either format this will be very easy to translate to what we need console.log(pemOrDer); }); ``` ``` signJson(privateEcdsaJwk, { foo: 'bar' }).then(function (jws) { // in either format this will be very easy to translate to what we need console.log(jws); }); ``` ``` signJson(privateEcdsaPem, { foo: 'bar' }).then(function (jws) { // in either format this will be very easy to translate to what we need console.log(jws); }); ``` Think you can do that?
Author

Yeah for sure, I'll work on that today.

Yeah for sure, I'll work on that today.
Author

Hi,
First, i would like to thank you for developing this great lib.

Any update on that? is ECDSA gone be supported in the near future?

Thanks!

Hi, First, i would like to thank you for developing this great lib. Any update on that? is ECDSA gone be supported in the near future? Thanks!
Owner

The first 90% of the work for ECDSA support is done: https://www.npmjs.com/package/eckles

What remains:

The first 90% of the work for ECDSA support is done: https://www.npmjs.com/package/eckles What remains: * [x] Add thumbprint to Eckles.js (2019-02-06: added in v1.4.0) * [ ] Add an option `ecCurve` analogous to `rsaKeySize` in Greenlock / ACME.js * https://git.coolaj86.com/coolaj86/greenlock.js/src/branch/master/lib/core.js#L72 * [ ] Use Eckles instead of rsa-compat when `ecCurve` is specified * https://git.coolaj86.com/coolaj86/greenlock.js/src/branch/master/lib/core.js#L92 * https://git.coolaj86.com/coolaj86/greenlock.js/src/branch/master/lib/core.js#L255 * [ ] Supplant other occurances of `RSA.*` with `Eckles.*` * [ ] Bonus: support old node versions that only have createECDH https://nodejs.org/api/crypto.html#crypto_class_ecdh (same benefits as the new API, just named... less correctly)
Author

@coolaj86 I was able to create a certificate with ECDSA key by manipulating the code and inject a method to the options which create the CSR (base64) as Acme-v2.js do.
Anyway it will be great if you will enable it in the lib (to inject a CSR create function to the options) In that way it's not limiting the usage of the lib and the user can sign the CSR by himself.

Another thing to keep in mind is that letsencrypt still not support signing the certificate with ECDSA. which meeans that the certificate private key will be ECDSA but it will signed with rsa certificate.

@coolaj86 I was able to create a certificate with ECDSA key by manipulating the code and inject a method to the options which create the CSR (base64) as Acme-v2.js do. Anyway it will be great if you will enable it in the lib (to inject a CSR create function to the options) In that way it's not limiting the usage of the lib and the user can sign the CSR by himself. Another thing to keep in mind is that letsencrypt still not support signing the certificate with ECDSA. which meeans that the certificate private key will be ECDSA but it will signed with rsa certificate.
Owner

This made it into v3.

This made it into v3.
Sign in to join this conversation.
No Label
No Milestone
No Assignees
2 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: coolaj86/acme.js-ARCHIVED#2
No description provided.