frp/vendor/github.com/tjfoc/gmsm/sm2/x509.go
2017-11-01 16:21:57 +08:00

2527 lines
76 KiB
Go

/*
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// crypto/x509 add sm2 support
package sm2
import (
"bytes"
"crypto"
"crypto/dsa"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/md5"
"crypto/rand"
"crypto/rsa"
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"crypto/x509/pkix"
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
"hash"
"io"
"io/ioutil"
"math/big"
"net"
"os"
"strconv"
"time"
"github.com/tjfoc/gmsm/sm3"
"golang.org/x/crypto/ripemd160"
"golang.org/x/crypto/sha3"
)
// pkixPublicKey reflects a PKIX public key structure. See SubjectPublicKeyInfo
// in RFC 3280.
type pkixPublicKey struct {
Algo pkix.AlgorithmIdentifier
BitString asn1.BitString
}
// ParsePKIXPublicKey parses a DER encoded public key. These values are
// typically found in PEM blocks with "BEGIN PUBLIC KEY".
//
// Supported key types include RSA, DSA, and ECDSA. Unknown key
// types result in an error.
//
// On success, pub will be of type *rsa.PublicKey, *dsa.PublicKey,
// or *ecdsa.PublicKey.
func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err error) {
var pki publicKeyInfo
if rest, err := asn1.Unmarshal(derBytes, &pki); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after ASN.1 of public-key")
}
algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm)
if algo == UnknownPublicKeyAlgorithm {
return nil, errors.New("x509: unknown public key algorithm")
}
return parsePublicKey(algo, &pki)
}
func marshalPublicKey(pub interface{}) (publicKeyBytes []byte, publicKeyAlgorithm pkix.AlgorithmIdentifier, err error) {
switch pub := pub.(type) {
case *rsa.PublicKey:
publicKeyBytes, err = asn1.Marshal(rsaPublicKey{
N: pub.N,
E: pub.E,
})
if err != nil {
return nil, pkix.AlgorithmIdentifier{}, err
}
publicKeyAlgorithm.Algorithm = oidPublicKeyRSA
// This is a NULL parameters value which is required by
// https://tools.ietf.org/html/rfc3279#section-2.3.1.
publicKeyAlgorithm.Parameters = asn1.RawValue{
Tag: 5,
}
case *ecdsa.PublicKey:
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
oid, ok := oidFromNamedCurve(pub.Curve)
if !ok {
return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported elliptic curve")
}
publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
var paramBytes []byte
paramBytes, err = asn1.Marshal(oid)
if err != nil {
return
}
publicKeyAlgorithm.Parameters.FullBytes = paramBytes
case *PublicKey:
publicKeyBytes = elliptic.Marshal(pub.Curve, pub.X, pub.Y)
oid, ok := oidFromNamedCurve(pub.Curve)
if !ok {
return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: unsupported SM2 curve")
}
publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA
var paramBytes []byte
paramBytes, err = asn1.Marshal(oid)
if err != nil {
return
}
publicKeyAlgorithm.Parameters.FullBytes = paramBytes
default:
return nil, pkix.AlgorithmIdentifier{}, errors.New("x509: only RSA and ECDSA(SM2) public keys supported")
}
return publicKeyBytes, publicKeyAlgorithm, nil
}
// MarshalPKIXPublicKey serialises a public key to DER-encoded PKIX format.
func MarshalPKIXPublicKey(pub interface{}) ([]byte, error) {
var publicKeyBytes []byte
var publicKeyAlgorithm pkix.AlgorithmIdentifier
var err error
if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil {
return nil, err
}
pkix := pkixPublicKey{
Algo: publicKeyAlgorithm,
BitString: asn1.BitString{
Bytes: publicKeyBytes,
BitLength: 8 * len(publicKeyBytes),
},
}
ret, _ := asn1.Marshal(pkix)
return ret, nil
}
// These structures reflect the ASN.1 structure of X.509 certificates.:
type certificate struct {
Raw asn1.RawContent
TBSCertificate tbsCertificate
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}
type tbsCertificate struct {
Raw asn1.RawContent
Version int `asn1:"optional,explicit,default:0,tag:0"`
SerialNumber *big.Int
SignatureAlgorithm pkix.AlgorithmIdentifier
Issuer asn1.RawValue
Validity validity
Subject asn1.RawValue
PublicKey publicKeyInfo
UniqueId asn1.BitString `asn1:"optional,tag:1"`
SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
Extensions []pkix.Extension `asn1:"optional,explicit,tag:3"`
}
type dsaAlgorithmParameters struct {
P, Q, G *big.Int
}
type dsaSignature struct {
R, S *big.Int
}
type ecdsaSignature dsaSignature
type validity struct {
NotBefore, NotAfter time.Time
}
type publicKeyInfo struct {
Raw asn1.RawContent
Algorithm pkix.AlgorithmIdentifier
PublicKey asn1.BitString
}
// RFC 5280, 4.2.1.1
type authKeyId struct {
Id []byte `asn1:"optional,tag:0"`
}
type SignatureAlgorithm int
type Hash uint
func init() {
RegisterHash(MD4, nil)
RegisterHash(MD5, md5.New)
RegisterHash(SHA1, sha1.New)
RegisterHash(SHA224, sha256.New224)
RegisterHash(SHA256, sha256.New)
RegisterHash(SHA384, sha512.New384)
RegisterHash(SHA512, sha512.New)
RegisterHash(MD5SHA1, nil)
RegisterHash(RIPEMD160, ripemd160.New)
RegisterHash(SHA3_224, sha3.New224)
RegisterHash(SHA3_256, sha3.New256)
RegisterHash(SHA3_384, sha3.New384)
RegisterHash(SHA3_512, sha3.New512)
RegisterHash(SHA512_224, sha512.New512_224)
RegisterHash(SHA512_256, sha512.New512_256)
RegisterHash(SM3, sm3.New)
}
// HashFunc simply returns the value of h so that Hash implements SignerOpts.
func (h Hash) HashFunc() crypto.Hash {
return crypto.Hash(h)
}
const (
MD4 Hash = 1 + iota // import golang.org/x/crypto/md4
MD5 // import crypto/md5
SHA1 // import crypto/sha1
SHA224 // import crypto/sha256
SHA256 // import crypto/sha256
SHA384 // import crypto/sha512
SHA512 // import crypto/sha512
MD5SHA1 // no implementation; MD5+SHA1 used for TLS RSA
RIPEMD160 // import golang.org/x/crypto/ripemd160
SHA3_224 // import golang.org/x/crypto/sha3
SHA3_256 // import golang.org/x/crypto/sha3
SHA3_384 // import golang.org/x/crypto/sha3
SHA3_512 // import golang.org/x/crypto/sha3
SHA512_224 // import crypto/sha512
SHA512_256 // import crypto/sha512
SM3
maxHash
)
var digestSizes = []uint8{
MD4: 16,
MD5: 16,
SHA1: 20,
SHA224: 28,
SHA256: 32,
SHA384: 48,
SHA512: 64,
SHA512_224: 28,
SHA512_256: 32,
SHA3_224: 28,
SHA3_256: 32,
SHA3_384: 48,
SHA3_512: 64,
MD5SHA1: 36,
RIPEMD160: 20,
SM3: 32,
}
// Size returns the length, in bytes, of a digest resulting from the given hash
// function. It doesn't require that the hash function in question be linked
// into the program.
func (h Hash) Size() int {
if h > 0 && h < maxHash {
return int(digestSizes[h])
}
panic("crypto: Size of unknown hash function")
}
var hashes = make([]func() hash.Hash, maxHash)
// New returns a new hash.Hash calculating the given hash function. New panics
// if the hash function is not linked into the binary.
func (h Hash) New() hash.Hash {
if h > 0 && h < maxHash {
f := hashes[h]
if f != nil {
return f()
}
}
panic("crypto: requested hash function #" + strconv.Itoa(int(h)) + " is unavailable")
}
// Available reports whether the given hash function is linked into the binary.
func (h Hash) Available() bool {
return h < maxHash && hashes[h] != nil
}
// RegisterHash registers a function that returns a new instance of the given
// hash function. This is intended to be called from the init function in
// packages that implement hash functions.
func RegisterHash(h Hash, f func() hash.Hash) {
if h >= maxHash {
panic("crypto: RegisterHash of unknown hash function")
}
hashes[h] = f
}
const (
UnknownSignatureAlgorithm SignatureAlgorithm = iota
MD2WithRSA
MD5WithRSA
// SM3WithRSA reserve
SHA1WithRSA
SHA256WithRSA
SHA384WithRSA
SHA512WithRSA
DSAWithSHA1
DSAWithSHA256
ECDSAWithSHA1
ECDSAWithSHA256
ECDSAWithSHA384
ECDSAWithSHA512
SHA256WithRSAPSS
SHA384WithRSAPSS
SHA512WithRSAPSS
SM2WithSM3
SM2WithSHA1
SM2WithSHA256
)
func (algo SignatureAlgorithm) isRSAPSS() bool {
switch algo {
case SHA256WithRSAPSS, SHA384WithRSAPSS, SHA512WithRSAPSS:
return true
default:
return false
}
}
var algoName = [...]string{
MD2WithRSA: "MD2-RSA",
MD5WithRSA: "MD5-RSA",
SHA1WithRSA: "SHA1-RSA",
// SM3WithRSA: "SM3-RSA", reserve
SHA256WithRSA: "SHA256-RSA",
SHA384WithRSA: "SHA384-RSA",
SHA512WithRSA: "SHA512-RSA",
SHA256WithRSAPSS: "SHA256-RSAPSS",
SHA384WithRSAPSS: "SHA384-RSAPSS",
SHA512WithRSAPSS: "SHA512-RSAPSS",
DSAWithSHA1: "DSA-SHA1",
DSAWithSHA256: "DSA-SHA256",
ECDSAWithSHA1: "ECDSA-SHA1",
ECDSAWithSHA256: "ECDSA-SHA256",
ECDSAWithSHA384: "ECDSA-SHA384",
ECDSAWithSHA512: "ECDSA-SHA512",
SM2WithSM3: "SM2-SM3",
SM2WithSHA1: "SM2-SHA1",
SM2WithSHA256: "SM2-SHA256",
}
func (algo SignatureAlgorithm) String() string {
if 0 < algo && int(algo) < len(algoName) {
return algoName[algo]
}
return strconv.Itoa(int(algo))
}
type PublicKeyAlgorithm int
const (
UnknownPublicKeyAlgorithm PublicKeyAlgorithm = iota
RSA
DSA
ECDSA
)
// OIDs for signature algorithms
//
// pkcs-1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 }
//
//
// RFC 3279 2.2.1 RSA Signature Algorithms
//
// md2WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 2 }
//
// md5WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 4 }
//
// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 5 }
//
// dsaWithSha1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) x9-57(10040) x9cm(4) 3 }
//
// RFC 3279 2.2.3 ECDSA Signature Algorithm
//
// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-x962(10045)
// signatures(4) ecdsa-with-SHA1(1)}
//
//
// RFC 4055 5 PKCS #1 Version 1.5
//
// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
//
// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
//
// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
//
//
// RFC 5758 3.1 DSA Signature Algorithms
//
// dsaWithSha256 OBJECT IDENTIFIER ::= {
// joint-iso-ccitt(2) country(16) us(840) organization(1) gov(101)
// csor(3) algorithms(4) id-dsa-with-sha2(3) 2}
//
// RFC 5758 3.2 ECDSA Signature Algorithm
//
// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
//
// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
//
// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
var (
oidSignatureMD2WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 2}
oidSignatureMD5WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 4}
oidSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 5}
oidSignatureSHA256WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 11}
oidSignatureSHA384WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 12}
oidSignatureSHA512WithRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 13}
oidSignatureRSAPSS = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 10}
oidSignatureDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 3}
oidSignatureDSAWithSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 2}
oidSignatureECDSAWithSHA1 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 1}
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}
oidSignatureECDSAWithSHA384 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 3}
oidSignatureECDSAWithSHA512 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 4}
oidSignatureSM2WithSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 501}
oidSignatureSM2WithSHA1 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 502}
oidSignatureSM2WithSHA256 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 503}
// oidSignatureSM3WithRSA = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 504}
oidSM3 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 401, 1}
oidSHA256 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 1}
oidSHA384 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 2}
oidSHA512 = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 2, 3}
oidMGF1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 8}
// oidISOSignatureSHA1WithRSA means the same as oidSignatureSHA1WithRSA
// but it's specified by ISO. Microsoft's makecert.exe has been known
// to produce certificates with this OID.
oidISOSignatureSHA1WithRSA = asn1.ObjectIdentifier{1, 3, 14, 3, 2, 29}
)
var signatureAlgorithmDetails = []struct {
algo SignatureAlgorithm
oid asn1.ObjectIdentifier
pubKeyAlgo PublicKeyAlgorithm
hash Hash
}{
{MD2WithRSA, oidSignatureMD2WithRSA, RSA, Hash(0) /* no value for MD2 */},
{MD5WithRSA, oidSignatureMD5WithRSA, RSA, MD5},
{SHA1WithRSA, oidSignatureSHA1WithRSA, RSA, SHA1},
{SHA1WithRSA, oidISOSignatureSHA1WithRSA, RSA, SHA1},
{SHA256WithRSA, oidSignatureSHA256WithRSA, RSA, SHA256},
{SHA384WithRSA, oidSignatureSHA384WithRSA, RSA, SHA384},
{SHA512WithRSA, oidSignatureSHA512WithRSA, RSA, SHA512},
{SHA256WithRSAPSS, oidSignatureRSAPSS, RSA, SHA256},
{SHA384WithRSAPSS, oidSignatureRSAPSS, RSA, SHA384},
{SHA512WithRSAPSS, oidSignatureRSAPSS, RSA, SHA512},
{DSAWithSHA1, oidSignatureDSAWithSHA1, DSA, SHA1},
{DSAWithSHA256, oidSignatureDSAWithSHA256, DSA, SHA256},
{ECDSAWithSHA1, oidSignatureECDSAWithSHA1, ECDSA, SHA1},
{ECDSAWithSHA256, oidSignatureECDSAWithSHA256, ECDSA, SHA256},
{ECDSAWithSHA384, oidSignatureECDSAWithSHA384, ECDSA, SHA384},
{ECDSAWithSHA512, oidSignatureECDSAWithSHA512, ECDSA, SHA512},
{SM2WithSM3, oidSignatureSM2WithSM3, ECDSA, SM3},
{SM2WithSHA1, oidSignatureSM2WithSHA1, ECDSA, SHA1},
{SM2WithSHA256, oidSignatureSM2WithSHA256, ECDSA, SHA256},
// {SM3WithRSA, oidSignatureSM3WithRSA, RSA, SM3},
}
// pssParameters reflects the parameters in an AlgorithmIdentifier that
// specifies RSA PSS. See https://tools.ietf.org/html/rfc3447#appendix-A.2.3
type pssParameters struct {
// The following three fields are not marked as
// optional because the default values specify SHA-1,
// which is no longer suitable for use in signatures.
Hash pkix.AlgorithmIdentifier `asn1:"explicit,tag:0"`
MGF pkix.AlgorithmIdentifier `asn1:"explicit,tag:1"`
SaltLength int `asn1:"explicit,tag:2"`
TrailerField int `asn1:"optional,explicit,tag:3,default:1"`
}
// rsaPSSParameters returns an asn1.RawValue suitable for use as the Parameters
// in an AlgorithmIdentifier that specifies RSA PSS.
func rsaPSSParameters(hashFunc Hash) asn1.RawValue {
var hashOID asn1.ObjectIdentifier
switch hashFunc {
case SHA256:
hashOID = oidSHA256
case SHA384:
hashOID = oidSHA384
case SHA512:
hashOID = oidSHA512
}
params := pssParameters{
Hash: pkix.AlgorithmIdentifier{
Algorithm: hashOID,
Parameters: asn1.RawValue{
Tag: 5, /* ASN.1 NULL */
},
},
MGF: pkix.AlgorithmIdentifier{
Algorithm: oidMGF1,
},
SaltLength: hashFunc.Size(),
TrailerField: 1,
}
mgf1Params := pkix.AlgorithmIdentifier{
Algorithm: hashOID,
Parameters: asn1.RawValue{
Tag: 5, /* ASN.1 NULL */
},
}
var err error
params.MGF.Parameters.FullBytes, err = asn1.Marshal(mgf1Params)
if err != nil {
panic(err)
}
serialized, err := asn1.Marshal(params)
if err != nil {
panic(err)
}
return asn1.RawValue{FullBytes: serialized}
}
func getSignatureAlgorithmFromAI(ai pkix.AlgorithmIdentifier) SignatureAlgorithm {
if !ai.Algorithm.Equal(oidSignatureRSAPSS) {
for _, details := range signatureAlgorithmDetails {
if ai.Algorithm.Equal(details.oid) {
return details.algo
}
}
return UnknownSignatureAlgorithm
}
// RSA PSS is special because it encodes important parameters
// in the Parameters.
var params pssParameters
if _, err := asn1.Unmarshal(ai.Parameters.FullBytes, &params); err != nil {
return UnknownSignatureAlgorithm
}
var mgf1HashFunc pkix.AlgorithmIdentifier
if _, err := asn1.Unmarshal(params.MGF.Parameters.FullBytes, &mgf1HashFunc); err != nil {
return UnknownSignatureAlgorithm
}
// PSS is greatly overburdened with options. This code forces
// them into three buckets by requiring that the MGF1 hash
// function always match the message hash function (as
// recommended in
// https://tools.ietf.org/html/rfc3447#section-8.1), that the
// salt length matches the hash length, and that the trailer
// field has the default value.
asn1NULL := []byte{0x05, 0x00}
if !bytes.Equal(params.Hash.Parameters.FullBytes, asn1NULL) ||
!params.MGF.Algorithm.Equal(oidMGF1) ||
!mgf1HashFunc.Algorithm.Equal(params.Hash.Algorithm) ||
!bytes.Equal(mgf1HashFunc.Parameters.FullBytes, asn1NULL) ||
params.TrailerField != 1 {
return UnknownSignatureAlgorithm
}
switch {
case params.Hash.Algorithm.Equal(oidSHA256) && params.SaltLength == 32:
return SHA256WithRSAPSS
case params.Hash.Algorithm.Equal(oidSHA384) && params.SaltLength == 48:
return SHA384WithRSAPSS
case params.Hash.Algorithm.Equal(oidSHA512) && params.SaltLength == 64:
return SHA512WithRSAPSS
}
return UnknownSignatureAlgorithm
}
// RFC 3279, 2.3 Public Key Algorithms
//
// pkcs-1 OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
// rsadsi(113549) pkcs(1) 1 }
//
// rsaEncryption OBJECT IDENTIFIER ::== { pkcs1-1 1 }
//
// id-dsa OBJECT IDENTIFIER ::== { iso(1) member-body(2) us(840)
// x9-57(10040) x9cm(4) 1 }
//
// RFC 5480, 2.1.1 Unrestricted Algorithm Identifier and Parameters
//
// id-ecPublicKey OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
var (
oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
oidPublicKeyDSA = asn1.ObjectIdentifier{1, 2, 840, 10040, 4, 1}
oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
)
func getPublicKeyAlgorithmFromOID(oid asn1.ObjectIdentifier) PublicKeyAlgorithm {
switch {
case oid.Equal(oidPublicKeyRSA):
return RSA
case oid.Equal(oidPublicKeyDSA):
return DSA
case oid.Equal(oidPublicKeyECDSA):
return ECDSA
}
return UnknownPublicKeyAlgorithm
}
// RFC 5480, 2.1.1.1. Named Curve
//
// secp224r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 33 }
//
// secp256r1 OBJECT IDENTIFIER ::= {
// iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
// prime(1) 7 }
//
// secp384r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 34 }
//
// secp521r1 OBJECT IDENTIFIER ::= {
// iso(1) identified-organization(3) certicom(132) curve(0) 35 }
//
// NB: secp256r1 is equivalent to prime256v1
var (
oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} // I get the SM2 ID through parsing the pem file generated by gmssl
)
func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
switch {
case oid.Equal(oidNamedCurveP224):
return elliptic.P224()
case oid.Equal(oidNamedCurveP256):
return elliptic.P256()
case oid.Equal(oidNamedCurveP384):
return elliptic.P384()
case oid.Equal(oidNamedCurveP521):
return elliptic.P521()
case oid.Equal(oidNamedCurveP256SM2):
return P256Sm2()
}
return nil
}
func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
switch curve {
case elliptic.P224():
return oidNamedCurveP224, true
case elliptic.P256():
return oidNamedCurveP256, true
case elliptic.P384():
return oidNamedCurveP384, true
case elliptic.P521():
return oidNamedCurveP521, true
case P256Sm2():
return oidNamedCurveP256SM2, true
}
return nil, false
}
// KeyUsage represents the set of actions that are valid for a given key. It's
// a bitmap of the KeyUsage* constants.
type KeyUsage int
const (
KeyUsageDigitalSignature KeyUsage = 1 << iota
KeyUsageContentCommitment
KeyUsageKeyEncipherment
KeyUsageDataEncipherment
KeyUsageKeyAgreement
KeyUsageCertSign
KeyUsageCRLSign
KeyUsageEncipherOnly
KeyUsageDecipherOnly
)
// RFC 5280, 4.2.1.12 Extended Key Usage
//
// anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 }
//
// id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
//
// id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 }
// id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 }
// id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 }
// id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
// id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 }
// id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 }
var (
oidExtKeyUsageAny = asn1.ObjectIdentifier{2, 5, 29, 37, 0}
oidExtKeyUsageServerAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 1}
oidExtKeyUsageClientAuth = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 2}
oidExtKeyUsageCodeSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 3}
oidExtKeyUsageEmailProtection = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 4}
oidExtKeyUsageIPSECEndSystem = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 5}
oidExtKeyUsageIPSECTunnel = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 6}
oidExtKeyUsageIPSECUser = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 7}
oidExtKeyUsageTimeStamping = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 8}
oidExtKeyUsageOCSPSigning = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 3, 9}
oidExtKeyUsageMicrosoftServerGatedCrypto = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 311, 10, 3, 3}
oidExtKeyUsageNetscapeServerGatedCrypto = asn1.ObjectIdentifier{2, 16, 840, 1, 113730, 4, 1}
)
// ExtKeyUsage represents an extended set of actions that are valid for a given key.
// Each of the ExtKeyUsage* constants define a unique action.
type ExtKeyUsage int
const (
ExtKeyUsageAny ExtKeyUsage = iota
ExtKeyUsageServerAuth
ExtKeyUsageClientAuth
ExtKeyUsageCodeSigning
ExtKeyUsageEmailProtection
ExtKeyUsageIPSECEndSystem
ExtKeyUsageIPSECTunnel
ExtKeyUsageIPSECUser
ExtKeyUsageTimeStamping
ExtKeyUsageOCSPSigning
ExtKeyUsageMicrosoftServerGatedCrypto
ExtKeyUsageNetscapeServerGatedCrypto
)
// extKeyUsageOIDs contains the mapping between an ExtKeyUsage and its OID.
var extKeyUsageOIDs = []struct {
extKeyUsage ExtKeyUsage
oid asn1.ObjectIdentifier
}{
{ExtKeyUsageAny, oidExtKeyUsageAny},
{ExtKeyUsageServerAuth, oidExtKeyUsageServerAuth},
{ExtKeyUsageClientAuth, oidExtKeyUsageClientAuth},
{ExtKeyUsageCodeSigning, oidExtKeyUsageCodeSigning},
{ExtKeyUsageEmailProtection, oidExtKeyUsageEmailProtection},
{ExtKeyUsageIPSECEndSystem, oidExtKeyUsageIPSECEndSystem},
{ExtKeyUsageIPSECTunnel, oidExtKeyUsageIPSECTunnel},
{ExtKeyUsageIPSECUser, oidExtKeyUsageIPSECUser},
{ExtKeyUsageTimeStamping, oidExtKeyUsageTimeStamping},
{ExtKeyUsageOCSPSigning, oidExtKeyUsageOCSPSigning},
{ExtKeyUsageMicrosoftServerGatedCrypto, oidExtKeyUsageMicrosoftServerGatedCrypto},
{ExtKeyUsageNetscapeServerGatedCrypto, oidExtKeyUsageNetscapeServerGatedCrypto},
}
func extKeyUsageFromOID(oid asn1.ObjectIdentifier) (eku ExtKeyUsage, ok bool) {
for _, pair := range extKeyUsageOIDs {
if oid.Equal(pair.oid) {
return pair.extKeyUsage, true
}
}
return
}
func oidFromExtKeyUsage(eku ExtKeyUsage) (oid asn1.ObjectIdentifier, ok bool) {
for _, pair := range extKeyUsageOIDs {
if eku == pair.extKeyUsage {
return pair.oid, true
}
}
return
}
// A Certificate represents an X.509 certificate.
type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
RawSubject []byte // DER encoded Subject
RawIssuer []byte // DER encoded Issuer
Signature []byte
SignatureAlgorithm SignatureAlgorithm
PublicKeyAlgorithm PublicKeyAlgorithm
PublicKey interface{}
Version int
SerialNumber *big.Int
Issuer pkix.Name
Subject pkix.Name
NotBefore, NotAfter time.Time // Validity bounds.
KeyUsage KeyUsage
// Extensions contains raw X.509 extensions. When parsing certificates,
// this can be used to extract non-critical extensions that are not
// parsed by this package. When marshaling certificates, the Extensions
// field is ignored, see ExtraExtensions.
Extensions []pkix.Extension
// ExtraExtensions contains extensions to be copied, raw, into any
// marshaled certificates. Values override any extensions that would
// otherwise be produced based on the other fields. The ExtraExtensions
// field is not populated when parsing certificates, see Extensions.
ExtraExtensions []pkix.Extension
// UnhandledCriticalExtensions contains a list of extension IDs that
// were not (fully) processed when parsing. Verify will fail if this
// slice is non-empty, unless verification is delegated to an OS
// library which understands all the critical extensions.
//
// Users can access these extensions using Extensions and can remove
// elements from this slice if they believe that they have been
// handled.
UnhandledCriticalExtensions []asn1.ObjectIdentifier
ExtKeyUsage []ExtKeyUsage // Sequence of extended key usages.
UnknownExtKeyUsage []asn1.ObjectIdentifier // Encountered extended key usages unknown to this package.
BasicConstraintsValid bool // if true then the next two fields are valid.
IsCA bool
MaxPathLen int
// MaxPathLenZero indicates that BasicConstraintsValid==true and
// MaxPathLen==0 should be interpreted as an actual maximum path length
// of zero. Otherwise, that combination is interpreted as MaxPathLen
// not being set.
MaxPathLenZero bool
SubjectKeyId []byte
AuthorityKeyId []byte
// RFC 5280, 4.2.2.1 (Authority Information Access)
OCSPServer []string
IssuingCertificateURL []string
// Subject Alternate Name values
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
// Name constraints
PermittedDNSDomainsCritical bool // if true then the name constraints are marked critical.
PermittedDNSDomains []string
// CRL Distribution Points
CRLDistributionPoints []string
PolicyIdentifiers []asn1.ObjectIdentifier
}
// ErrUnsupportedAlgorithm results from attempting to perform an operation that
// involves algorithms that are not currently implemented.
var ErrUnsupportedAlgorithm = errors.New("x509: cannot verify signature: algorithm unimplemented")
// An InsecureAlgorithmError
type InsecureAlgorithmError SignatureAlgorithm
func (e InsecureAlgorithmError) Error() string {
return fmt.Sprintf("x509: cannot verify signature: insecure algorithm %v", SignatureAlgorithm(e))
}
// ConstraintViolationError results when a requested usage is not permitted by
// a certificate. For example: checking a signature when the public key isn't a
// certificate signing key.
type ConstraintViolationError struct{}
func (ConstraintViolationError) Error() string {
return "x509: invalid signature: parent certificate cannot sign this kind of certificate"
}
func (c *Certificate) Equal(other *Certificate) bool {
return bytes.Equal(c.Raw, other.Raw)
}
// Entrust have a broken root certificate (CN=Entrust.net Certification
// Authority (2048)) which isn't marked as a CA certificate and is thus invalid
// according to PKIX.
// We recognise this certificate by its SubjectPublicKeyInfo and exempt it
// from the Basic Constraints requirement.
// See http://www.entrust.net/knowledge-base/technote.cfm?tn=7869
//
// TODO(agl): remove this hack once their reissued root is sufficiently
// widespread.
var entrustBrokenSPKI = []byte{
0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00,
0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01,
0x00, 0x97, 0xa3, 0x2d, 0x3c, 0x9e, 0xde, 0x05,
0xda, 0x13, 0xc2, 0x11, 0x8d, 0x9d, 0x8e, 0xe3,
0x7f, 0xc7, 0x4b, 0x7e, 0x5a, 0x9f, 0xb3, 0xff,
0x62, 0xab, 0x73, 0xc8, 0x28, 0x6b, 0xba, 0x10,
0x64, 0x82, 0x87, 0x13, 0xcd, 0x57, 0x18, 0xff,
0x28, 0xce, 0xc0, 0xe6, 0x0e, 0x06, 0x91, 0x50,
0x29, 0x83, 0xd1, 0xf2, 0xc3, 0x2a, 0xdb, 0xd8,
0xdb, 0x4e, 0x04, 0xcc, 0x00, 0xeb, 0x8b, 0xb6,
0x96, 0xdc, 0xbc, 0xaa, 0xfa, 0x52, 0x77, 0x04,
0xc1, 0xdb, 0x19, 0xe4, 0xae, 0x9c, 0xfd, 0x3c,
0x8b, 0x03, 0xef, 0x4d, 0xbc, 0x1a, 0x03, 0x65,
0xf9, 0xc1, 0xb1, 0x3f, 0x72, 0x86, 0xf2, 0x38,
0xaa, 0x19, 0xae, 0x10, 0x88, 0x78, 0x28, 0xda,
0x75, 0xc3, 0x3d, 0x02, 0x82, 0x02, 0x9c, 0xb9,
0xc1, 0x65, 0x77, 0x76, 0x24, 0x4c, 0x98, 0xf7,
0x6d, 0x31, 0x38, 0xfb, 0xdb, 0xfe, 0xdb, 0x37,
0x02, 0x76, 0xa1, 0x18, 0x97, 0xa6, 0xcc, 0xde,
0x20, 0x09, 0x49, 0x36, 0x24, 0x69, 0x42, 0xf6,
0xe4, 0x37, 0x62, 0xf1, 0x59, 0x6d, 0xa9, 0x3c,
0xed, 0x34, 0x9c, 0xa3, 0x8e, 0xdb, 0xdc, 0x3a,
0xd7, 0xf7, 0x0a, 0x6f, 0xef, 0x2e, 0xd8, 0xd5,
0x93, 0x5a, 0x7a, 0xed, 0x08, 0x49, 0x68, 0xe2,
0x41, 0xe3, 0x5a, 0x90, 0xc1, 0x86, 0x55, 0xfc,
0x51, 0x43, 0x9d, 0xe0, 0xb2, 0xc4, 0x67, 0xb4,
0xcb, 0x32, 0x31, 0x25, 0xf0, 0x54, 0x9f, 0x4b,
0xd1, 0x6f, 0xdb, 0xd4, 0xdd, 0xfc, 0xaf, 0x5e,
0x6c, 0x78, 0x90, 0x95, 0xde, 0xca, 0x3a, 0x48,
0xb9, 0x79, 0x3c, 0x9b, 0x19, 0xd6, 0x75, 0x05,
0xa0, 0xf9, 0x88, 0xd7, 0xc1, 0xe8, 0xa5, 0x09,
0xe4, 0x1a, 0x15, 0xdc, 0x87, 0x23, 0xaa, 0xb2,
0x75, 0x8c, 0x63, 0x25, 0x87, 0xd8, 0xf8, 0x3d,
0xa6, 0xc2, 0xcc, 0x66, 0xff, 0xa5, 0x66, 0x68,
0x55, 0x02, 0x03, 0x01, 0x00, 0x01,
}
// CheckSignatureFrom verifies that the signature on c is a valid signature
// from parent.
func (c *Certificate) CheckSignatureFrom(parent *Certificate) error {
// RFC 5280, 4.2.1.9:
// "If the basic constraints extension is not present in a version 3
// certificate, or the extension is present but the cA boolean is not
// asserted, then the certified public key MUST NOT be used to verify
// certificate signatures."
// (except for Entrust, see comment above entrustBrokenSPKI)
if (parent.Version == 3 && !parent.BasicConstraintsValid ||
parent.BasicConstraintsValid && !parent.IsCA) &&
!bytes.Equal(c.RawSubjectPublicKeyInfo, entrustBrokenSPKI) {
return ConstraintViolationError{}
}
if parent.KeyUsage != 0 && parent.KeyUsage&KeyUsageCertSign == 0 {
return ConstraintViolationError{}
}
if parent.PublicKeyAlgorithm == UnknownPublicKeyAlgorithm {
return ErrUnsupportedAlgorithm
}
// TODO(agl): don't ignore the path length constraint.
return parent.CheckSignature(c.SignatureAlgorithm, c.RawTBSCertificate, c.Signature)
}
// CheckSignature verifies that signature is a valid signature over signed from
// c's public key.
func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) error {
return checkSignature(algo, signed, signature, c.PublicKey)
}
// CheckSignature verifies that signature is a valid signature over signed from
// a crypto.PublicKey.
func checkSignature(algo SignatureAlgorithm, signed, signature []byte, publicKey crypto.PublicKey) (err error) {
var hashType Hash
switch algo {
case SHA1WithRSA, DSAWithSHA1, ECDSAWithSHA1, SM2WithSHA1:
hashType = SHA1
case SHA256WithRSA, SHA256WithRSAPSS, DSAWithSHA256, ECDSAWithSHA256, SM2WithSHA256:
hashType = SHA256
case SHA384WithRSA, SHA384WithRSAPSS, ECDSAWithSHA384:
hashType = SHA384
case SHA512WithRSA, SHA512WithRSAPSS, ECDSAWithSHA512:
hashType = SHA512
case MD2WithRSA, MD5WithRSA:
return InsecureAlgorithmError(algo)
case SM2WithSM3: // SM3WithRSA reserve
hashType = SM3
default:
return ErrUnsupportedAlgorithm
}
if !hashType.Available() {
return ErrUnsupportedAlgorithm
}
h := hashType.New()
h.Write(signed)
digest := h.Sum(nil)
switch pub := publicKey.(type) {
case *rsa.PublicKey:
if algo.isRSAPSS() {
return rsa.VerifyPSS(pub, crypto.Hash(hashType), digest, signature, &rsa.PSSOptions{SaltLength: rsa.PSSSaltLengthEqualsHash})
} else {
return rsa.VerifyPKCS1v15(pub, crypto.Hash(hashType), digest, signature)
}
case *dsa.PublicKey:
dsaSig := new(dsaSignature)
if rest, err := asn1.Unmarshal(signature, dsaSig); err != nil {
return err
} else if len(rest) != 0 {
return errors.New("x509: trailing data after DSA signature")
}
if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 {
return errors.New("x509: DSA signature contained zero or negative values")
}
if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) {
return errors.New("x509: DSA verification failure")
}
return
case *ecdsa.PublicKey:
ecdsaSig := new(ecdsaSignature)
if rest, err := asn1.Unmarshal(signature, ecdsaSig); err != nil {
return err
} else if len(rest) != 0 {
return errors.New("x509: trailing data after ECDSA signature")
}
if ecdsaSig.R.Sign() <= 0 || ecdsaSig.S.Sign() <= 0 {
return errors.New("x509: ECDSA signature contained zero or negative values")
}
switch pub.Curve {
case P256Sm2():
if !Verify(&PublicKey{
Curve: pub.Curve,
X: pub.X,
Y: pub.Y,
}, digest, ecdsaSig.R, ecdsaSig.S) {
return errors.New("x509: SM2 verification failure")
}
default:
if !ecdsa.Verify(pub, digest, ecdsaSig.R, ecdsaSig.S) {
return errors.New("x509: ECDSA verification failure")
}
}
return
}
return ErrUnsupportedAlgorithm
}
// CheckCRLSignature checks that the signature in crl is from c.
func (c *Certificate) CheckCRLSignature(crl *pkix.CertificateList) error {
algo := getSignatureAlgorithmFromAI(crl.SignatureAlgorithm)
return c.CheckSignature(algo, crl.TBSCertList.Raw, crl.SignatureValue.RightAlign())
}
type UnhandledCriticalExtension struct{}
func (h UnhandledCriticalExtension) Error() string {
return "x509: unhandled critical extension"
}
type basicConstraints struct {
IsCA bool `asn1:"optional"`
MaxPathLen int `asn1:"optional,default:-1"`
}
// RFC 5280 4.2.1.4
type policyInformation struct {
Policy asn1.ObjectIdentifier
// policyQualifiers omitted
}
// RFC 5280, 4.2.1.10
type nameConstraints struct {
Permitted []generalSubtree `asn1:"optional,tag:0"`
Excluded []generalSubtree `asn1:"optional,tag:1"`
}
type generalSubtree struct {
Name string `asn1:"tag:2,optional,ia5"`
}
// RFC 5280, 4.2.2.1
type authorityInfoAccess struct {
Method asn1.ObjectIdentifier
Location asn1.RawValue
}
// RFC 5280, 4.2.1.14
type distributionPoint struct {
DistributionPoint distributionPointName `asn1:"optional,tag:0"`
Reason asn1.BitString `asn1:"optional,tag:1"`
CRLIssuer asn1.RawValue `asn1:"optional,tag:2"`
}
type distributionPointName struct {
FullName asn1.RawValue `asn1:"optional,tag:0"`
RelativeName pkix.RDNSequence `asn1:"optional,tag:1"`
}
// asn1Null is the ASN.1 encoding of a NULL value.
var asn1Null = []byte{5, 0}
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, error) {
asn1Data := keyData.PublicKey.RightAlign()
switch algo {
case RSA:
// RSA public keys must have a NULL in the parameters
// (https://tools.ietf.org/html/rfc3279#section-2.3.1).
if !bytes.Equal(keyData.Algorithm.Parameters.FullBytes, asn1Null) {
return nil, errors.New("x509: RSA key missing NULL parameters")
}
p := new(rsaPublicKey)
rest, err := asn1.Unmarshal(asn1Data, p)
if err != nil {
return nil, err
}
if len(rest) != 0 {
return nil, errors.New("x509: trailing data after RSA public key")
}
if p.N.Sign() <= 0 {
return nil, errors.New("x509: RSA modulus is not a positive number")
}
if p.E <= 0 {
return nil, errors.New("x509: RSA public exponent is not a positive number")
}
pub := &rsa.PublicKey{
E: p.E,
N: p.N,
}
return pub, nil
case DSA:
var p *big.Int
rest, err := asn1.Unmarshal(asn1Data, &p)
if err != nil {
return nil, err
}
if len(rest) != 0 {
return nil, errors.New("x509: trailing data after DSA public key")
}
paramsData := keyData.Algorithm.Parameters.FullBytes
params := new(dsaAlgorithmParameters)
rest, err = asn1.Unmarshal(paramsData, params)
if err != nil {
return nil, err
}
if len(rest) != 0 {
return nil, errors.New("x509: trailing data after DSA parameters")
}
if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 {
return nil, errors.New("x509: zero or negative DSA parameter")
}
pub := &dsa.PublicKey{
Parameters: dsa.Parameters{
P: params.P,
Q: params.Q,
G: params.G,
},
Y: p,
}
return pub, nil
case ECDSA:
paramsData := keyData.Algorithm.Parameters.FullBytes
namedCurveOID := new(asn1.ObjectIdentifier)
rest, err := asn1.Unmarshal(paramsData, namedCurveOID)
if err != nil {
return nil, err
}
if len(rest) != 0 {
return nil, errors.New("x509: trailing data after ECDSA parameters")
}
namedCurve := namedCurveFromOID(*namedCurveOID)
if namedCurve == nil {
return nil, errors.New("x509: unsupported elliptic curve")
}
x, y := elliptic.Unmarshal(namedCurve, asn1Data)
if x == nil {
return nil, errors.New("x509: failed to unmarshal elliptic curve point")
}
pub := &ecdsa.PublicKey{
Curve: namedCurve,
X: x,
Y: y,
}
return pub, nil
default:
return nil, nil
}
}
func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err error) {
// RFC 5280, 4.2.1.6
// SubjectAltName ::= GeneralNames
//
// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
//
// GeneralName ::= CHOICE {
// otherName [0] OtherName,
// rfc822Name [1] IA5String,
// dNSName [2] IA5String,
// x400Address [3] ORAddress,
// directoryName [4] Name,
// ediPartyName [5] EDIPartyName,
// uniformResourceIdentifier [6] IA5String,
// iPAddress [7] OCTET STRING,
// registeredID [8] OBJECT IDENTIFIER }
var seq asn1.RawValue
var rest []byte
if rest, err = asn1.Unmarshal(value, &seq); err != nil {
return
} else if len(rest) != 0 {
err = errors.New("x509: trailing data after X.509 extension")
return
}
if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 {
err = asn1.StructuralError{Msg: "bad SAN sequence"}
return
}
rest = seq.Bytes
for len(rest) > 0 {
var v asn1.RawValue
rest, err = asn1.Unmarshal(rest, &v)
if err != nil {
return
}
switch v.Tag {
case 1:
emailAddresses = append(emailAddresses, string(v.Bytes))
case 2:
dnsNames = append(dnsNames, string(v.Bytes))
case 7:
switch len(v.Bytes) {
case net.IPv4len, net.IPv6len:
ipAddresses = append(ipAddresses, v.Bytes)
default:
err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes)))
return
}
}
}
return
}
func parseCertificate(in *certificate) (*Certificate, error) {
out := new(Certificate)
out.Raw = in.Raw
out.RawTBSCertificate = in.TBSCertificate.Raw
out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw
out.RawSubject = in.TBSCertificate.Subject.FullBytes
out.RawIssuer = in.TBSCertificate.Issuer.FullBytes
out.Signature = in.SignatureValue.RightAlign()
out.SignatureAlgorithm =
getSignatureAlgorithmFromAI(in.TBSCertificate.SignatureAlgorithm)
out.PublicKeyAlgorithm =
getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm)
var err error
out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey)
if err != nil {
return nil, err
}
out.Version = in.TBSCertificate.Version + 1
out.SerialNumber = in.TBSCertificate.SerialNumber
var issuer, subject pkix.RDNSequence
if rest, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 subject")
}
if rest, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 subject")
}
out.Issuer.FillFromRDNSequence(&issuer)
out.Subject.FillFromRDNSequence(&subject)
out.NotBefore = in.TBSCertificate.Validity.NotBefore
out.NotAfter = in.TBSCertificate.Validity.NotAfter
for _, e := range in.TBSCertificate.Extensions {
out.Extensions = append(out.Extensions, e)
unhandled := false
if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 {
switch e.Id[3] {
case 15:
// RFC 5280, 4.2.1.3
var usageBits asn1.BitString
if rest, err := asn1.Unmarshal(e.Value, &usageBits); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 KeyUsage")
}
var usage int
for i := 0; i < 9; i++ {
if usageBits.At(i) != 0 {
usage |= 1 << uint(i)
}
}
out.KeyUsage = KeyUsage(usage)
case 19:
// RFC 5280, 4.2.1.9
var constraints basicConstraints
if rest, err := asn1.Unmarshal(e.Value, &constraints); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 BasicConstraints")
}
out.BasicConstraintsValid = true
out.IsCA = constraints.IsCA
out.MaxPathLen = constraints.MaxPathLen
out.MaxPathLenZero = out.MaxPathLen == 0
case 17:
out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(e.Value)
if err != nil {
return nil, err
}
if len(out.DNSNames) == 0 && len(out.EmailAddresses) == 0 && len(out.IPAddresses) == 0 {
// If we didn't parse anything then we do the critical check, below.
unhandled = true
}
case 30:
// RFC 5280, 4.2.1.10
// NameConstraints ::= SEQUENCE {
// permittedSubtrees [0] GeneralSubtrees OPTIONAL,
// excludedSubtrees [1] GeneralSubtrees OPTIONAL }
//
// GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree
//
// GeneralSubtree ::= SEQUENCE {
// base GeneralName,
// minimum [0] BaseDistance DEFAULT 0,
// maximum [1] BaseDistance OPTIONAL }
//
// BaseDistance ::= INTEGER (0..MAX)
var constraints nameConstraints
if rest, err := asn1.Unmarshal(e.Value, &constraints); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 NameConstraints")
}
if len(constraints.Excluded) > 0 && e.Critical {
return out, UnhandledCriticalExtension{}
}
for _, subtree := range constraints.Permitted {
if len(subtree.Name) == 0 {
if e.Critical {
return out, UnhandledCriticalExtension{}
}
continue
}
out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name)
}
case 31:
// RFC 5280, 4.2.1.13
// CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
//
// DistributionPoint ::= SEQUENCE {
// distributionPoint [0] DistributionPointName OPTIONAL,
// reasons [1] ReasonFlags OPTIONAL,
// cRLIssuer [2] GeneralNames OPTIONAL }
//
// DistributionPointName ::= CHOICE {
// fullName [0] GeneralNames,
// nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
var cdp []distributionPoint
if rest, err := asn1.Unmarshal(e.Value, &cdp); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 CRL distribution point")
}
for _, dp := range cdp {
// Per RFC 5280, 4.2.1.13, one of distributionPoint or cRLIssuer may be empty.
if len(dp.DistributionPoint.FullName.Bytes) == 0 {
continue
}
var n asn1.RawValue
if _, err := asn1.Unmarshal(dp.DistributionPoint.FullName.Bytes, &n); err != nil {
return nil, err
}
// Trailing data after the fullName is
// allowed because other elements of
// the SEQUENCE can appear.
if n.Tag == 6 {
out.CRLDistributionPoints = append(out.CRLDistributionPoints, string(n.Bytes))
}
}
case 35:
// RFC 5280, 4.2.1.1
var a authKeyId
if rest, err := asn1.Unmarshal(e.Value, &a); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 authority key-id")
}
out.AuthorityKeyId = a.Id
case 37:
// RFC 5280, 4.2.1.12. Extended Key Usage
// id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 }
//
// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
//
// KeyPurposeId ::= OBJECT IDENTIFIER
var keyUsage []asn1.ObjectIdentifier
if rest, err := asn1.Unmarshal(e.Value, &keyUsage); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 ExtendedKeyUsage")
}
for _, u := range keyUsage {
if extKeyUsage, ok := extKeyUsageFromOID(u); ok {
out.ExtKeyUsage = append(out.ExtKeyUsage, extKeyUsage)
} else {
out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u)
}
}
case 14:
// RFC 5280, 4.2.1.2
var keyid []byte
if rest, err := asn1.Unmarshal(e.Value, &keyid); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 key-id")
}
out.SubjectKeyId = keyid
case 32:
// RFC 5280 4.2.1.4: Certificate Policies
var policies []policyInformation
if rest, err := asn1.Unmarshal(e.Value, &policies); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 certificate policies")
}
out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies))
for i, policy := range policies {
out.PolicyIdentifiers[i] = policy.Policy
}
default:
// Unknown extensions are recorded if critical.
unhandled = true
}
} else if e.Id.Equal(oidExtensionAuthorityInfoAccess) {
// RFC 5280 4.2.2.1: Authority Information Access
var aia []authorityInfoAccess
if rest, err := asn1.Unmarshal(e.Value, &aia); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 authority information")
}
for _, v := range aia {
// GeneralName: uniformResourceIdentifier [6] IA5String
if v.Location.Tag != 6 {
continue
}
if v.Method.Equal(oidAuthorityInfoAccessOcsp) {
out.OCSPServer = append(out.OCSPServer, string(v.Location.Bytes))
} else if v.Method.Equal(oidAuthorityInfoAccessIssuers) {
out.IssuingCertificateURL = append(out.IssuingCertificateURL, string(v.Location.Bytes))
}
}
} else {
// Unknown extensions are recorded if critical.
unhandled = true
}
if e.Critical && unhandled {
out.UnhandledCriticalExtensions = append(out.UnhandledCriticalExtensions, e.Id)
}
}
return out, nil
}
// ParseCertificate parses a single certificate from the given ASN.1 DER data.
func ParseCertificate(asn1Data []byte) (*Certificate, error) {
var cert certificate
rest, err := asn1.Unmarshal(asn1Data, &cert)
if err != nil {
return nil, err
}
if len(rest) > 0 {
return nil, asn1.SyntaxError{Msg: "trailing data"}
}
return parseCertificate(&cert)
}
// ParseCertificates parses one or more certificates from the given ASN.1 DER
// data. The certificates must be concatenated with no intermediate padding.
func ParseCertificates(asn1Data []byte) ([]*Certificate, error) {
var v []*certificate
for len(asn1Data) > 0 {
cert := new(certificate)
var err error
asn1Data, err = asn1.Unmarshal(asn1Data, cert)
if err != nil {
return nil, err
}
v = append(v, cert)
}
ret := make([]*Certificate, len(v))
for i, ci := range v {
cert, err := parseCertificate(ci)
if err != nil {
return nil, err
}
ret[i] = cert
}
return ret, nil
}
func reverseBitsInAByte(in byte) byte {
b1 := in>>4 | in<<4
b2 := b1>>2&0x33 | b1<<2&0xcc
b3 := b2>>1&0x55 | b2<<1&0xaa
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}
oidExtensionExtendedKeyUsage = []int{2, 5, 29, 37}
oidExtensionAuthorityKeyId = []int{2, 5, 29, 35}
oidExtensionBasicConstraints = []int{2, 5, 29, 19}
oidExtensionSubjectAltName = []int{2, 5, 29, 17}
oidExtensionCertificatePolicies = []int{2, 5, 29, 32}
oidExtensionNameConstraints = []int{2, 5, 29, 30}
oidExtensionCRLDistributionPoints = []int{2, 5, 29, 31}
oidExtensionAuthorityInfoAccess = []int{1, 3, 6, 1, 5, 5, 7, 1, 1}
)
var (
oidAuthorityInfoAccessOcsp = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 1}
oidAuthorityInfoAccessIssuers = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 48, 2}
)
// oidNotInExtensions returns whether an extension with the given oid exists in
// extensions.
func oidInExtensions(oid asn1.ObjectIdentifier, extensions []pkix.Extension) bool {
for _, e := range extensions {
if e.Id.Equal(oid) {
return true
}
}
return false
}
// marshalSANs marshals a list of addresses into a the contents of an X.509
// SubjectAlternativeName extension.
func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP) (derBytes []byte, err error) {
var rawValues []asn1.RawValue
for _, name := range dnsNames {
rawValues = append(rawValues, asn1.RawValue{Tag: 2, Class: 2, Bytes: []byte(name)})
}
for _, email := range emailAddresses {
rawValues = append(rawValues, asn1.RawValue{Tag: 1, Class: 2, Bytes: []byte(email)})
}
for _, rawIP := range ipAddresses {
// If possible, we always want to encode IPv4 addresses in 4 bytes.
ip := rawIP.To4()
if ip == nil {
ip = rawIP
}
rawValues = append(rawValues, asn1.RawValue{Tag: 7, Class: 2, Bytes: ip})
}
return asn1.Marshal(rawValues)
}
func buildExtensions(template *Certificate) (ret []pkix.Extension, err error) {
ret = make([]pkix.Extension, 10 /* maximum number of elements. */)
n := 0
if template.KeyUsage != 0 &&
!oidInExtensions(oidExtensionKeyUsage, template.ExtraExtensions) {
ret[n].Id = oidExtensionKeyUsage
ret[n].Critical = true
var a [2]byte
a[0] = reverseBitsInAByte(byte(template.KeyUsage))
a[1] = reverseBitsInAByte(byte(template.KeyUsage >> 8))
l := 1
if a[1] != 0 {
l = 2
}
bitString := a[:l]
ret[n].Value, err = asn1.Marshal(asn1.BitString{Bytes: bitString, BitLength: asn1BitLength(bitString)})
if err != nil {
return
}
n++
}
if (len(template.ExtKeyUsage) > 0 || len(template.UnknownExtKeyUsage) > 0) &&
!oidInExtensions(oidExtensionExtendedKeyUsage, template.ExtraExtensions) {
ret[n].Id = oidExtensionExtendedKeyUsage
var oids []asn1.ObjectIdentifier
for _, u := range template.ExtKeyUsage {
if oid, ok := oidFromExtKeyUsage(u); ok {
oids = append(oids, oid)
} else {
panic("internal error")
}
}
oids = append(oids, template.UnknownExtKeyUsage...)
ret[n].Value, err = asn1.Marshal(oids)
if err != nil {
return
}
n++
}
if template.BasicConstraintsValid && !oidInExtensions(oidExtensionBasicConstraints, template.ExtraExtensions) {
// Leaving MaxPathLen as zero indicates that no maximum path
// length is desired, unless MaxPathLenZero is set. A value of
// -1 causes encoding/asn1 to omit the value as desired.
maxPathLen := template.MaxPathLen
if maxPathLen == 0 && !template.MaxPathLenZero {
maxPathLen = -1
}
ret[n].Id = oidExtensionBasicConstraints
ret[n].Value, err = asn1.Marshal(basicConstraints{template.IsCA, maxPathLen})
ret[n].Critical = true
if err != nil {
return
}
n++
}
if len(template.SubjectKeyId) > 0 && !oidInExtensions(oidExtensionSubjectKeyId, template.ExtraExtensions) {
ret[n].Id = oidExtensionSubjectKeyId
ret[n].Value, err = asn1.Marshal(template.SubjectKeyId)
if err != nil {
return
}
n++
}
if len(template.AuthorityKeyId) > 0 && !oidInExtensions(oidExtensionAuthorityKeyId, template.ExtraExtensions) {
ret[n].Id = oidExtensionAuthorityKeyId
ret[n].Value, err = asn1.Marshal(authKeyId{template.AuthorityKeyId})
if err != nil {
return
}
n++
}
if (len(template.OCSPServer) > 0 || len(template.IssuingCertificateURL) > 0) &&
!oidInExtensions(oidExtensionAuthorityInfoAccess, template.ExtraExtensions) {
ret[n].Id = oidExtensionAuthorityInfoAccess
var aiaValues []authorityInfoAccess
for _, name := range template.OCSPServer {
aiaValues = append(aiaValues, authorityInfoAccess{
Method: oidAuthorityInfoAccessOcsp,
Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
})
}
for _, name := range template.IssuingCertificateURL {
aiaValues = append(aiaValues, authorityInfoAccess{
Method: oidAuthorityInfoAccessIssuers,
Location: asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)},
})
}
ret[n].Value, err = asn1.Marshal(aiaValues)
if err != nil {
return
}
n++
}
if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) &&
!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
ret[n].Id = oidExtensionSubjectAltName
ret[n].Value, err = marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses)
if err != nil {
return
}
n++
}
if len(template.PolicyIdentifiers) > 0 &&
!oidInExtensions(oidExtensionCertificatePolicies, template.ExtraExtensions) {
ret[n].Id = oidExtensionCertificatePolicies
policies := make([]policyInformation, len(template.PolicyIdentifiers))
for i, policy := range template.PolicyIdentifiers {
policies[i].Policy = policy
}
ret[n].Value, err = asn1.Marshal(policies)
if err != nil {
return
}
n++
}
if len(template.PermittedDNSDomains) > 0 &&
!oidInExtensions(oidExtensionNameConstraints, template.ExtraExtensions) {
ret[n].Id = oidExtensionNameConstraints
ret[n].Critical = template.PermittedDNSDomainsCritical
var out nameConstraints
out.Permitted = make([]generalSubtree, len(template.PermittedDNSDomains))
for i, permitted := range template.PermittedDNSDomains {
out.Permitted[i] = generalSubtree{Name: permitted}
}
ret[n].Value, err = asn1.Marshal(out)
if err != nil {
return
}
n++
}
if len(template.CRLDistributionPoints) > 0 &&
!oidInExtensions(oidExtensionCRLDistributionPoints, template.ExtraExtensions) {
ret[n].Id = oidExtensionCRLDistributionPoints
var crlDp []distributionPoint
for _, name := range template.CRLDistributionPoints {
rawFullName, _ := asn1.Marshal(asn1.RawValue{Tag: 6, Class: 2, Bytes: []byte(name)})
dp := distributionPoint{
DistributionPoint: distributionPointName{
FullName: asn1.RawValue{Tag: 0, Class: 2, IsCompound: true, Bytes: rawFullName},
},
}
crlDp = append(crlDp, dp)
}
ret[n].Value, err = asn1.Marshal(crlDp)
if err != nil {
return
}
n++
}
// Adding another extension here? Remember to update the maximum number
// of elements in the make() at the top of the function.
return append(ret[:n], template.ExtraExtensions...), nil
}
func subjectBytes(cert *Certificate) ([]byte, error) {
if len(cert.RawSubject) > 0 {
return cert.RawSubject, nil
}
return asn1.Marshal(cert.Subject.ToRDNSequence())
}
// signingParamsForPublicKey returns the parameters to use for signing with
// priv. If requestedSigAlgo is not zero then it overrides the default
// signature algorithm.
func signingParamsForPublicKey(pub interface{}, requestedSigAlgo SignatureAlgorithm) (hashFunc Hash, sigAlgo pkix.AlgorithmIdentifier, err error) {
var pubType PublicKeyAlgorithm
switch pub := pub.(type) {
case *rsa.PublicKey:
pubType = RSA
hashFunc = SHA256
sigAlgo.Algorithm = oidSignatureSHA256WithRSA
sigAlgo.Parameters = asn1.RawValue{
Tag: 5,
}
case *ecdsa.PublicKey:
pubType = ECDSA
switch pub.Curve {
case elliptic.P224(), elliptic.P256():
hashFunc = SHA256
sigAlgo.Algorithm = oidSignatureECDSAWithSHA256
case elliptic.P384():
hashFunc = SHA384
sigAlgo.Algorithm = oidSignatureECDSAWithSHA384
case elliptic.P521():
hashFunc = SHA512
sigAlgo.Algorithm = oidSignatureECDSAWithSHA512
default:
err = errors.New("x509: unknown elliptic curve")
}
case *PublicKey:
pubType = ECDSA
switch pub.Curve {
case P256Sm2():
hashFunc = SM3
sigAlgo.Algorithm = oidSignatureSM2WithSM3
default:
err = errors.New("x509: unknown SM2 curve")
}
default:
err = errors.New("x509: only RSA and ECDSA keys supported")
}
if err != nil {
return
}
if requestedSigAlgo == 0 {
return
}
found := false
for _, details := range signatureAlgorithmDetails {
if details.algo == requestedSigAlgo {
if details.pubKeyAlgo != pubType {
err = errors.New("x509: requested SignatureAlgorithm does not match private key type")
return
}
sigAlgo.Algorithm, hashFunc = details.oid, details.hash
if hashFunc == 0 {
err = errors.New("x509: cannot sign with hash function requested")
return
}
if requestedSigAlgo.isRSAPSS() {
sigAlgo.Parameters = rsaPSSParameters(hashFunc)
}
found = true
break
}
}
if !found {
err = errors.New("x509: unknown SignatureAlgorithm")
}
return
}
// CreateCertificate creates a new certificate based on a template. The
// following members of template are used: SerialNumber, Subject, NotBefore,
// NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
// IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
// PermittedDNSDomains, SignatureAlgorithm.
//
// The certificate is signed by parent. If parent is equal to template then the
// certificate is self-signed. The parameter pub is the public key of the
// signee and priv is the private key of the signer.
//
// The returned slice is the certificate in DER encoding.
//
// All keys types that are implemented via crypto.Signer are supported (This
// includes *rsa.PublicKey and *ecdsa.PublicKey.)
func CreateCertificate(rand io.Reader, template, parent *Certificate, pub, priv interface{}) (cert []byte, err error) {
key, ok := priv.(crypto.Signer)
if !ok {
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
if template.SerialNumber == nil {
return nil, errors.New("x509: no SerialNumber given")
}
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
}
publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(pub)
if err != nil {
return nil, err
}
asn1Issuer, err := subjectBytes(parent)
if err != nil {
return
}
asn1Subject, err := subjectBytes(template)
if err != nil {
return
}
if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {
template.AuthorityKeyId = parent.SubjectKeyId
}
extensions, err := buildExtensions(template)
if err != nil {
return
}
encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
c := tbsCertificate{
Version: 2,
SerialNumber: template.SerialNumber,
SignatureAlgorithm: signatureAlgorithm,
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
Extensions: extensions,
}
tbsCertContents, err := asn1.Marshal(c)
if err != nil {
return
}
c.Raw = tbsCertContents
h := hashFunc.New()
h.Write(tbsCertContents)
digest := h.Sum(nil)
var signerOpts crypto.SignerOpts
signerOpts = hashFunc
if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() {
signerOpts = &rsa.PSSOptions{
SaltLength: rsa.PSSSaltLengthEqualsHash,
Hash: crypto.Hash(hashFunc),
}
}
var signature []byte
signature, err = key.Sign(rand, digest, signerOpts)
if err != nil {
return
}
return asn1.Marshal(certificate{
nil,
c,
signatureAlgorithm,
asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
}
// pemCRLPrefix is the magic string that indicates that we have a PEM encoded
// CRL.
var pemCRLPrefix = []byte("-----BEGIN X509 CRL")
// pemType is the type of a PEM encoded CRL.
var pemType = "X509 CRL"
// ParseCRL parses a CRL from the given bytes. It's often the case that PEM
// encoded CRLs will appear where they should be DER encoded, so this function
// will transparently handle PEM encoding as long as there isn't any leading
// garbage.
func ParseCRL(crlBytes []byte) (*pkix.CertificateList, error) {
if bytes.HasPrefix(crlBytes, pemCRLPrefix) {
block, _ := pem.Decode(crlBytes)
if block != nil && block.Type == pemType {
crlBytes = block.Bytes
}
}
return ParseDERCRL(crlBytes)
}
// ParseDERCRL parses a DER encoded CRL from the given bytes.
func ParseDERCRL(derBytes []byte) (*pkix.CertificateList, error) {
certList := new(pkix.CertificateList)
if rest, err := asn1.Unmarshal(derBytes, certList); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after CRL")
}
return certList, nil
}
// CreateCRL returns a DER encoded CRL, signed by this Certificate, that
// contains the given list of revoked certificates.
func (c *Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) {
key, ok := priv.(crypto.Signer)
if !ok {
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(key.Public(), 0)
if err != nil {
return nil, err
}
// Force revocation times to UTC per RFC 5280.
revokedCertsUTC := make([]pkix.RevokedCertificate, len(revokedCerts))
for i, rc := range revokedCerts {
rc.RevocationTime = rc.RevocationTime.UTC()
revokedCertsUTC[i] = rc
}
tbsCertList := pkix.TBSCertificateList{
Version: 1,
Signature: signatureAlgorithm,
Issuer: c.Subject.ToRDNSequence(),
ThisUpdate: now.UTC(),
NextUpdate: expiry.UTC(),
RevokedCertificates: revokedCertsUTC,
}
// Authority Key Id
if len(c.SubjectKeyId) > 0 {
var aki pkix.Extension
aki.Id = oidExtensionAuthorityKeyId
aki.Value, err = asn1.Marshal(authKeyId{Id: c.SubjectKeyId})
if err != nil {
return
}
tbsCertList.Extensions = append(tbsCertList.Extensions, aki)
}
tbsCertListContents, err := asn1.Marshal(tbsCertList)
if err != nil {
return
}
h := hashFunc.New()
h.Write(tbsCertListContents)
digest := h.Sum(nil)
var signature []byte
signature, err = key.Sign(rand, digest, hashFunc)
if err != nil {
return
}
return asn1.Marshal(pkix.CertificateList{
TBSCertList: tbsCertList,
SignatureAlgorithm: signatureAlgorithm,
SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
})
}
// CertificateRequest represents a PKCS #10, certificate signature request.
type CertificateRequest struct {
Raw []byte // Complete ASN.1 DER content (CSR, signature algorithm and signature).
RawTBSCertificateRequest []byte // Certificate request info part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
RawSubject []byte // DER encoded Subject.
Version int
Signature []byte
SignatureAlgorithm SignatureAlgorithm
PublicKeyAlgorithm PublicKeyAlgorithm
PublicKey interface{}
Subject pkix.Name
// Attributes is the dried husk of a bug and shouldn't be used.
Attributes []pkix.AttributeTypeAndValueSET
// Extensions contains raw X.509 extensions. When parsing CSRs, this
// can be used to extract extensions that are not parsed by this
// package.
Extensions []pkix.Extension
// ExtraExtensions contains extensions to be copied, raw, into any
// marshaled CSR. Values override any extensions that would otherwise
// be produced based on the other fields but are overridden by any
// extensions specified in Attributes.
//
// The ExtraExtensions field is not populated when parsing CSRs, see
// Extensions.
ExtraExtensions []pkix.Extension
// Subject Alternate Name values.
DNSNames []string
EmailAddresses []string
IPAddresses []net.IP
}
// These structures reflect the ASN.1 structure of X.509 certificate
// signature requests (see RFC 2986):
type tbsCertificateRequest struct {
Raw asn1.RawContent
Version int
Subject asn1.RawValue
PublicKey publicKeyInfo
RawAttributes []asn1.RawValue `asn1:"tag:0"`
}
type certificateRequest struct {
Raw asn1.RawContent
TBSCSR tbsCertificateRequest
SignatureAlgorithm pkix.AlgorithmIdentifier
SignatureValue asn1.BitString
}
// oidExtensionRequest is a PKCS#9 OBJECT IDENTIFIER that indicates requested
// extensions in a CSR.
var oidExtensionRequest = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 9, 14}
// newRawAttributes converts AttributeTypeAndValueSETs from a template
// CertificateRequest's Attributes into tbsCertificateRequest RawAttributes.
func newRawAttributes(attributes []pkix.AttributeTypeAndValueSET) ([]asn1.RawValue, error) {
var rawAttributes []asn1.RawValue
b, err := asn1.Marshal(attributes)
if err != nil {
return nil, err
}
rest, err := asn1.Unmarshal(b, &rawAttributes)
if err != nil {
return nil, err
}
if len(rest) != 0 {
return nil, errors.New("x509: failed to unmarshal raw CSR Attributes")
}
return rawAttributes, nil
}
// parseRawAttributes Unmarshals RawAttributes intos AttributeTypeAndValueSETs.
func parseRawAttributes(rawAttributes []asn1.RawValue) []pkix.AttributeTypeAndValueSET {
var attributes []pkix.AttributeTypeAndValueSET
for _, rawAttr := range rawAttributes {
var attr pkix.AttributeTypeAndValueSET
rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr)
// Ignore attributes that don't parse into pkix.AttributeTypeAndValueSET
// (i.e.: challengePassword or unstructuredName).
if err == nil && len(rest) == 0 {
attributes = append(attributes, attr)
}
}
return attributes
}
// parseCSRExtensions parses the attributes from a CSR and extracts any
// requested extensions.
func parseCSRExtensions(rawAttributes []asn1.RawValue) ([]pkix.Extension, error) {
// pkcs10Attribute reflects the Attribute structure from section 4.1 of
// https://tools.ietf.org/html/rfc2986.
type pkcs10Attribute struct {
Id asn1.ObjectIdentifier
Values []asn1.RawValue `asn1:"set"`
}
var ret []pkix.Extension
for _, rawAttr := range rawAttributes {
var attr pkcs10Attribute
if rest, err := asn1.Unmarshal(rawAttr.FullBytes, &attr); err != nil || len(rest) != 0 || len(attr.Values) == 0 {
// Ignore attributes that don't parse.
continue
}
if !attr.Id.Equal(oidExtensionRequest) {
continue
}
var extensions []pkix.Extension
if _, err := asn1.Unmarshal(attr.Values[0].FullBytes, &extensions); err != nil {
return nil, err
}
ret = append(ret, extensions...)
}
return ret, nil
}
// CreateCertificateRequest creates a new certificate request based on a template.
// The following members of template are used: Subject, Attributes,
// SignatureAlgorithm, Extensions, DNSNames, EmailAddresses, and IPAddresses.
// The private key is the private key of the signer.
//
// The returned slice is the certificate request in DER encoding.
//
// All keys types that are implemented via crypto.Signer are supported (This
// includes *rsa.PublicKey and *ecdsa.PublicKey.)
func CreateCertificateRequest(rand io.Reader, template *CertificateRequest, priv interface{}) (csr []byte, err error) {
key, ok := priv.(crypto.Signer)
if !ok {
return nil, errors.New("x509: certificate private key does not implement crypto.Signer")
}
var hashFunc Hash
var sigAlgo pkix.AlgorithmIdentifier
hashFunc, sigAlgo, err = signingParamsForPublicKey(key.Public(), template.SignatureAlgorithm)
if err != nil {
return nil, err
}
var publicKeyBytes []byte
var publicKeyAlgorithm pkix.AlgorithmIdentifier
publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(key.Public())
if err != nil {
return nil, err
}
var extensions []pkix.Extension
if (len(template.DNSNames) > 0 || len(template.EmailAddresses) > 0 || len(template.IPAddresses) > 0) &&
!oidInExtensions(oidExtensionSubjectAltName, template.ExtraExtensions) {
sanBytes, err := marshalSANs(template.DNSNames, template.EmailAddresses, template.IPAddresses)
if err != nil {
return nil, err
}
extensions = append(extensions, pkix.Extension{
Id: oidExtensionSubjectAltName,
Value: sanBytes,
})
}
extensions = append(extensions, template.ExtraExtensions...)
var attributes []pkix.AttributeTypeAndValueSET
attributes = append(attributes, template.Attributes...)
if len(extensions) > 0 {
// specifiedExtensions contains all the extensions that we
// found specified via template.Attributes.
specifiedExtensions := make(map[string]bool)
for _, atvSet := range template.Attributes {
if !atvSet.Type.Equal(oidExtensionRequest) {
continue
}
for _, atvs := range atvSet.Value {
for _, atv := range atvs {
specifiedExtensions[atv.Type.String()] = true
}
}
}
atvs := make([]pkix.AttributeTypeAndValue, 0, len(extensions))
for _, e := range extensions {
if specifiedExtensions[e.Id.String()] {
// Attributes already contained a value for
// this extension and it takes priority.
continue
}
atvs = append(atvs, pkix.AttributeTypeAndValue{
// There is no place for the critical flag in a CSR.
Type: e.Id,
Value: e.Value,
})
}
// Append the extensions to an existing attribute if possible.
appended := false
for _, atvSet := range attributes {
if !atvSet.Type.Equal(oidExtensionRequest) || len(atvSet.Value) == 0 {
continue
}
atvSet.Value[0] = append(atvSet.Value[0], atvs...)
appended = true
break
}
// Otherwise, add a new attribute for the extensions.
if !appended {
attributes = append(attributes, pkix.AttributeTypeAndValueSET{
Type: oidExtensionRequest,
Value: [][]pkix.AttributeTypeAndValue{
atvs,
},
})
}
}
asn1Subject := template.RawSubject
if len(asn1Subject) == 0 {
asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence())
if err != nil {
return
}
}
rawAttributes, err := newRawAttributes(attributes)
if err != nil {
return
}
tbsCSR := tbsCertificateRequest{
Version: 0, // PKCS #10, RFC 2986
Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: publicKeyInfo{
Algorithm: publicKeyAlgorithm,
PublicKey: asn1.BitString{
Bytes: publicKeyBytes,
BitLength: len(publicKeyBytes) * 8,
},
},
RawAttributes: rawAttributes,
}
tbsCSRContents, err := asn1.Marshal(tbsCSR)
if err != nil {
return
}
tbsCSR.Raw = tbsCSRContents
h := hashFunc.New()
h.Write(tbsCSRContents)
digest := h.Sum(nil)
var signature []byte
signature, err = key.Sign(rand, digest, hashFunc)
if err != nil {
return
}
return asn1.Marshal(certificateRequest{
TBSCSR: tbsCSR,
SignatureAlgorithm: sigAlgo,
SignatureValue: asn1.BitString{
Bytes: signature,
BitLength: len(signature) * 8,
},
})
}
// ParseCertificateRequest parses a single certificate request from the
// given ASN.1 DER data.
func ParseCertificateRequest(asn1Data []byte) (*CertificateRequest, error) {
var csr certificateRequest
rest, err := asn1.Unmarshal(asn1Data, &csr)
if err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, asn1.SyntaxError{Msg: "trailing data"}
}
return parseCertificateRequest(&csr)
}
func parseCertificateRequest(in *certificateRequest) (*CertificateRequest, error) {
out := &CertificateRequest{
Raw: in.Raw,
RawTBSCertificateRequest: in.TBSCSR.Raw,
RawSubjectPublicKeyInfo: in.TBSCSR.PublicKey.Raw,
RawSubject: in.TBSCSR.Subject.FullBytes,
Signature: in.SignatureValue.RightAlign(),
SignatureAlgorithm: getSignatureAlgorithmFromAI(in.SignatureAlgorithm),
PublicKeyAlgorithm: getPublicKeyAlgorithmFromOID(in.TBSCSR.PublicKey.Algorithm.Algorithm),
Version: in.TBSCSR.Version,
Attributes: parseRawAttributes(in.TBSCSR.RawAttributes),
}
var err error
out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCSR.PublicKey)
if err != nil {
return nil, err
}
var subject pkix.RDNSequence
if rest, err := asn1.Unmarshal(in.TBSCSR.Subject.FullBytes, &subject); err != nil {
return nil, err
} else if len(rest) != 0 {
return nil, errors.New("x509: trailing data after X.509 Subject")
}
out.Subject.FillFromRDNSequence(&subject)
if out.Extensions, err = parseCSRExtensions(in.TBSCSR.RawAttributes); err != nil {
return nil, err
}
for _, extension := range out.Extensions {
if extension.Id.Equal(oidExtensionSubjectAltName) {
out.DNSNames, out.EmailAddresses, out.IPAddresses, err = parseSANExtension(extension.Value)
if err != nil {
return nil, err
}
}
}
return out, nil
}
// CheckSignature reports whether the signature on c is valid.
func (c *CertificateRequest) CheckSignature() error {
return checkSignature(c.SignatureAlgorithm, c.RawTBSCertificateRequest, c.Signature, c.PublicKey)
}
func ReadCertificateRequestFromMem(data []byte) (*CertificateRequest, error) {
block, _ := pem.Decode(data)
if block == nil {
return nil, errors.New("failed to decode certificate request")
}
return ParseCertificateRequest(block.Bytes)
}
func ReadCertificateRequestFromPem(FileName string) (*CertificateRequest, error) {
data, err := ioutil.ReadFile(FileName)
if err != nil {
return nil, err
}
return ReadCertificateRequestFromMem(data)
}
func CreateCertificateRequestToMem(template *CertificateRequest, privKey *PrivateKey) ([]byte, error) {
der, err := CreateCertificateRequest(rand.Reader, template, privKey)
if err != nil {
return nil, err
}
block := &pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: der,
}
return pem.EncodeToMemory(block), nil
}
func CreateCertificateRequestToPem(FileName string, template *CertificateRequest,
privKey *PrivateKey) (bool, error) {
der, err := CreateCertificateRequest(rand.Reader, template, privKey)
if err != nil {
return false, err
}
block := &pem.Block{
Type: "CERTIFICATE REQUEST",
Bytes: der,
}
file, err := os.Create(FileName)
if err != nil {
return false, err
}
defer file.Close()
err = pem.Encode(file, block)
if err != nil {
return false, err
}
return true, nil
}
func ReadCertificateFromMem(data []byte) (*Certificate, error) {
block, _ := pem.Decode(data)
if block == nil {
return nil, errors.New("failed to decode certificate request")
}
return ParseCertificate(block.Bytes)
}
func ReadCertificateFromPem(FileName string) (*Certificate, error) {
data, err := ioutil.ReadFile(FileName)
if err != nil {
return nil, err
}
return ReadCertificateFromMem(data)
}
func CreateCertificateToMem(template, parent *Certificate, pubKey *PublicKey, privKey *PrivateKey) ([]byte, error) {
der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey)
if err != nil {
return nil, err
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: der,
}
return pem.EncodeToMemory(block), nil
}
func CreateCertificateToPem(FileName string, template, parent *Certificate, pubKey *PublicKey, privKey *PrivateKey) (bool, error) {
der, err := CreateCertificate(rand.Reader, template, parent, pubKey, privKey)
if err != nil {
return false, err
}
block := &pem.Block{
Type: "CERTIFICATE",
Bytes: der,
}
file, err := os.Create(FileName)
if err != nil {
return false, err
}
defer file.Close()
err = pem.Encode(file, block)
if err != nil {
return false, err
}
return true, nil
}