Skip to content
This repository has been archived by the owner on Mar 27, 2024. It is now read-only.

refactor: Support JwsVerificationKey2020 for DID public key #1538

Merged
merged 1 commit into from Apr 2, 2020

Conversation

kdimak
Copy link
Contributor

@kdimak kdimak commented Mar 31, 2020

For linked data signatures with JwsVerificationKey2020 type, it's not enough information to make signature verification based on the public key bytes and a type (JwsVerificationKey2020). We need to know additionally what signature algorithm (and/or curve) was used - e.g. ES256 or EdDSA.
In the case of DID documents, we can read this information from the public key if it's defined as publicKeyJwk.
As a result, we extend PublicKey struct with Curve, Alg and KeyType fields and use them in the signature verifier implementations (e.g. in PublicKeyVerifierEC).

closes #1527, #1513

Signed-off-by: Dmitriy Kinoshenko dkinoshenko@gmail.com

@codecov
Copy link

codecov bot commented Mar 31, 2020

Codecov Report

Merging #1538 into master will increase coverage by 0.09%.
The diff coverage is 95.28%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1538      +/-   ##
==========================================
+ Coverage   91.32%   91.42%   +0.09%     
==========================================
  Files         156      156              
  Lines       10633    10752     +119     
==========================================
+ Hits         9711     9830     +119     
+ Misses        518      517       -1     
- Partials      404      405       +1     
Impacted Files Coverage Δ
pkg/doc/signature/verifier/verifier.go 95.65% <ø> (ø)
pkg/doc/did/doc.go 91.37% <82.05%> (-0.77%) ⬇️
pkg/doc/jose/jwk.go 98.59% <98.33%> (+8.11%) ⬆️
.../suite/jsonwebsignature2020/public_key_verifier.go 95.74% <100.00%> (+4.07%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e17df7e...669dc5b. Read the comment docs.

"math/big"

"github.com/decred/dcrd/dcrec/secp256k1/v2"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have you tried github.com/btcsuite ? I believe they have secp256k1 alg as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't. github.com/decred was initially added by @sudeshrshetty but I think we can switch to github.com/btcsuite.

Comment on lines 35 to 37
switch pubKey.Curve {
case "P-256":
curve = elliptic.P256()
keySize = 32
case "P-384":
curve = elliptic.P384()
keySize = 48
case "P-521":
curve = elliptic.P521()
keySize = 66
case "secp256k1":
curve = secp256k1.S256()
keySize = 32
default:
return fmt.Errorf("ecdsa: unsupported elliptic curve '%s'", pubKey.Curve)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't belong to Verify()

create a separate function

probably create a struct keyInfo that has a curve and keySize if needed in more than one place
probably expose it to be used for Sign as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK! I will try to simplify it.

y *big.Int
Kty string
Crv string
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no kid needed?

Copy link
Contributor Author

@kdimak kdimak Mar 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already there, inside embedded jose.JSONWebKey. x, y, key type, curve are not copied from jose.rawJSONWebKey to jose.JSONWebKey as a result of unmarshalling. That's why I had to add them to JWK struct to support secp256k1 properly.

Copy link
Contributor

@baha-ai baha-ai Mar 31, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there seems to be duplication of fields with JSONWebKey then.. it's better to remove duplicate fields


Value []byte

Algorithm string `json:"-"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need to show Alg, Curve & KeyType in exported did.Doc.PublicKey? Why can't we just decode public key internally and stick to old structure?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can at least make it hidden, why not?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those new fields are made private, thank you @sudeshrshetty

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, but what is the use of those private fields?
As I can see we are setting it from jwk instance but they are not being read anywhere afterwards.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually Curve is exposed (like in ecdsa.PublicKey)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why clients should care about curve? For key type based logics - they should be able to figure out using public key type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For JsonWebSignature2020, it's not enough to have only type value of the public key. Look at the example:

  "publicKey": [
    {
      "id": "did:example:123#_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A",
      "type": "JwsVerificationKey2020",
      "controller": "did:example:123",
      "publicKeyJwk": {
        "crv": "Ed25519",
        "x": "VCpo2LMLhn6iWku8MKvSLg2ZAoC-nlOyPVQaO3FxVeQ",
        "kty": "OKP",
        "kid": "_Qq0UL2Fq651Q0Fjd6TvnYE-faHiOpRlPVQcY_-tA4A"
      }
    },
    {
      "id": "did:example:123#4SZ-StXrp5Yd4_4rxHVTCYTHyt4zyPfN1fIuYsm6k3A",
      "type": "JwsVerificationKey2020",
      "controller": "did:example:123",
      "publicKeyJwk": {
        "crv": "secp256k1",
        "x": "Z4Y3NNOxv0J6tCgqOBFnHnaZhJF6LdulT7z8A-2D5_8",
        "y": "i5a2NtJoUKXkLm6q8nOEu9WOkso1Ag6FTUT6k_LMnGk",
        "kty": "EC",
        "kid": "4SZ-StXrp5Yd4_4rxHVTCYTHyt4zyPfN1fIuYsm6k3A"
      }
    }
  ]

The type is the same and is JwsVerificationKey2020.
We can't deduce is it Ed25519 or secp256k1 etc. We need to extract extra information from publicKeyJwk.
That's the problem solved in this PR.

@kdimak kdimak force-pushed the issue-1527 branch 2 times, most recently from 604d9ad to ce99590 Compare March 31, 2020 21:11
// if kty="EC" and Crv="secp256k1", then handle differently
return btcPublicKey(key.X, key.Y)
if jwk.Y == nil {
return nil, fmt.Errorf("missed y value in EC key")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed there are many detailed error messages returned like the above line.

If these messages reveal key details, then it's a security vulnerability. Please review all the returned errors in this document and only return generic messages to the user (or probably log detailed error messages in debug mode only).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. I changed the detailed error messages to a single generic invalid JWK.


Value []byte

algorithm string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would seem like it could be a publicKeyJWK sub struct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, we can just add publicKeyJwk field of *jose.JWK type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will also update verifier.PublicKey struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated.

Curve: elliptic.P521(),
KeySize: p521KeySize,
}
case "secp256k1":
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about X25519 / Ed25519?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Filed #1556.

@troyronda troyronda merged commit dab0fe3 into hyperledger-archives:master Apr 2, 2020
@kdimak kdimak deleted the issue-1527 branch April 2, 2020 17:16
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Support JwsVerificationKey2020 for DID public key
4 participants