// marshalPKCS8PrivateKey marshals the provided ECDSA private key into the // PKCS#8 private key format. func marshalPKCS8PrivateKey(key *ecdsa.PrivateKey) ([]byte, error) { oid, ok := oidFromNamedCurve(key.PublicKey.Curve) if !ok { return nil, fmt.Errorf("illegal curve") } paramBytes, err := asn1.Marshal(oid) if err != nil { return nil, err } var algo pkix.AlgorithmIdentifier algo.Algorithm = oidPublicKeyECDSA algo.Parameters.FullBytes = paramBytes privBytes, err := x509.MarshalECPrivateKey(key) if err != nil { return nil, err } pkcs8 := struct { Version int Algo pkix.AlgorithmIdentifier PrivateKey []byte }{ Version: 1, Algo: algo, PrivateKey: privBytes, } return asn1.Marshal(pkcs8) }
func TestPbDecrypterFor(t *testing.T) { params, _ := asn1.Marshal(pbeParams{ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, }) alg := pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), Parameters: asn1.RawValue{ FullBytes: params, }, } pass, _ := bmpString([]byte("Sesame open")) _, err := pbDecrypterFor(alg, pass) if _, ok := err.(NotImplementedError); !ok { t.Errorf("expected not implemented error, got: %T %s", err, err) } alg.Algorithm = asn1.ObjectIdentifier([]int{1, 2, 840, 113549, 1, 12, 1, 3}) cbc, err := pbDecrypterFor(alg, pass) if err != nil { t.Errorf("err: %v", err) } M := []byte{1, 2, 3, 4, 5, 6, 7, 8} expectedM := []byte{185, 73, 135, 249, 137, 1, 122, 247} cbc.CryptBlocks(M, M) if bytes.Compare(M, expectedM) != 0 { t.Errorf("expected M to be '%d', but found '%d", expectedM, M) } }
func makeSafeContents(bags []safeBag, password []byte) (ci contentInfo, err error) { var data []byte if data, err = asn1.Marshal(bags); err != nil { return } if password == nil { ci.ContentType = oidDataContentType ci.Content.Class = 2 ci.Content.Tag = 0 ci.Content.IsCompound = true if ci.Content.Bytes, err = asn1.Marshal(data); err != nil { return } } else { var randomSalt []byte if _, err = rand.Read(randomSalt); err != nil { return } var algo pkix.AlgorithmIdentifier algo.Algorithm = oidPbewithSHAAnd40BitRC2CBC if algo.Parameters.FullBytes, err = asn1.Marshal(pbeParams{Salt: randomSalt, Iterations: 2048}); err != nil { return } var encryptedData encryptedData encryptedData.Version = 0 encryptedData.EncryptedContentInfo.ContentType = oidDataContentType encryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm = algo if err = pbEncrypt(&encryptedData.EncryptedContentInfo, data, password); err != nil { return } ci.ContentType = oidEncryptedDataContentType ci.Content.Class = 2 ci.Content.Tag = 0 ci.Content.IsCompound = true if ci.Content.Bytes, err = asn1.Marshal(encryptedData); err != nil { return } } return }
func TestPbDecrypterFor(t *testing.T) { params, _ := asn1.Marshal(pbeParams{ Salt: []byte{1, 2, 3, 4, 5, 6, 7, 8}, Iterations: 2048, }) alg := pkix.AlgorithmIdentifier{ Algorithm: asn1.ObjectIdentifier([]int{1, 2, 3}), Parameters: asn1.RawValue{ FullBytes: params, }, } pass, _ := bmpString("Sesame open") _, _, err := pbDecrypterFor(alg, pass) if _, ok := err.(NotImplementedError); !ok { t.Errorf("expected not implemented error, got: %T %s", err, err) } alg.Algorithm = sha1WithTripleDES cbc, blockSize, err := pbDecrypterFor(alg, pass) if err != nil { t.Errorf("unexpected error from pbDecrypterFor %v", err) } if blockSize != 8 { t.Errorf("unexpected block size %d, wanted 8", blockSize) } plaintext := []byte{1, 2, 3, 4, 5, 6, 7, 8} expectedCiphertext := []byte{185, 73, 135, 249, 137, 1, 122, 247} ciphertext := make([]byte, len(plaintext)) cbc.CryptBlocks(ciphertext, plaintext) if bytes.Compare(ciphertext, expectedCiphertext) != 0 { t.Errorf("bad ciphertext, got %x but wanted %x", ciphertext, expectedCiphertext) } }
// 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. // // 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. // // The only supported key types are RSA and ECDSA (*rsa.PublicKey or // *ecdsa.PublicKey for pub, *rsa.PrivateKey or *ecdsa.PublicKey for priv). func CreateCertificate(rand io.Reader, template, parent *Certificate, pub interface{}, priv interface{}) (cert []byte, err error) { var publicKeyBytes []byte var publicKeyAlgorithm pkix.AlgorithmIdentifier if publicKeyBytes, publicKeyAlgorithm, err = marshalPublicKey(pub); err != nil { return nil, err } var signatureAlgorithm pkix.AlgorithmIdentifier var hashFunc crypto.Hash switch priv := priv.(type) { case *rsa.PrivateKey: signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA hashFunc = crypto.SHA1 case *ecdsa.PrivateKey: switch priv.Curve { case elliptic.P256(): hashFunc = crypto.SHA256 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256 case elliptic.P384(): hashFunc = crypto.SHA384 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384 case elliptic.P521(): hashFunc = crypto.SHA512 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512 default: return nil, errors.New("x509: unknown elliptic curve") } default: return nil, errors.New("x509: only RSA and ECDSA private keys supported") } if err != nil { return } if len(parent.SubjectKeyId) > 0 { template.AuthorityKeyId = parent.SubjectKeyId } extensions, err := buildExtensions(template) if err != nil { return } asn1Issuer, err := subjectBytes(parent) if err != nil { return } asn1Subject, err := subjectBytes(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 signature []byte switch priv := priv.(type) { case *rsa.PrivateKey: signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest) case *ecdsa.PrivateKey: var r, s *big.Int if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil { signature, err = asn1.Marshal(ecdsaSignature{r, s}) } default: panic("internal error") } if err != nil { return } cert, err = asn1.Marshal(certificate{ nil, c, signatureAlgorithm, asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) return }
// CreateCertificateSigningRequest creates a new certificate signing request // based on a template. The following members of template are used: Subject. // // The certificate signing request is signed with the parameter priv which is // the private key of the requester. The public part of the priv key is // included in the certification request information // // The returned slice is the certificate signing request in DER encoding. // // The only supported key type are RSA and ECDSA (*rsa.PrivateKey or // *ecdsa.PrivateKey for priv) func CreateCertificateSigningRequest(rand io.Reader, template *CertificateSigningRequest, priv interface{}) (csr []byte, err error) { var publicKeyBytes []byte var publicKeyAlgorithm pkix.AlgorithmIdentifier var signatureAlgorithm pkix.AlgorithmIdentifier var hashFunc crypto.Hash switch priv := priv.(type) { case *rsa.PrivateKey: signatureAlgorithm.Algorithm = oidSignatureSHA1WithRSA hashFunc = crypto.SHA1 publicKeyBytes, err = asn1.Marshal(rsaPublicKey{ N: priv.PublicKey.N, E: priv.PublicKey.E, }) publicKeyAlgorithm.Algorithm = oidPublicKeyRSA case *ecdsa.PrivateKey: switch priv.Curve { case elliptic.P224(), elliptic.P256(): hashFunc = crypto.SHA256 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256 case elliptic.P384(): hashFunc = crypto.SHA384 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384 case elliptic.P521(): hashFunc = crypto.SHA512 signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512 default: return nil, errors.New("x509: unknown elliptic curve") } oid, ok := oidFromNamedCurve(priv.PublicKey.Curve) if !ok { return nil, errors.New("x509: unknown elliptic curve") } publicKeyAlgorithm.Algorithm = oidPublicKeyECDSA var paramBytes []byte paramBytes, err = asn1.Marshal(oid) if err != nil { return } publicKeyAlgorithm.Parameters.FullBytes = paramBytes publicKeyBytes = elliptic.Marshal(priv.PublicKey.Curve, priv.PublicKey.X, priv.PublicKey.Y) default: return nil, errors.New("x509: only RSA private keys supported") } if err != nil { return } var asn1Subject []byte if len(template.RawSubject) > 0 { asn1Subject = template.RawSubject } else { asn1Subject, err = asn1.Marshal(template.Subject.ToRDNSequence()) } if err != nil { return } encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes} c := certificationRequestInfo{ Version: 0, Subject: asn1.RawValue{FullBytes: asn1Subject}, SubjectPKInfo: publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey}, } csrInfoContents, err := asn1.Marshal(c) if err != nil { return } c.Raw = csrInfoContents if !hashFunc.Available() { return nil, x509.ErrUnsupportedAlgorithm } h := hashFunc.New() h.Write(csrInfoContents) digest := h.Sum(nil) var signature []byte switch priv := priv.(type) { case *rsa.PrivateKey: signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest) case *ecdsa.PrivateKey: var r, s *big.Int if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil { signature, err = asn1.Marshal(ecdsaSignature{r, s}) } default: panic("internal error") } if err != nil { return } csr, err = asn1.Marshal(certificateSigningRequest{ nil, c, signatureAlgorithm, asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) return }
func (c *x509Certificate) CreateCRL(rand io.Reader, priv interface{}, revokedCerts []pkix.RevokedCertificate, now, expiry time.Time) (crlBytes []byte, err error) { var signatureAlgorithm pkix.AlgorithmIdentifier var hashFunc crypto.Hash switch priv := priv.(type) { // CRL signing for RSA Keys is already in x509 lib case *rsa.PrivateKey: return c.CreateCRL(rand, priv, revokedCerts, now, expiry) case *ecdsa.PrivateKey: switch priv.Curve { case elliptic.P224(), elliptic.P256(): signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA256 hashFunc = crypto.SHA256 case elliptic.P384(): signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA384 hashFunc = crypto.SHA384 case elliptic.P521(): signatureAlgorithm.Algorithm = oidSignatureECDSAWithSHA512 hashFunc = crypto.SHA512 default: return nil, errors.New("Unknown curve") } default: return nil, errors.New("Unknown key type") } tbsCertList := pkix.TBSCertificateList{ Version: 2, Signature: signatureAlgorithm, Issuer: c.Subject.ToRDNSequence(), ThisUpdate: now.UTC(), NextUpdate: expiry.UTC(), RevokedCertificates: revokedCerts, } tbsCertListContents, err := asn1.Marshal(tbsCertList) if err != nil { return } h := hashFunc.New() h.Write(tbsCertListContents) digest := h.Sum(nil) var signature []byte switch priv := priv.(type) { case *rsa.PrivateKey: signature, err = rsa.SignPKCS1v15(rand, priv, hashFunc, digest) case *ecdsa.PrivateKey: var r, s *big.Int if r, s, err = ecdsa.Sign(rand, priv, digest); err == nil { signature, err = asn1.Marshal(ecdsaSignature{r, s}) } default: return nil, errors.New("Unknown key type") } if err != nil { return } return asn1.Marshal(pkix.CertificateList{ TBSCertList: tbsCertList, SignatureAlgorithm: signatureAlgorithm, SignatureValue: asn1.BitString{Bytes: signature, BitLength: len(signature) * 8}, }) }