var ( TCertEncTCertIndex = asn1.ObjectIdentifier{1, 2, 3, 4, 5, 6, 7} )
func DERToX509Certificate(asn1Data []byte) (*x509.Certificate, error) { return x509.ParseCertificate(asn1Data) }
func PEMtoCertificate(raw []byte) (*x509.Certificate, error) { block, _ := pem.Decode(raw) if block == nil { return nil, errors.New("No PEM block available") }
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { return nil, errors.New("Not a valid CERTIFICATE PEM block") }
cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, err }
return cert, nil }
func PEMtoDER(raw []byte) ([]byte, error) { block, _ := pem.Decode(raw) if block == nil { return nil, errors.New("No PEM block available") }
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { return nil, errors.New("Not a valid CERTIFICATE PEM block") }
return block.Bytes, nil }
func PEMtoCertificateAndDER(raw []byte) (*x509.Certificate, []byte, error) { block, _ := pem.Decode(raw) if block == nil { return nil, nil, errors.New("No PEM block available") }
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { return nil, nil, errors.New("Not a valid CERTIFICATE PEM block") }
cert, err := x509.ParseCertificate(block.Bytes) if err != nil { return nil, nil, err }
return cert, block.Bytes, nil }
func DERCertToPEM(der []byte) []byte { return pem.EncodeToMemory( &pem.Block{ Type: "CERTIFICATE", Bytes: der, }, ) }
func GetCriticalExtension(cert *x509.Certificate, oid asn1.ObjectIdentifier) ([]byte, error) { for i, ext := range cert.UnhandledCriticalExtensions { if IntArrayEquals(ext, oid) { cert.UnhandledCriticalExtensions = append(cert.UnhandledCriticalExtensions[:i], cert.UnhandledCriticalExtensions[i+1:]...)
break } }
for _, ext := range cert.Extensions { if IntArrayEquals(ext.Id, oid) { return ext.Value, nil } }
return nil, errors.New("Failed retrieving extension.") }
func NewSelfSignedCert() ([]byte, interface{}, error) { privKey, err := NewECDSAKey() if err != nil { return nil, nil, err }
testExtKeyUsage := []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageServerAuth} testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}} extraExtensionData := []byte("extra extension") commonName := "test.example.com" template := x509.Certificate{ SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: commonName, Organization: []string{"Σ Acme Co"}, Country: []string{"US"}, ExtraNames: []pkix.AttributeTypeAndValue{ { Type: []int{2, 5, 4, 42}, Value: "Gopher", }, { Type: []int{2, 5, 4, 6}, Value: "NL", }, }, }, NotBefore: time.Unix(1000, 0), NotAfter: time.Unix(100000, 0),
SignatureAlgorithm: x509.ECDSAWithSHA384,
SubjectKeyId: []byte{1, 2, 3, 4}, KeyUsage: x509.KeyUsageCertSign,
ExtKeyUsage: testExtKeyUsage, UnknownExtKeyUsage: testUnknownExtKeyUsage,
BasicConstraintsValid: true, IsCA: true,
OCSPServer: []string{"http://ocsp.example.com"}, IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
DNSNames: []string{"test.example.com"}, EmailAddresses: []string{"gopher@golang.org"}, IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}}, PermittedDNSDomains: []string{".example.com", "example.com"},
CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
ExtraExtensions: []pkix.Extension{ { Id: []int{1, 2, 3, 4}, Value: extraExtensionData, }, }, }
cert, err := x509.CreateCertificate(rand.Reader, &template, &template, &privKey.PublicKey, privKey) if err != nil { return nil, nil, err }
return cert, privKey, nil }
func CheckCertPKAgainstSK(x509Cert *x509.Certificate, privateKey interface{}) error { switch pub := x509Cert.PublicKey.(type) { case *rsa.PublicKey: priv, ok := privateKey.(*rsa.PrivateKey) if !ok { return errors.New("Private key type does not match public key type") } if pub.N.Cmp(priv.N) != 0 { return errors.New("Private key does not match public key") } case *ecdsa.PublicKey: priv, ok := privateKey.(*ecdsa.PrivateKey) if !ok { return errors.New("Private key type does not match public key type")
} if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 { return errors.New("Private key does not match public key") } default: return errors.New("Unknown public key algorithm") }
return nil }
func CheckCertAgainRoot(x509Cert *x509.Certificate, certPool *x509.CertPool) ([][]*x509.Certificate, error) { opts := x509.VerifyOptions{ Roots: certPool, }
return x509Cert.Verify(opts) }
func CheckCertAgainstSKAndRoot(x509Cert *x509.Certificate, privateKey interface{}, certPool *x509.CertPool) error { if err := CheckCertPKAgainstSK(x509Cert, privateKey); err != nil { return err }
if _, err := CheckCertAgainRoot(x509Cert, certPool); err != nil { return err }
return nil }
|