mirror of
https://github.com/golang/go
synced 2024-11-11 21:20:21 -07:00
crypto/x509: write exact BitLength in ASN.1 encoding for certificate KeyUsage
The encoded value of the certificate KeyUsage did contain additonal padding that was not present with other certificate generators. According to ITU-T X.690 the BitLength value should have no padding in a DER encoding. See discussion: https://groups.google.com/forum/#!topic/golang-nuts/dzaJ3hMpDcs This CL has been discussed at: http://golang.org/cl/168990043 Change-Id: I1eff3f441b0566966a2d279631901ad9287c917d Reviewed-on: https://go-review.googlesource.com/2255 Reviewed-by: Adam Langley <agl@golang.org>
This commit is contained in:
parent
d1210acffd
commit
2fe8eadc9a
@ -1135,6 +1135,26 @@ func reverseBitsInAByte(in byte) byte {
|
||||
return b3
|
||||
}
|
||||
|
||||
// asn1BitLength returns the bit-length of bitString by considering the
|
||||
// most-significant bit in a byte to be the "first" bit. This convention
|
||||
// matches ASN.1, but differs from almost everything else.
|
||||
func asn1BitLength(bitString []byte) int {
|
||||
bitLen := len(bitString) * 8
|
||||
|
||||
for i := range bitString {
|
||||
b := bitString[len(bitString)-i-1]
|
||||
|
||||
for bit := uint(0); bit < 8; bit++ {
|
||||
if (b>>bit)&1 == 1 {
|
||||
return bitLen
|
||||
}
|
||||
bitLen--
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
var (
|
||||
oidExtensionSubjectKeyId = []int{2, 5, 29, 14}
|
||||
oidExtensionKeyUsage = []int{2, 5, 29, 15}
|
||||
@ -1203,7 +1223,8 @@ func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
|
||||
l = 2
|
||||
}
|
||||
|
||||
ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: a[0:l], BitLength: l * 8})
|
||||
bitString := a[:l]
|
||||
ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
@ -1016,6 +1016,28 @@ func TestMaxPathLen(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestASN1BitLength(t *testing.T) {
|
||||
tests := []struct {
|
||||
bytes []byte
|
||||
bitLen int
|
||||
}{
|
||||
{nil, 0},
|
||||
{[]byte{0x00}, 0},
|
||||
{[]byte{0x00, 0x00}, 0},
|
||||
{[]byte{0xf0}, 4},
|
||||
{[]byte{0x88}, 5},
|
||||
{[]byte{0xff}, 8},
|
||||
{[]byte{0xff, 0x80}, 9},
|
||||
{[]byte{0xff, 0x81}, 16},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
if got := asn1BitLength(test.bytes); got != test.bitLen {
|
||||
t.Errorf("#%d: calculated bit-length of %d for %x, wanted %d", i, got, test.bytes, test.bitLen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This CSR was generated with OpenSSL:
|
||||
// openssl req -out CSR.csr -new -newkey rsa:2048 -nodes -keyout privateKey.key -config openssl.cnf
|
||||
//
|
||||
|
Loading…
Reference in New Issue
Block a user