github.com/devops-filetransfer/sshego@v7.0.4+incompatible/_vendor/golang.org/x/crypto/acme/jws_test.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package acme 6 7 import ( 8 "crypto/ecdsa" 9 "crypto/elliptic" 10 "crypto/rsa" 11 "crypto/x509" 12 "encoding/base64" 13 "encoding/json" 14 "encoding/pem" 15 "fmt" 16 "math/big" 17 "testing" 18 ) 19 20 const ( 21 testKeyPEM = ` 22 -----BEGIN RSA PRIVATE KEY----- 23 MIIEowIBAAKCAQEA4xgZ3eRPkwoRvy7qeRUbmMDe0V+xH9eWLdu0iheeLlrmD2mq 24 WXfP9IeSKApbn34g8TuAS9g5zhq8ELQ3kmjr+KV86GAMgI6VAcGlq3QrzpTCf/30 25 Ab7+zawrfRaFONa1HwEzPY1KHnGVkxJc85gNkwYI9SY2RHXtvln3zs5wITNrdosq 26 EXeaIkVYBEhbhNu54pp3kxo6TuWLi9e6pXeWetEwmlBwtWZlPoib2j3TxLBksKZf 27 oyFyek380mHgJAumQ/I2fjj98/97mk3ihOY4AgVdCDj1z/GCoZkG5Rq7nbCGyosy 28 KWyDX00Zs+nNqVhoLeIvXC4nnWdJMZ6rogxyQQIDAQABAoIBACIEZTOI1Kao9nmV 29 9IeIsuaR1Y61b9neOF/MLmIVIZu+AAJFCMB4Iw11FV6sFodwpEyeZhx2WkpWVN+H 30 r19eGiLX3zsL0DOdqBJoSIHDWCCMxgnYJ6nvS0nRxX3qVrBp8R2g12Ub+gNPbmFm 31 ecf/eeERIVxfifd9VsyRu34eDEvcmKFuLYbElFcPh62xE3x12UZvV/sN7gXbawpP 32 G+w255vbE5MoaKdnnO83cTFlcHvhn24M/78qP7Te5OAeelr1R89kYxQLpuGe4fbS 33 zc6E3ym5Td6urDetGGrSY1Eu10/8sMusX+KNWkm+RsBRbkyKq72ks/qKpOxOa+c6 34 9gm+Y8ECgYEA/iNUyg1ubRdH11p82l8KHtFC1DPE0V1gSZsX29TpM5jS4qv46K+s 35 8Ym1zmrORM8x+cynfPx1VQZQ34EYeCMIX212ryJ+zDATl4NE0I4muMvSiH9vx6Xc 36 7FmhNnaYzPsBL5Tm9nmtQuP09YEn8poiOJFiDs/4olnD5ogA5O4THGkCgYEA5MIL 37 qWYBUuqbEWLRtMruUtpASclrBqNNsJEsMGbeqBJmoMxdHeSZckbLOrqm7GlMyNRJ 38 Ne/5uWRGSzaMYuGmwsPpERzqEvYFnSrpjW5YtXZ+JtxFXNVfm9Z1gLLgvGpOUCIU 39 RbpoDckDe1vgUuk3y5+DjZihs+rqIJ45XzXTzBkCgYBWuf3segruJZy5rEKhTv+o 40 JqeUvRn0jNYYKFpLBeyTVBrbie6GkbUGNIWbrK05pC+c3K9nosvzuRUOQQL1tJbd 41 4gA3oiD9U4bMFNr+BRTHyZ7OQBcIXdz3t1qhuHVKtnngIAN1p25uPlbRFUNpshnt 42 jgeVoHlsBhApcs5DUc+pyQKBgDzeHPg/+g4z+nrPznjKnktRY1W+0El93kgi+J0Q 43 YiJacxBKEGTJ1MKBb8X6sDurcRDm22wMpGfd9I5Cv2v4GsUsF7HD/cx5xdih+G73 44 c4clNj/k0Ff5Nm1izPUno4C+0IOl7br39IPmfpSuR6wH/h6iHQDqIeybjxyKvT1G 45 N0rRAoGBAKGD+4ZI/E1MoJ5CXB8cDDMHagbE3cq/DtmYzE2v1DFpQYu5I4PCm5c7 46 EQeIP6dZtv8IMgtGIb91QX9pXvP0aznzQKwYIA8nZgoENCPfiMTPiEDT9e/0lObO 47 9XWsXpbSTsRPj0sv1rB+UzBJ0PgjK4q2zOF0sNo7b1+6nlM3BWPx 48 -----END RSA PRIVATE KEY----- 49 ` 50 51 // This thumbprint is for the testKey defined above. 52 testKeyThumbprint = "6nicxzh6WETQlrvdchkz-U3e3DOQZ4heJKU63rfqMqQ" 53 54 // openssl ecparam -name secp256k1 -genkey -noout 55 testKeyECPEM = ` 56 -----BEGIN EC PRIVATE KEY----- 57 MHcCAQEEIK07hGLr0RwyUdYJ8wbIiBS55CjnkMD23DWr+ccnypWLoAoGCCqGSM49 58 AwEHoUQDQgAE5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HThqIrvawF5 59 QAaS/RNouybCiRhRjI3EaxLkQwgrCw0gqQ== 60 -----END EC PRIVATE KEY----- 61 ` 62 // openssl ecparam -name secp384r1 -genkey -noout 63 testKeyEC384PEM = ` 64 -----BEGIN EC PRIVATE KEY----- 65 MIGkAgEBBDAQ4lNtXRORWr1bgKR1CGysr9AJ9SyEk4jiVnlUWWUChmSNL+i9SLSD 66 Oe/naPqXJ6CgBwYFK4EEACKhZANiAAQzKtj+Ms0vHoTX5dzv3/L5YMXOWuI5UKRj 67 JigpahYCqXD2BA1j0E/2xt5vlPf+gm0PL+UHSQsCokGnIGuaHCsJAp3ry0gHQEke 68 WYXapUUFdvaK1R2/2hn5O+eiQM8YzCg= 69 -----END EC PRIVATE KEY----- 70 ` 71 // openssl ecparam -name secp521r1 -genkey -noout 72 testKeyEC512PEM = ` 73 -----BEGIN EC PRIVATE KEY----- 74 MIHcAgEBBEIBSNZKFcWzXzB/aJClAb305ibalKgtDA7+70eEkdPt28/3LZMM935Z 75 KqYHh/COcxuu3Kt8azRAUz3gyr4zZKhlKUSgBwYFK4EEACOhgYkDgYYABAHUNKbx 76 7JwC7H6pa2sV0tERWhHhB3JmW+OP6SUgMWryvIKajlx73eS24dy4QPGrWO9/ABsD 77 FqcRSkNVTXnIv6+0mAF25knqIBIg5Q8M9BnOu9GGAchcwt3O7RDHmqewnJJDrbjd 78 GGnm6rb+NnWR9DIopM0nKNkToWoF/hzopxu4Ae/GsQ== 79 -----END EC PRIVATE KEY----- 80 ` 81 // 1. openssl ec -in key.pem -noout -text 82 // 2. remove first byte, 04 (the header); the rest is X and Y 83 // 3. convert each with: echo <val> | xxd -r -p | base64 -w 100 | tr -d '=' | tr '/+' '_-' 84 testKeyECPubX = "5lhEug5xK4xBDZ2nAbaxLtaLiv85bxJ7ePd1dkO23HQ" 85 testKeyECPubY = "4aiK72sBeUAGkv0TaLsmwokYUYyNxGsS5EMIKwsNIKk" 86 testKeyEC384PubX = "MyrY_jLNLx6E1-Xc79_y-WDFzlriOVCkYyYoKWoWAqlw9gQNY9BP9sbeb5T3_oJt" 87 testKeyEC384PubY = "Dy_lB0kLAqJBpyBrmhwrCQKd68tIB0BJHlmF2qVFBXb2itUdv9oZ-TvnokDPGMwo" 88 testKeyEC512PubX = "AdQ0pvHsnALsfqlraxXS0RFaEeEHcmZb44_pJSAxavK8gpqOXHvd5Lbh3LhA8atY738AGwMWpxFKQ1VNeci_r7SY" 89 testKeyEC512PubY = "AXbmSeogEiDlDwz0Gc670YYByFzC3c7tEMeap7CckkOtuN0Yaebqtv42dZH0MiikzSco2ROhagX-HOinG7gB78ax" 90 91 // echo -n '{"crv":"P-256","kty":"EC","x":"<testKeyECPubX>","y":"<testKeyECPubY>"}' | \ 92 // openssl dgst -binary -sha256 | base64 | tr -d '=' | tr '/+' '_-' 93 testKeyECThumbprint = "zedj-Bd1Zshp8KLePv2MB-lJ_Hagp7wAwdkA0NUTniU" 94 ) 95 96 var ( 97 testKey *rsa.PrivateKey 98 testKeyEC *ecdsa.PrivateKey 99 testKeyEC384 *ecdsa.PrivateKey 100 testKeyEC512 *ecdsa.PrivateKey 101 ) 102 103 func init() { 104 testKey = parseRSA(testKeyPEM, "testKeyPEM") 105 testKeyEC = parseEC(testKeyECPEM, "testKeyECPEM") 106 testKeyEC384 = parseEC(testKeyEC384PEM, "testKeyEC384PEM") 107 testKeyEC512 = parseEC(testKeyEC512PEM, "testKeyEC512PEM") 108 } 109 110 func decodePEM(s, name string) []byte { 111 d, _ := pem.Decode([]byte(s)) 112 if d == nil { 113 panic("no block found in " + name) 114 } 115 return d.Bytes 116 } 117 118 func parseRSA(s, name string) *rsa.PrivateKey { 119 b := decodePEM(s, name) 120 k, err := x509.ParsePKCS1PrivateKey(b) 121 if err != nil { 122 panic(fmt.Sprintf("%s: %v", name, err)) 123 } 124 return k 125 } 126 127 func parseEC(s, name string) *ecdsa.PrivateKey { 128 b := decodePEM(s, name) 129 k, err := x509.ParseECPrivateKey(b) 130 if err != nil { 131 panic(fmt.Sprintf("%s: %v", name, err)) 132 } 133 return k 134 } 135 136 func TestJWSEncodeJSON(t *testing.T) { 137 claims := struct{ Msg string }{"Hello JWS"} 138 // JWS signed with testKey and "nonce" as the nonce value 139 // JSON-serialized JWS fields are split for easier testing 140 const ( 141 // {"alg":"RS256","jwk":{"e":"AQAB","kty":"RSA","n":"..."},"nonce":"nonce"} 142 protected = "eyJhbGciOiJSUzI1NiIsImp3ayI6eyJlIjoiQVFBQiIsImt0eSI6" + 143 "IlJTQSIsIm4iOiI0eGdaM2VSUGt3b1J2eTdxZVJVYm1NRGUwVi14" + 144 "SDllV0xkdTBpaGVlTGxybUQybXFXWGZQOUllU0tBcGJuMzRnOFR1" + 145 "QVM5ZzV6aHE4RUxRM2ttanItS1Y4NkdBTWdJNlZBY0dscTNRcnpw" + 146 "VENmXzMwQWI3LXphd3JmUmFGT05hMUh3RXpQWTFLSG5HVmt4SmM4" + 147 "NWdOa3dZSTlTWTJSSFh0dmxuM3pzNXdJVE5yZG9zcUVYZWFJa1ZZ" + 148 "QkVoYmhOdTU0cHAza3hvNlR1V0xpOWU2cFhlV2V0RXdtbEJ3dFda" + 149 "bFBvaWIyajNUeExCa3NLWmZveUZ5ZWszODBtSGdKQXVtUV9JMmZq" + 150 "ajk4Xzk3bWszaWhPWTRBZ1ZkQ0RqMXpfR0NvWmtHNVJxN25iQ0d5" + 151 "b3N5S1d5RFgwMFpzLW5OcVZob0xlSXZYQzRubldkSk1aNnJvZ3h5" + 152 "UVEifSwibm9uY2UiOiJub25jZSJ9" 153 // {"Msg":"Hello JWS"} 154 payload = "eyJNc2ciOiJIZWxsbyBKV1MifQ" 155 signature = "eAGUikStX_UxyiFhxSLMyuyBcIB80GeBkFROCpap2sW3EmkU_ggF" + 156 "knaQzxrTfItICSAXsCLIquZ5BbrSWA_4vdEYrwWtdUj7NqFKjHRa" + 157 "zpLHcoR7r1rEHvkoP1xj49lS5fc3Wjjq8JUhffkhGbWZ8ZVkgPdC" + 158 "4tMBWiQDoth-x8jELP_3LYOB_ScUXi2mETBawLgOT2K8rA0Vbbmx" + 159 "hWNlOWuUf-8hL5YX4IOEwsS8JK_TrTq5Zc9My0zHJmaieqDV0UlP" + 160 "k0onFjPFkGm7MrPSgd0MqRG-4vSAg2O4hDo7rKv4n8POjjXlNQvM" + 161 "9IPLr8qZ7usYBKhEGwX3yq_eicAwBw" 162 ) 163 164 b, err := jwsEncodeJSON(claims, testKey, "nonce") 165 if err != nil { 166 t.Fatal(err) 167 } 168 var jws struct{ Protected, Payload, Signature string } 169 if err := json.Unmarshal(b, &jws); err != nil { 170 t.Fatal(err) 171 } 172 if jws.Protected != protected { 173 t.Errorf("protected:\n%s\nwant:\n%s", jws.Protected, protected) 174 } 175 if jws.Payload != payload { 176 t.Errorf("payload:\n%s\nwant:\n%s", jws.Payload, payload) 177 } 178 if jws.Signature != signature { 179 t.Errorf("signature:\n%s\nwant:\n%s", jws.Signature, signature) 180 } 181 } 182 183 func TestJWSEncodeJSONEC(t *testing.T) { 184 tt := []struct { 185 key *ecdsa.PrivateKey 186 x, y string 187 alg, crv string 188 }{ 189 {testKeyEC, testKeyECPubX, testKeyECPubY, "ES256", "P-256"}, 190 {testKeyEC384, testKeyEC384PubX, testKeyEC384PubY, "ES384", "P-384"}, 191 {testKeyEC512, testKeyEC512PubX, testKeyEC512PubY, "ES512", "P-521"}, 192 } 193 for i, test := range tt { 194 claims := struct{ Msg string }{"Hello JWS"} 195 b, err := jwsEncodeJSON(claims, test.key, "nonce") 196 if err != nil { 197 t.Errorf("%d: %v", i, err) 198 continue 199 } 200 var jws struct{ Protected, Payload, Signature string } 201 if err := json.Unmarshal(b, &jws); err != nil { 202 t.Errorf("%d: %v", i, err) 203 continue 204 } 205 206 b, err = base64.RawURLEncoding.DecodeString(jws.Protected) 207 if err != nil { 208 t.Errorf("%d: jws.Protected: %v", i, err) 209 } 210 var head struct { 211 Alg string 212 Nonce string 213 JWK struct { 214 Crv string 215 Kty string 216 X string 217 Y string 218 } `json:"jwk"` 219 } 220 if err := json.Unmarshal(b, &head); err != nil { 221 t.Errorf("%d: jws.Protected: %v", i, err) 222 } 223 if head.Alg != test.alg { 224 t.Errorf("%d: head.Alg = %q; want %q", i, head.Alg, test.alg) 225 } 226 if head.Nonce != "nonce" { 227 t.Errorf("%d: head.Nonce = %q; want nonce", i, head.Nonce) 228 } 229 if head.JWK.Crv != test.crv { 230 t.Errorf("%d: head.JWK.Crv = %q; want %q", i, head.JWK.Crv, test.crv) 231 } 232 if head.JWK.Kty != "EC" { 233 t.Errorf("%d: head.JWK.Kty = %q; want EC", i, head.JWK.Kty) 234 } 235 if head.JWK.X != test.x { 236 t.Errorf("%d: head.JWK.X = %q; want %q", i, head.JWK.X, test.x) 237 } 238 if head.JWK.Y != test.y { 239 t.Errorf("%d: head.JWK.Y = %q; want %q", i, head.JWK.Y, test.y) 240 } 241 } 242 } 243 244 func TestJWKThumbprintRSA(t *testing.T) { 245 // Key example from RFC 7638 246 const base64N = "0vx7agoebGcQSuuPiLJXZptN9nndrQmbXEps2aiAFbWhM78LhWx4cbbfAAt" + 247 "VT86zwu1RK7aPFFxuhDR1L6tSoc_BJECPebWKRXjBZCiFV4n3oknjhMstn6" + 248 "4tZ_2W-5JsGY4Hc5n9yBXArwl93lqt7_RN5w6Cf0h4QyQ5v-65YGjQR0_FD" + 249 "W2QvzqY368QQMicAtaSqzs8KJZgnYb9c7d0zgdAZHzu6qMQvRL5hajrn1n9" + 250 "1CbOpbISD08qNLyrdkt-bFTWhAI4vMQFh6WeZu0fM4lFd2NcRwr3XPksINH" + 251 "aQ-G_xBniIqbw0Ls1jF44-csFCur-kEgU8awapJzKnqDKgw" 252 const base64E = "AQAB" 253 const expected = "NzbLsXh8uDCcd-6MNwXF4W_7noWXFZAfHkxZsRGC9Xs" 254 255 b, err := base64.RawURLEncoding.DecodeString(base64N) 256 if err != nil { 257 t.Fatalf("Error parsing example key N: %v", err) 258 } 259 n := new(big.Int).SetBytes(b) 260 261 b, err = base64.RawURLEncoding.DecodeString(base64E) 262 if err != nil { 263 t.Fatalf("Error parsing example key E: %v", err) 264 } 265 e := new(big.Int).SetBytes(b) 266 267 pub := &rsa.PublicKey{N: n, E: int(e.Uint64())} 268 th, err := JWKThumbprint(pub) 269 if err != nil { 270 t.Error(err) 271 } 272 if th != expected { 273 t.Errorf("thumbprint = %q; want %q", th, expected) 274 } 275 } 276 277 func TestJWKThumbprintEC(t *testing.T) { 278 // Key example from RFC 7520 279 // expected was computed with 280 // echo -n '{"crv":"P-521","kty":"EC","x":"<base64X>","y":"<base64Y>"}' | \ 281 // openssl dgst -binary -sha256 | \ 282 // base64 | \ 283 // tr -d '=' | tr '/+' '_-' 284 const ( 285 base64X = "AHKZLLOsCOzz5cY97ewNUajB957y-C-U88c3v13nmGZx6sYl_oJXu9A5RkT" + 286 "KqjqvjyekWF-7ytDyRXYgCF5cj0Kt" 287 base64Y = "AdymlHvOiLxXkEhayXQnNCvDX4h9htZaCJN34kfmC6pV5OhQHiraVySsUda" + 288 "QkAgDPrwQrJmbnX9cwlGfP-HqHZR1" 289 expected = "dHri3SADZkrush5HU_50AoRhcKFryN-PI6jPBtPL55M" 290 ) 291 292 b, err := base64.RawURLEncoding.DecodeString(base64X) 293 if err != nil { 294 t.Fatalf("Error parsing example key X: %v", err) 295 } 296 x := new(big.Int).SetBytes(b) 297 298 b, err = base64.RawURLEncoding.DecodeString(base64Y) 299 if err != nil { 300 t.Fatalf("Error parsing example key Y: %v", err) 301 } 302 y := new(big.Int).SetBytes(b) 303 304 pub := &ecdsa.PublicKey{Curve: elliptic.P521(), X: x, Y: y} 305 th, err := JWKThumbprint(pub) 306 if err != nil { 307 t.Error(err) 308 } 309 if th != expected { 310 t.Errorf("thumbprint = %q; want %q", th, expected) 311 } 312 } 313 314 func TestJWKThumbprintErrUnsupportedKey(t *testing.T) { 315 _, err := JWKThumbprint(struct{}{}) 316 if err != ErrUnsupportedKey { 317 t.Errorf("err = %q; want %q", err, ErrUnsupportedKey) 318 } 319 }