...

Source file src/github.com/letsencrypt/boulder/test/integration/bad_key_test.go

Documentation: github.com/letsencrypt/boulder/test/integration

     1  //go:build integration
     2  
     3  package integration
     4  
     5  import (
     6  	"crypto/rand"
     7  	"crypto/rsa"
     8  	"crypto/x509"
     9  	"crypto/x509/pkix"
    10  	"math/big"
    11  	"testing"
    12  
    13  	"github.com/eggsampler/acme/v3"
    14  
    15  	"github.com/letsencrypt/boulder/test"
    16  )
    17  
    18  // TestFermat ensures that a certificate public key which can be factored using
    19  // less than 100 rounds of Fermat's Algorithm is rejected.
    20  func TestFermat(t *testing.T) {
    21  	t.Parallel()
    22  
    23  	type testCase struct {
    24  		name string
    25  		p    string
    26  		q    string
    27  	}
    28  
    29  	testCases := []testCase{
    30  		{
    31  			name: "canon printer (2048 bit, 1 round)",
    32  			p:    "155536235030272749691472293262418471207550926406427515178205576891522284497518443889075039382254334975506248481615035474816604875321501901699955105345417152355947783063521554077194367454070647740704883461064399268622437721385112646454393005862535727615809073410746393326688230040267160616554768771412289114449",
    33  			q:    "155536235030272749691472293262418471207550926406427515178205576891522284497518443889075039382254334975506248481615035474816604875321501901699955105345417152355947783063521554077194367454070647740704883461064399268622437721385112646454393005862535727615809073410746393326688230040267160616554768771412289114113",
    34  		},
    35  		{
    36  			name: "innsbruck printer (4096 bit, 1 round)",
    37  			p:    "25868808535211632564072019392873831934145242707953960515208595626279836366691068618582894100813803673421320899654654938470888358089618966238341690624345530870988951109006149164192566967552401505863871260691612081236189439839963332690997129144163260418447718577834226720411404568398865166471102885763673744513186211985402019037772108416694793355840983833695882936201196462579254234744648546792097397517107797153785052856301942321429858537224127598198913168345965493941246097657533085617002572245972336841716321849601971924830462771411171570422802773095537171762650402420866468579928479284978914972383512240254605625661",
    38  			q:    "25868808535211632564072019392873831934145242707953960515208595626279836366691068618582894100813803673421320899654654938470888358089618966238341690624345530870988951109006149164192566967552401505863871260691612081236189439839963332690997129144163260418447718577834226720411404568398865166471102885763673744513186211985402019037772108416694793355840983833695882936201196462579254234744648546792097397517107797153785052856301942321429858537224127598198913168345965493941246097657533085617002572245972336841716321849601971924830462771411171570422802773095537171762650402420866468579928479284978914972383512240254605624819",
    39  		},
    40  		// Ideally we'd have a 2408-bit, nearly-100-rounds test case, but it turns
    41  		// out purposefully generating keys that require 1 < N < 100 rounds to be
    42  		// factored is surprisingly tricky.
    43  	}
    44  
    45  	for _, tc := range testCases {
    46  		tc := tc
    47  		t.Run(tc.name, func(t *testing.T) {
    48  			t.Parallel()
    49  
    50  			// Create a client and complete an HTTP-01 challenge for a fake domain.
    51  			c, err := makeClient()
    52  			test.AssertNotError(t, err, "creating acme client")
    53  
    54  			domain := random_domain()
    55  
    56  			order, err := c.Client.NewOrder(
    57  				c.Account, []acme.Identifier{{Type: "dns", Value: domain}})
    58  			test.AssertNotError(t, err, "creating new order")
    59  			test.AssertEquals(t, len(order.Authorizations), 1)
    60  
    61  			authUrl := order.Authorizations[0]
    62  
    63  			auth, err := c.Client.FetchAuthorization(c.Account, authUrl)
    64  			test.AssertNotError(t, err, "fetching authorization")
    65  
    66  			chal, ok := auth.ChallengeMap[acme.ChallengeTypeHTTP01]
    67  			test.Assert(t, ok, "getting HTTP-01 challenge")
    68  
    69  			err = addHTTP01Response(chal.Token, chal.KeyAuthorization)
    70  			defer delHTTP01Response(chal.Token)
    71  			test.AssertNotError(t, err, "adding HTTP-01 response")
    72  
    73  			chal, err = c.Client.UpdateChallenge(c.Account, chal)
    74  			test.AssertNotError(t, err, "updating HTTP-01 challenge")
    75  
    76  			// Reconstruct the public modulus N from the test case's prime factors.
    77  			p, ok := new(big.Int).SetString(tc.p, 10)
    78  			test.Assert(t, ok, "failed to create large prime")
    79  			q, ok := new(big.Int).SetString(tc.q, 10)
    80  			test.Assert(t, ok, "failed to create large prime")
    81  			n := new(big.Int).Mul(p, q)
    82  
    83  			// Reconstruct the private exponent D from the test case's prime factors.
    84  			p_1 := new(big.Int).Sub(p, big.NewInt(1))
    85  			q_1 := new(big.Int).Sub(q, big.NewInt(1))
    86  			field := new(big.Int).Mul(p_1, q_1)
    87  			d := new(big.Int).ModInverse(big.NewInt(65537), field)
    88  
    89  			// Create a CSR containing the reconstructed pubkey and signed with the
    90  			// reconstructed private key.
    91  			pubkey := rsa.PublicKey{
    92  				N: n,
    93  				E: 65537,
    94  			}
    95  
    96  			privkey := rsa.PrivateKey{
    97  				PublicKey: pubkey,
    98  				D:         d,
    99  				Primes:    []*big.Int{p, q},
   100  			}
   101  
   102  			csrDer, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
   103  				SignatureAlgorithm: x509.SHA256WithRSA,
   104  				PublicKeyAlgorithm: x509.RSA,
   105  				PublicKey:          &pubkey,
   106  				Subject:            pkix.Name{CommonName: domain},
   107  				DNSNames:           []string{domain},
   108  			}, &privkey)
   109  			test.AssertNotError(t, err, "creating CSR")
   110  
   111  			csr, err := x509.ParseCertificateRequest(csrDer)
   112  			test.AssertNotError(t, err, "parsing CSR")
   113  
   114  			// Finalizing the order should fail as we reject the public key.
   115  			_, err = c.Client.FinalizeOrder(c.Account, order, csr)
   116  			test.AssertError(t, err, "finalizing order")
   117  			test.AssertContains(t, err.Error(), "urn:ietf:params:acme:error:badCSR")
   118  			test.AssertContains(t, err.Error(), "key generated with factors too close together")
   119  		})
   120  	}
   121  }
   122  

View as plain text