@@ -15,11 +15,13 @@ import (
15
15
"encoding/base64"
16
16
"encoding/hex"
17
17
"encoding/json"
18
+ "encoding/pem"
18
19
"fmt"
19
20
"io"
20
21
"math/big"
21
22
"net/http"
22
23
"net/http/httptest"
24
+ "net/url"
23
25
"reflect"
24
26
"sort"
25
27
"strings"
@@ -37,6 +39,17 @@ func newTestClient() *Client {
37
39
}
38
40
}
39
41
42
+ // newTestClientWithMockDirectory creates a client with a non-nil Directory
43
+ // that contains mock field values.
44
+ func newTestClientWithMockDirectory () * Client {
45
+ return & Client {
46
+ Key : testKeyEC ,
47
+ dir : & Directory {
48
+ RenewalInfoURL : "https://example.com/acme/renewal-info/" ,
49
+ },
50
+ }
51
+ }
52
+
40
53
// Decodes a JWS-encoded request and unmarshals the decoded JSON into a provided
41
54
// interface.
42
55
func decodeJWSRequest (t * testing.T , v interface {}, r io.Reader ) {
@@ -497,6 +510,133 @@ func TestFetchCertSize(t *testing.T) {
497
510
}
498
511
}
499
512
513
+ const (
514
+ issuerPEM = `-----BEGIN CERTIFICATE-----
515
+ MIIE3DCCA0SgAwIBAgIRAPoe8bsoe0klnS+2X8jSXe0wDQYJKoZIhvcNAQELBQAw
516
+ gYUxHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEtMCsGA1UECwwkY3Bh
517
+ bG1lckBwdW1wa2luLmxvY2FsIChDaHJpcyBQYWxtZXIpMTQwMgYDVQQDDCtta2Nl
518
+ cnQgY3BhbG1lckBwdW1wa2luLmxvY2FsIChDaHJpcyBQYWxtZXIpMB4XDTIzMDcx
519
+ MjE4MjIxNloXDTMzMDcxMjE4MjIxNlowgYUxHjAcBgNVBAoTFW1rY2VydCBkZXZl
520
+ bG9wbWVudCBDQTEtMCsGA1UECwwkY3BhbG1lckBwdW1wa2luLmxvY2FsIChDaHJp
521
+ cyBQYWxtZXIpMTQwMgYDVQQDDCtta2NlcnQgY3BhbG1lckBwdW1wa2luLmxvY2Fs
522
+ IChDaHJpcyBQYWxtZXIpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA
523
+ vsqsjjsfOwfwHJO9/st4+bA5Y05puXzjiX+B586Zm3nneQpxTb35vTA7hUn5kT9h
524
+ +AlEfOvs1t17NNvQ0NjDXID5xSTfzBU/STAG4gKCGkzJPma++TWM+dlRaL7ZICvE
525
+ qigVtbZeCZbu56j0kaZ9eYZyvS1itkTIhN/67qsh7j7BlDhLR1m7jQNz7QaNtLkJ
526
+ 8NJzKUVmpFHssLBBHkQSWpC7deJczcwZvBI7WbjJyz5xt+gw6sPvNtzGzu+jRmjD
527
+ 6GtQFbAcV7OTkUDIaxiiO8d5MPqYFTTntPH0Tj/JwEmbUteICYe7aH7Oq/aYWD2I
528
+ 407ymNjOh1YVHZuOaZVMgw2bhzLWnQYQtO2fTxQud+ppd7T4RFvirYD4Nv/TGjtx
529
+ M3YidhioHgd1i41BfSaq+g/QjBljJRygWJo+HX4xRHS3FZvMLtC2/drxVETZyWYj
530
+ YVOK+BTteZf5xOSlVqSZ0I1lF0GEiglPrz7ki0zcOL5H8J4V+kKSE+3oIhM/dvG1
531
+ AgMBAAGjRTBDMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0G
532
+ A1UdDgQWBBT6S+ENDu2e76E5I59q6xQrH7PE2zANBgkqhkiG9w0BAQsFAAOCAYEA
533
+ dZJMBDtrgdTnV4r4XxPwjShFcGxnEHVRbKOixw6euVvfHutCyKljlwQAwKhTJ9iM
534
+ ua48h72jlWtgAXDLDXCV7SSYilGhBGECEubxxDGE/b9TBxHediopxQp9wogeUhmV
535
+ 9BXw0ppJbH1CLmL5bfTR7cJZVz6M8XuqSzTayxuUImcoUNO7dNV0Q5igWRb8vUUK
536
+ ITX9tA54qOF3ENQLmeouDdtdJJLI2ExUoqO8XEKwMFg+Pj4AVu2kyzziCCela2ji
537
+ TUNcLW0ri2wwY8cc+IsF40tUjcMKlHp1NHVlawgP4wKW7YlEOweGLUFFKTxvTlSZ
538
+ gQDZANpuJL7Wqrmu8edffCOnMVxGrSLm6HuVc/RembdguWOPgKb8QImpJQcYv+RD
539
+ 1KZpqFsCEAED46v7Ea5jrSsyJ/ZysvMC8RfYS55wMTwfaZyVldFW9U3ElzoaWsei
540
+ ip2IXMXY/9RjRwc4RGEJcMyIGKXRUat9blzBtv/pNv1uChG2GDCbhltCyz3v5Tn/
541
+ -----END CERTIFICATE-----`
542
+ leafPEM = `-----BEGIN CERTIFICATE-----
543
+ MIIEizCCAvOgAwIBAgIRAITApw7R8HSs7GU7cj8dEyUwDQYJKoZIhvcNAQELBQAw
544
+ gYUxHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEtMCsGA1UECwwkY3Bh
545
+ bG1lckBwdW1wa2luLmxvY2FsIChDaHJpcyBQYWxtZXIpMTQwMgYDVQQDDCtta2Nl
546
+ cnQgY3BhbG1lckBwdW1wa2luLmxvY2FsIChDaHJpcyBQYWxtZXIpMB4XDTIzMDcx
547
+ MjE4MjIxNloXDTI1MTAxMjE4MjIxNlowWDEnMCUGA1UEChMebWtjZXJ0IGRldmVs
548
+ b3BtZW50IGNlcnRpZmljYXRlMS0wKwYDVQQLDCRjcGFsbWVyQHB1bXBraW4ubG9j
549
+ YWwgKENocmlzIFBhbG1lcikwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
550
+ AQDNDO8P4MI9jaqVcPtF8C4GgHnTP5EK3U9fgyGApKGxTpicMQkA6z4GXwUP/Fvq
551
+ 7RuCU9Wg7By5VetKIHF7FxkxWkUMrssr7mV8v6mRCh/a5GqDs14aj5ucjLQAJV74
552
+ tLAdrCiijQ1fkPWc82fob+LkfKWGCWw7Cxf6ZtEyC8jz/DnfQXUvOiZS729ndGF7
553
+ FobKRfIoirD+GI2NTYIp3LAUFSPR6HXTe7HAg8J81VoUKli8z504+FebfMmHePm/
554
+ zIfiI0njAj4czOlZD56/oLsV0WRUizFjafHHUFz1HVdfFw8Qf9IOOTydYOe8M5i0
555
+ lVbVO5G+HP+JDn3cr9MT41B9AgMBAAGjgaEwgZ4wDgYDVR0PAQH/BAQDAgWgMBMG
556
+ A1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQYMBaAFPpL4Q0O7Z7voTkjn2rrFCsf
557
+ s8TbMFYGA1UdEQRPME2CC2V4YW1wbGUuY29tgg0qLmV4YW1wbGUuY29tggxleGFt
558
+ cGxlLnRlc3SCCWxvY2FsaG9zdIcEfwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkq
559
+ hkiG9w0BAQsFAAOCAYEAMlOb7lrHuSxwcnAu7mL1ysTGqKn1d2TyDJAN5W8YFY+4
560
+ XLpofNkK2UzZ0t9LQRnuFUcjmfqmfplh5lpC7pKmtL4G5Qcdc+BczQWcopbxd728
561
+ sht9BKRkH+Bo1I+1WayKKNXW+5bsMv4CH641zxaMBlzjEnPvwKkNaGLMH3x5lIeX
562
+ GGgkKNXwVtINmyV+lTNVtu2IlHprxJGCjRfEuX7mEv6uRnqz3Wif+vgyh3MBgM/1
563
+ dUOsTBNH4a6Jl/9VPSOfRdQOStqIlwTa/J1bhTvivsYt1+eWjLnsQJLgZQqwKvYH
564
+ BJ30gAk1oNnuSkx9dHbx4mO+4mB9oIYUALXUYakb8JHTOnuMSj9qelVj5vjVxl9q
565
+ KRitptU+kLYRA4HSgUXrhDIm4Q6D/w8/ascPqQ3HxPIDFLe+gTofEjqnnsnQB29L
566
+ gWpI8l5/MtXAOMdW69eEovnADc2pgaiif0T+v9nNKBc5xfDZHnrnqIqVzQEwL5Qv
567
+ niQI8IsWD5LcQ1Eg7kCq
568
+ -----END CERTIFICATE-----`
569
+ )
570
+
571
+ func TestGetRenewalURL (t * testing.T ) {
572
+ leaf , _ := pem .Decode ([]byte (leafPEM ))
573
+ issuer , _ := pem .Decode ([]byte (issuerPEM ))
574
+
575
+ parsedLeaf , err := x509 .ParseCertificate (leaf .Bytes )
576
+ if err != nil {
577
+ t .Fatal (err )
578
+ }
579
+ parsedIssuer , err := x509 .ParseCertificate (issuer .Bytes )
580
+ if err != nil {
581
+ t .Fatal (err )
582
+ }
583
+
584
+ client := newTestClientWithMockDirectory ()
585
+ urlString , err := client .getRenewalURL (parsedLeaf , parsedIssuer )
586
+ if err != nil {
587
+ t .Fatal (err )
588
+ }
589
+
590
+ parsedURL , err := url .Parse (urlString )
591
+ if err != nil {
592
+ t .Fatal (err )
593
+ }
594
+ if scheme := parsedURL .Scheme ; scheme == "" {
595
+ t .Fatalf ("malformed URL scheme: %q from %q" , scheme , urlString )
596
+ }
597
+ if host := parsedURL .Host ; host == "" {
598
+ t .Fatalf ("malformed URL host: %q from %q" , host , urlString )
599
+ }
600
+ if parsedURL .RawQuery != "" {
601
+ t .Fatalf ("malformed URL: should not have a query" )
602
+ }
603
+ path := parsedURL .EscapedPath ()
604
+ slash := strings .LastIndex (path , "/" )
605
+ if slash == - 1 {
606
+ t .Fatalf ("malformed URL path: %q from %q" , path , urlString )
607
+ }
608
+ certIDPart := path [slash + 1 :]
609
+ if certIDPart == "" {
610
+ t .Fatalf ("missing certID part in URL path: %q from %q" , path , urlString )
611
+ }
612
+ }
613
+
614
+ func TestUnmarshalRenewalInfo (t * testing.T ) {
615
+ renewalInfoJSON := `{
616
+ "suggestedWindow": {
617
+ "start": "2021-01-03T00:00:00Z",
618
+ "end": "2021-01-07T00:00:00Z"
619
+ },
620
+ "explanationURL": "https://example.com/docs/example-mass-reissuance-event"
621
+ }`
622
+ expectedStart := time .Date (2021 , time .January , 3 , 0 , 0 , 0 , 0 , time .UTC )
623
+ expectedEnd := time .Date (2021 , time .January , 7 , 0 , 0 , 0 , 0 , time .UTC )
624
+
625
+ var info RenewalInfo
626
+ if err := json .Unmarshal ([]byte (renewalInfoJSON ), & info ); err != nil {
627
+ t .Fatal (err )
628
+ }
629
+ if _ , err := url .Parse (info .ExplanationURL ); err != nil {
630
+ t .Fatal (err )
631
+ }
632
+ if ! info .SuggestedWindow .Start .Equal (expectedStart ) {
633
+ t .Fatalf ("%v != %v" , expectedStart , info .SuggestedWindow .Start )
634
+ }
635
+ if ! info .SuggestedWindow .End .Equal (expectedEnd ) {
636
+ t .Fatalf ("%v != %v" , expectedEnd , info .SuggestedWindow .End )
637
+ }
638
+ }
639
+
500
640
func TestNonce_add (t * testing.T ) {
501
641
var c Client
502
642
c .addNonce (http.Header {"Replay-Nonce" : {"nonce" }})
0 commit comments