smx509: avoid crypto/rand.Int to generate serial number #308

This commit is contained in:
Sun Yimin 2025-03-04 08:48:18 +08:00 committed by GitHub
parent d433e416fa
commit 89962cf1e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -26,7 +26,6 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/ed25519" "crypto/ed25519"
"crypto/elliptic" "crypto/elliptic"
cryptorand "crypto/rand"
"crypto/rsa" "crypto/rsa"
"crypto/sha1" "crypto/sha1"
"crypto/x509" "crypto/x509"
@ -118,7 +117,7 @@ func marshalPublicKey(pub any) (publicKeyBytes []byte, publicKeyAlgorithm pkix.A
case ed25519.PublicKey: case ed25519.PublicKey:
publicKeyBytes = pub publicKeyBytes = pub
publicKeyAlgorithm.Algorithm = oidPublicKeyEd25519 publicKeyAlgorithm.Algorithm = oidPublicKeyEd25519
case *sdkecdh.PublicKey: case *sdkecdh.PublicKey:
publicKeyBytes = pub.Bytes() publicKeyBytes = pub.Bytes()
if pub.Curve() == sdkecdh.X25519() { if pub.Curve() == sdkecdh.X25519() {
publicKeyAlgorithm.Algorithm = oidPublicKeyX25519 publicKeyAlgorithm.Algorithm = oidPublicKeyX25519
@ -1542,25 +1541,19 @@ func CreateCertificate(rand io.Reader, template, parent, pub, priv any) ([]byte,
serialNumber := realTemplate.SerialNumber serialNumber := realTemplate.SerialNumber
if serialNumber == nil { if serialNumber == nil {
// Generate a serial number following RFC 5280 Section 4.1.2.2 if one is not provided. // Generate a serial number following RFC 5280, Section 4.1.2.2 if one
// Requirements: // is not provided. The serial number must be positive and at most 20
// - serial number must be positive // octets *when encoded*.
// - at most 20 octets when encoded serialBytes := make([]byte, 20)
maxSerial := big.NewInt(1).Lsh(big.NewInt(1), 20*8) if _, err := io.ReadFull(rand, serialBytes); err != nil {
for { return nil, err
var err error
serialNumber, err = cryptorand.Int(rand, maxSerial)
if err != nil {
return nil, err
}
// If the serial is exactly 20 octets, check if the high bit of the first byte is set.
// If so, generate a new serial, since it will be padded with a leading 0 byte during
// encoding so that the serial is not interpreted as a negative integer, making it
// 21 octets.
if serialBytes := serialNumber.Bytes(); len(serialBytes) > 0 && (len(serialBytes) < 20 || serialBytes[0]&0x80 == 0) {
break
}
} }
// If the top bit is set, the serial will be padded with a leading zero
// byte during encoding, so that it's not interpreted as a negative
// integer. This padding would make the serial 21 octets so we clear the
// top bit to ensure the correct length in all cases.
serialBytes[0] &= 0b0111_1111
serialNumber = new(big.Int).SetBytes(serialBytes)
} }
// RFC 5280 Section 4.1.2.2: serial number must be positive // RFC 5280 Section 4.1.2.2: serial number must be positive