github.com/hyperledger/aries-framework-go@v0.3.2/pkg/doc/jwt/jwt_support.go (about) 1 /* 2 Copyright SecureKey Technologies Inc. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package jwt 8 9 import ( 10 "crypto" 11 "crypto/ed25519" 12 "crypto/rand" 13 "crypto/rsa" 14 "errors" 15 16 "github.com/hyperledger/aries-framework-go/pkg/doc/jose" 17 ) 18 19 // JoseED25519Signer is a Jose compliant signer. 20 type JoseED25519Signer struct { 21 privKey []byte 22 headers map[string]interface{} 23 } 24 25 // Sign data. 26 func (s JoseED25519Signer) Sign(data []byte) ([]byte, error) { 27 return ed25519.Sign(s.privKey, data), nil 28 } 29 30 // Headers returns the signer's headers map. 31 func (s JoseED25519Signer) Headers() jose.Headers { 32 return s.headers 33 } 34 35 // NewEd25519Signer returns a Jose compliant signer that can be passed as a signer to jwt.NewSigned(). 36 func NewEd25519Signer(privKey []byte) *JoseED25519Signer { 37 return &JoseED25519Signer{ 38 privKey: privKey, 39 headers: prepareJWSHeaders(nil, signatureEdDSA), 40 } 41 } 42 43 // JoseEd25519Verifier is a Jose compliant verifier. 44 type JoseEd25519Verifier struct { 45 pubKey []byte 46 } 47 48 // Verify signingInput against signature. it validates that joseHeaders contains EdDSA alg for this implementation. 49 func (v JoseEd25519Verifier) Verify(joseHeaders jose.Headers, _, signingInput, signature []byte) error { 50 alg, ok := joseHeaders.Algorithm() 51 if !ok { 52 return errors.New("alg is not defined") 53 } 54 55 if alg != "EdDSA" { 56 return errors.New("alg is not EdDSA") 57 } 58 59 if ok := ed25519.Verify(v.pubKey, signingInput, signature); !ok { 60 return errors.New("signature doesn't match") 61 } 62 63 return nil 64 } 65 66 // NewEd25519Verifier returns a Jose compliant verifier that can be passed as a verifier option to jwt.Parse(). 67 func NewEd25519Verifier(pubKey []byte) (*JoseEd25519Verifier, error) { 68 if l := len(pubKey); l != ed25519.PublicKeySize { 69 return nil, errors.New("bad ed25519 public key length") 70 } 71 72 return &JoseEd25519Verifier{pubKey: pubKey}, nil 73 } 74 75 // RS256Signer is a Jose complient signer. 76 type RS256Signer struct { 77 privKey *rsa.PrivateKey 78 headers map[string]interface{} 79 } 80 81 // NewRS256Signer returns a Jose compliant signer that can be passed as a signer to jwt.NewSigned(). 82 func NewRS256Signer(privKey *rsa.PrivateKey, headers map[string]interface{}) *RS256Signer { 83 return &RS256Signer{ 84 privKey: privKey, 85 headers: prepareJWSHeaders(headers, signatureRS256), 86 } 87 } 88 89 // Sign data. 90 func (s RS256Signer) Sign(data []byte) ([]byte, error) { 91 hash := crypto.SHA256.New() 92 93 _, err := hash.Write(data) 94 if err != nil { 95 return nil, err 96 } 97 98 hashed := hash.Sum(nil) 99 100 return rsa.SignPKCS1v15(rand.Reader, s.privKey, crypto.SHA256, hashed) 101 } 102 103 // Headers returns the signer's headers map. 104 func (s RS256Signer) Headers() jose.Headers { 105 return s.headers 106 } 107 108 // RS256Verifier is a Jose compliant verifier. 109 type RS256Verifier struct { 110 pubKey *rsa.PublicKey 111 } 112 113 // NewRS256Verifier returns a Jose compliant verifier that can be passed as a verifier option to jwt.Parse(). 114 func NewRS256Verifier(pubKey *rsa.PublicKey) *RS256Verifier { 115 return &RS256Verifier{pubKey: pubKey} 116 } 117 118 // Verify signingInput against the signature. It also validates that joseHeaders includes the right alg. 119 func (v RS256Verifier) Verify(joseHeaders jose.Headers, _, signingInput, signature []byte) error { 120 alg, ok := joseHeaders.Algorithm() 121 if !ok { 122 return errors.New("alg is not defined") 123 } 124 125 if alg != "RS256" { 126 return errors.New("alg is not RS256") 127 } 128 129 hash := crypto.SHA256.New() 130 131 _, err := hash.Write(signingInput) 132 if err != nil { 133 return err 134 } 135 136 hashed := hash.Sum(nil) 137 138 return rsa.VerifyPKCS1v15(v.pubKey, crypto.SHA256, hashed, signature) 139 } 140 141 func verifyEd25519(jws string, pubKey ed25519.PublicKey) error { 142 v, err := NewEd25519Verifier(pubKey) 143 if err != nil { 144 return err 145 } 146 147 sVerifier := jose.NewCompositeAlgSigVerifier(jose.AlgSignatureVerifier{ 148 Alg: "EdDSA", 149 Verifier: v, 150 }) 151 152 token, _, err := Parse(jws, WithSignatureVerifier(sVerifier)) 153 if err != nil { 154 return err 155 } 156 157 if token == nil { 158 return errors.New("nil token") 159 } 160 161 return nil 162 } 163 164 func verifyRS256(jws string, pubKey *rsa.PublicKey) error { 165 v := NewRS256Verifier(pubKey) 166 167 sVerifier := jose.NewCompositeAlgSigVerifier(jose.AlgSignatureVerifier{ 168 Alg: "RS256", 169 Verifier: v, 170 }) 171 172 token, _, err := Parse(jws, WithSignatureVerifier(sVerifier)) 173 if err != nil { 174 return err 175 } 176 177 if token == nil { 178 return errors.New("nil token") 179 } 180 181 return nil 182 } 183 184 func prepareJWSHeaders(headers map[string]interface{}, alg string) map[string]interface{} { 185 newHeaders := make(map[string]interface{}) 186 187 for k, v := range headers { 188 newHeaders[k] = v 189 } 190 191 newHeaders[jose.HeaderAlgorithm] = alg 192 193 return newHeaders 194 }