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  }