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}
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
}
}
}
+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
//