diff --git a/pkg/x509/helper/helper.go b/pkg/x509/helper/helper.go new file mode 100644 index 0000000..ace3a68 --- /dev/null +++ b/pkg/x509/helper/helper.go @@ -0,0 +1,18 @@ +package helper + +import ( + "crypto/rand" + "fmt" + "math/big" +) + +// GenerateRandomSerial generates a random serial number to be used in X.509 certificates. The implementation is +// compliant to https://www.rfc-editor.org/rfc/rfc5280#section-4.1.2.2. +func GenerateRandomSerial() (*big.Int, error) { + serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 160)) + if err != nil { + return nil, fmt.Errorf("could not generate random serial number: %w", err) + } + + return serial, nil +} diff --git a/pkg/x509/helper/helper_test.go b/pkg/x509/helper/helper_test.go new file mode 100644 index 0000000..662a8f3 --- /dev/null +++ b/pkg/x509/helper/helper_test.go @@ -0,0 +1,15 @@ +package helper_test + +import ( + "testing" + + "git.cacert.org/cacert-gosigner/pkg/x509/helper" + "github.com/stretchr/testify/assert" +) + +func TestGenerateRandomSerial(t *testing.T) { + rnd, err := helper.GenerateRandomSerial() + assert.NoError(t, err) + assert.LessOrEqual(t, rnd.BitLen(), 160) + assert.GreaterOrEqual(t, rnd.BitLen(), 153) +} diff --git a/pkg/x509/revoking/revoking_test.go b/pkg/x509/revoking/revoking_test.go index 3bae694..bb8d934 100644 --- a/pkg/x509/revoking/revoking_test.go +++ b/pkg/x509/revoking/revoking_test.go @@ -28,12 +28,24 @@ import ( "math/big" "testing" + "git.cacert.org/cacert-gosigner/pkg/x509/helper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "git.cacert.org/cacert-gosigner/pkg/x509/revoking" ) +func randomSerial(t *testing.T) *big.Int { + t.Helper() + + serial, err := helper.GenerateRandomSerial() + if err != nil { + t.Fatal(err) + } + + return serial +} + type testRepo struct { crlNumber *big.Int revoked []pkix.RevokedCertificate @@ -107,17 +119,6 @@ func (b brokenRepoNoRevocations) NextCRLNumber() (*big.Int, error) { return nil, nil } -func randomSerial(t *testing.T) *big.Int { - t.Helper() - - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Fatalf("could not generate random serial number: %v", err) - } - - return serial -} - func TestX509Revoking_Revoke(t *testing.T) { testRepository := testRepo{revoked: make([]pkix.RevokedCertificate, 0), crlNumber: big.NewInt(0)} @@ -125,10 +126,7 @@ func TestX509Revoking_Revoke(t *testing.T) { r := revoking.NewX509Revoking(&testRepository, x509.ECDSAWithSHA256, caCertificate, caKey) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) revoke, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) assert.NoError(t, err) @@ -152,10 +150,7 @@ func TestX509Revoking_Revoke_BrokenRepo(t *testing.T) { r := revoking.NewX509Revoking(&brokenRepo{}, x509.SHA256WithRSA, caCertificate, caKey) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) revoke, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) @@ -174,12 +169,9 @@ func TestX509Revoking_CreateCRL(t *testing.T) { key, ) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) - _, err = r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) + _, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) require.NoError(t, err) crl, err := r.CreateCRL() @@ -212,12 +204,9 @@ func TestX509Revoking_CreateCRL_BrokenRepoNoRevocations(t *testing.T) { r := revoking.NewX509Revoking(&brokenRepoNoRevocations{}, x509.SHA256WithRSA, caCertificate, caKey) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) - _, err = r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) + _, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) require.NoError(t, err) crl, err := r.CreateCRL() @@ -232,12 +221,9 @@ func TestX509Revoking_CreateCRL_BrokenRepoNoCRLNumber(t *testing.T) { r := revoking.NewX509Revoking(&brokenRepoNoCrlNumber{}, x509.SHA256WithRSA, caCertificate, caKey) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) - _, err = r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) + _, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) require.NoError(t, err) crl, err := r.CreateCRL() @@ -257,12 +243,9 @@ func TestX509Revoking_CreateCRL_WrongAlgorithm(t *testing.T) { key, ) - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Errorf("could not create random serial: %v", err) - } + serial := randomSerial(t) - _, err = r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) + _, err := r.Revoke(revoking.NewRevokeCertificate(serial, revoking.CRLReasonKeyCompromise)) require.NoError(t, err) crl, err := r.CreateCRL() diff --git a/pkg/x509/signing/signing_test.go b/pkg/x509/signing/signing_test.go index cc8b3b7..3fd186a 100644 --- a/pkg/x509/signing/signing_test.go +++ b/pkg/x509/signing/signing_test.go @@ -28,11 +28,23 @@ import ( "testing" "time" + "git.cacert.org/cacert-gosigner/pkg/x509/helper" "github.com/stretchr/testify/assert" "git.cacert.org/cacert-gosigner/pkg/x509/signing" ) +func randomSerial(t *testing.T) *big.Int { + t.Helper() + + serial, err := helper.GenerateRandomSerial() + if err != nil { + t.Fatal(err) + } + + return serial +} + type testRepo struct { certs map[string]x509.Certificate } @@ -53,17 +65,6 @@ func newTestSignerResponse(certificate *x509.Certificate) *signing.SignerRespons return &signing.SignerResponse{Certificate: certificate} } -func randomSerial(t *testing.T) *big.Int { - t.Helper() - - serial, err := rand.Int(rand.Reader, new(big.Int).Lsh(big.NewInt(1), 128)) - if err != nil { - t.Fatalf("could not generate random serial number: %v", err) - } - - return serial -} - func (s *testSigner) SignCertificate(request *signing.SignerRequest) (*signing.SignerResponse, error) { startDate := time.Now().Add(-1 * time.Minute) template := &x509.Certificate{