@@ -27,6 +27,7 @@ import (
27
27
"crypto/ecdsa"
28
28
"crypto/ed25519"
29
29
"crypto/elliptic"
30
+ cryptorand "crypto/rand"
30
31
"crypto/rsa"
31
32
"crypto/sha1"
32
33
"crypto/x509/pkix"
@@ -1655,6 +1656,9 @@ var emptyASN1Subject = []byte{0x30, 0}
1655
1656
// If SubjectKeyId from template is empty and the template is a CA, SubjectKeyId
1656
1657
// will be generated from the hash of the public key.
1657
1658
//
1659
+ // If template.SerialNumber is nil, a serial number will be generated which
1660
+ // conforms to RFC 5280, Section 4.1.2.2 using entropy from rand.
1661
+ //
1658
1662
// The PolicyIdentifier and Policies fields can both be used to marshal certificate
1659
1663
// policy OIDs. By default, only the Policies is marshaled, but if the
1660
1664
// GODEBUG setting "x509usepolicies" has the value "0", the PolicyIdentifiers field will
@@ -1667,16 +1671,35 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
1667
1671
return nil , errors .New ("x509: certificate private key does not implement crypto.Signer" )
1668
1672
}
1669
1673
1670
- if template .SerialNumber == nil {
1671
- return nil , errors .New ("x509: no SerialNumber given" )
1674
+ serialNumber := template .SerialNumber
1675
+ if serialNumber == nil {
1676
+ // Generate a serial number following RFC 5280 Section 4.1.2.2 if one is not provided.
1677
+ // Requirements:
1678
+ // - serial number must be positive
1679
+ // - at most 20 octets when encoded
1680
+ maxSerial := big .NewInt (1 ).Lsh (big .NewInt (1 ), 20 * 8 )
1681
+ for {
1682
+ var err error
1683
+ serialNumber , err = cryptorand .Int (rand , maxSerial )
1684
+ if err != nil {
1685
+ return nil , err
1686
+ }
1687
+ // If the serial is exactly 20 octets, check if the high bit of the first byte is set.
1688
+ // If so, generate a new serial, since it will be padded with a leading 0 byte during
1689
+ // encoding so that the serial is not interpreted as a negative integer, making it
1690
+ // 21 octets.
1691
+ if serialBytes := serialNumber .Bytes (); len (serialBytes ) > 0 && (len (serialBytes ) < 20 || serialBytes [0 ]& 0x80 == 0 ) {
1692
+ break
1693
+ }
1694
+ }
1672
1695
}
1673
1696
1674
1697
// RFC 5280 Section 4.1.2.2: serial number must positive
1675
1698
//
1676
1699
// We _should_ also restrict serials to <= 20 octets, but it turns out a lot of people
1677
1700
// get this wrong, in part because the encoding can itself alter the length of the
1678
1701
// serial. For now we accept these non-conformant serials.
1679
- if template . SerialNumber .Sign () == - 1 {
1702
+ if serialNumber .Sign () == - 1 {
1680
1703
return nil , errors .New ("x509: serial number must be positive" )
1681
1704
}
1682
1705
@@ -1740,7 +1763,7 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv
1740
1763
encodedPublicKey := asn1.BitString {BitLength : len (publicKeyBytes ) * 8 , Bytes : publicKeyBytes }
1741
1764
c := tbsCertificate {
1742
1765
Version : 2 ,
1743
- SerialNumber : template . SerialNumber ,
1766
+ SerialNumber : serialNumber ,
1744
1767
SignatureAlgorithm : algorithmIdentifier ,
1745
1768
Issuer : asn1.RawValue {FullBytes : asn1Issuer },
1746
1769
Validity : validity {template .NotBefore .UTC (), template .NotAfter .UTC ()},
0 commit comments