mirror of
https://github.com/golang/go.git
synced 2026-06-28 03:40:37 +00:00
crypto/x509: add RawSignatureAlgorithm
Fixes #76133 Change-Id: I7889aeff2ed197ee15f2ce7689b99b936a6a6964 Reviewed-on: https://go-review.googlesource.com/c/go/+/778660 LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Auto-Submit: Filippo Valsorda <filippo@golang.org> Reviewed-by: Austin Clements <austin@google.com> Reviewed-by: Roland Shoemaker <roland@golang.org>
This commit is contained in:
parent
e62d3e6e89
commit
6997bcd820
5 changed files with 121 additions and 11 deletions
3
api/next/76133.txt
Normal file
3
api/next/76133.txt
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
pkg crypto/x509, type Certificate struct, RawSignatureAlgorithm []uint8 #76133
|
||||
pkg crypto/x509, type CertificateRequest struct, RawSignatureAlgorithm []uint8 #76133
|
||||
pkg crypto/x509, type RevocationList struct, RawSignatureAlgorithm []uint8 #76133
|
||||
4
doc/next/6-stdlib/99-minor/crypto/x509/76133.md
Normal file
4
doc/next/6-stdlib/99-minor/crypto/x509/76133.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
The new [Certificate.RawSignatureAlgorithm], [CertificateRequest.RawSignatureAlgorithm],
|
||||
and [RevocationList.RawSignatureAlgorithm] fields expose the DER-encoded
|
||||
AlgorithmIdentifier of the signature algorithm, including when the
|
||||
SignatureAlgorithm field is [UnknownSignatureAlgorithm].
|
||||
|
|
@ -936,7 +936,11 @@ func parseCertificate(der []byte) (*Certificate, error) {
|
|||
cert.SerialNumber = serial
|
||||
|
||||
var sigAISeq cryptobyte.String
|
||||
if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
if !tbs.ReadASN1Element(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
return nil, errors.New("x509: malformed signature algorithm identifier")
|
||||
}
|
||||
cert.RawSignatureAlgorithm = sigAISeq
|
||||
if !sigAISeq.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
return nil, errors.New("x509: malformed signature algorithm identifier")
|
||||
}
|
||||
// Before parsing the inner algorithm identifier, extract
|
||||
|
|
@ -1143,7 +1147,11 @@ func ParseRevocationList(der []byte) (*RevocationList, error) {
|
|||
}
|
||||
|
||||
var sigAISeq cryptobyte.String
|
||||
if !tbs.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
if !tbs.ReadASN1Element(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
return nil, errors.New("x509: malformed signature algorithm identifier")
|
||||
}
|
||||
rl.RawSignatureAlgorithm = sigAISeq
|
||||
if !sigAISeq.ReadASN1(&sigAISeq, cryptobyte_asn1.SEQUENCE) {
|
||||
return nil, errors.New("x509: malformed signature algorithm identifier")
|
||||
}
|
||||
// Before parsing the inner algorithm identifier, extract
|
||||
|
|
|
|||
|
|
@ -707,6 +707,7 @@ type Certificate struct {
|
|||
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
|
||||
RawSubject []byte // DER encoded Subject
|
||||
RawIssuer []byte // DER encoded Issuer
|
||||
RawSignatureAlgorithm []byte // DER encoded AlgorithmIdentifier
|
||||
|
||||
Signature []byte
|
||||
SignatureAlgorithm SignatureAlgorithm
|
||||
|
|
@ -1914,6 +1915,7 @@ type CertificateRequest struct {
|
|||
RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content.
|
||||
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
|
||||
RawSubject []byte // DER encoded Subject.
|
||||
RawSignatureAlgorithm []byte // DER encoded AlgorithmIdentifier.
|
||||
|
||||
Version int
|
||||
Signature []byte
|
||||
|
|
@ -1966,8 +1968,12 @@ type tbsCertificateRequest struct {
|
|||
type certificateRequest struct {
|
||||
Raw asn1.RawContent
|
||||
TBSCSR tbsCertificateRequest
|
||||
SignatureAlgorithm pkix.AlgorithmIdentifier
|
||||
SignatureValue asn1.BitString
|
||||
SignatureAlgorithm struct {
|
||||
Raw asn1.RawContent
|
||||
Algorithm asn1.ObjectIdentifier
|
||||
Parameters asn1.RawValue `asn1:"optional"`
|
||||
}
|
||||
SignatureValue asn1.BitString
|
||||
}
|
||||
|
||||
// oidExtensionRequest is a PKCS #9 OBJECT IDENTIFIER that indicates requested
|
||||
|
|
@ -2202,11 +2208,12 @@ func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return asn1.Marshal(certificateRequest{
|
||||
TBSCSR: tbsCSR,
|
||||
SignatureAlgorithm: algorithmIdentifier,
|
||||
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
|
||||
})
|
||||
cr := certificateRequest{}
|
||||
cr.TBSCSR = tbsCSR
|
||||
cr.SignatureAlgorithm.Algorithm = algorithmIdentifier.Algorithm
|
||||
cr.SignatureAlgorithm.Parameters = algorithmIdentifier.Parameters
|
||||
cr.SignatureValue = asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}
|
||||
return asn1.Marshal(cr)
|
||||
}
|
||||
|
||||
// ParseCertificateRequest parses a single certificate request from the
|
||||
|
|
@ -2230,9 +2237,13 @@ func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error
|
|||
RawTBSCertificateRequest: in.TBSCSR.Raw,
|
||||
RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw,
|
||||
RawSubject: in.TBSCSR.Subject.FullBytes,
|
||||
RawSignatureAlgorithm: in.SignatureAlgorithm.Raw,
|
||||
|
||||
Signature: in.SignatureValue.RightAlign(),
|
||||
SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm),
|
||||
Signature: in.SignatureValue.RightAlign(),
|
||||
SignatureAlgorithm: getSignatureAlgorithmFromAI(pkix.AlgorithmIdentifier{
|
||||
Algorithm: in.SignatureAlgorithm.Algorithm,
|
||||
Parameters: in.SignatureAlgorithm.Parameters,
|
||||
}),
|
||||
|
||||
PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm),
|
||||
|
||||
|
|
@ -2327,6 +2338,9 @@ type RevocationList struct {
|
|||
RawTBSRevocationList []byte
|
||||
// RawIssuer contains the DER encoded Issuer.
|
||||
RawIssuer []byte
|
||||
// RawSignatureAlgorithm contains the DER encoded signature algorithm as a
|
||||
// PKIX AlgorithmIdentifier.
|
||||
RawSignatureAlgorithm []byte
|
||||
|
||||
// Issuer contains the DN of the issuing certificate.
|
||||
Issuer pkix.Name
|
||||
|
|
|
|||
|
|
@ -3506,6 +3506,87 @@ Qc4=
|
|||
}
|
||||
}
|
||||
|
||||
func TestRawSignatureAlgorithm(t *testing.T) {
|
||||
// checkAI verifies that raw is a DER-encoded AlgorithmIdentifier with the
|
||||
// expected OID.
|
||||
checkAI := func(t *testing.T, raw []byte, wantOID asn1.ObjectIdentifier) {
|
||||
t.Helper()
|
||||
if len(raw) == 0 {
|
||||
t.Fatal("RawSignatureAlgorithm is empty")
|
||||
}
|
||||
var ai pkix.AlgorithmIdentifier
|
||||
rest, err := asn1.Unmarshal(raw, &ai)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to unmarshal RawSignatureAlgorithm: %s", err)
|
||||
}
|
||||
if len(rest) != 0 {
|
||||
t.Fatalf("trailing data after RawSignatureAlgorithm: %x", rest)
|
||||
}
|
||||
if !ai.Algorithm.Equal(wantOID) {
|
||||
t.Fatalf("unexpected OID: got %v, want %v", ai.Algorithm, wantOID)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("Certificate", func(t *testing.T) {
|
||||
p, _ := pem.Decode([]byte(pemCertificate))
|
||||
cert, err := ParseCertificate(p.Bytes)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse certificate: %s", err)
|
||||
}
|
||||
checkAI(t, cert.RawSignatureAlgorithm, oidSignatureSHA256WithRSA)
|
||||
})
|
||||
|
||||
priv, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to generate key: %s", err)
|
||||
}
|
||||
|
||||
t.Run("CertificateRequest", func(t *testing.T) {
|
||||
csrDER, err := CreateCertificateRequest(rand.Reader, &CertificateRequest{}, priv)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create CSR: %s", err)
|
||||
}
|
||||
csr, err := ParseCertificateRequest(csrDER)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse CSR: %s", err)
|
||||
}
|
||||
checkAI(t, csr.RawSignatureAlgorithm, oidSignatureECDSAWithSHA256)
|
||||
})
|
||||
|
||||
t.Run("RevocationList", func(t *testing.T) {
|
||||
issuerTmpl := &Certificate{
|
||||
SerialNumber: big.NewInt(1),
|
||||
Subject: pkix.Name{CommonName: "issuer"},
|
||||
NotBefore: time.Now(),
|
||||
NotAfter: time.Now().Add(time.Hour),
|
||||
KeyUsage: KeyUsageCRLSign,
|
||||
IsCA: true,
|
||||
BasicConstraintsValid: true,
|
||||
}
|
||||
issuerDER, err := CreateCertificate(rand.Reader, issuerTmpl, issuerTmpl, priv.Public(), priv)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create issuer: %s", err)
|
||||
}
|
||||
issuer, err := ParseCertificate(issuerDER)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse issuer: %s", err)
|
||||
}
|
||||
crlDER, err := CreateRevocationList(rand.Reader, &RevocationList{
|
||||
Number: big.NewInt(1),
|
||||
ThisUpdate: time.Now(),
|
||||
NextUpdate: time.Now().Add(time.Hour),
|
||||
}, issuer, priv)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to create CRL: %s", err)
|
||||
}
|
||||
crl, err := ParseRevocationList(crlDER)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to parse CRL: %s", err)
|
||||
}
|
||||
checkAI(t, crl.RawSignatureAlgorithm, oidSignatureECDSAWithSHA256)
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseCertificateRawEquals(t *testing.T) {
|
||||
p, _ := pem.Decode([]byte(pemCertificate))
|
||||
cert, err := ParseCertificate(p.Bytes)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue