Example #1
0
// ParseOneCertificateFromPEM attempts to parse one PEM encoded certificate object,
// either a raw x509 certificate or a PKCS #7 structure possibly containing
// multiple certificates, from the top of certsPEM, which itself may
// contain multiple PEM encoded certificate objects.
func ParseOneCertificateFromPEM(certsPEM []byte) ([]*x509.Certificate, []byte, error) {

	block, rest := pem.Decode(certsPEM)
	if block == nil {
		return nil, rest, nil
	}

	cert, err := x509.ParseCertificate(block.Bytes)
	if err != nil {
		pkcs7data, err := pkcs7.ParsePKCS7(block.Bytes)
		if err != nil {
			return nil, rest, err
		}
		if pkcs7data.ContentInfo != "SignedData" {
			return nil, rest, errors.New("only PKCS #7 Signed Data Content Info supported for certificate parsing")
		}
		certs := pkcs7data.Content.SignedData.Certificates
		if certs == nil {
			return nil, rest, errors.New("PKCS #7 structure contains no certificates")
		}
		return certs, rest, nil
	}
	var certs = []*x509.Certificate{cert}
	return certs, rest, nil
}
Example #2
0
// Given a slice of PKCS #7 content infos containing PKCS #12 Safe Bag Data,
// getBags returns those Safe Bags.
func getBags(authenticatedSafe []asn1.RawValue, password []byte) (bags []safeBag, err error) {
	for _, contentInfo := range authenticatedSafe {

		var safeContents []safeBag
		bagContainer, err := pkcs7.ParsePKCS7(contentInfo.FullBytes)
		if err != nil {
			return nil, err
		}
		switch {
		case bagContainer.ContentInfo == "Data":
			if _, err = asn1.Unmarshal(bagContainer.Content.Data, &safeContents); err != nil {
				return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
			}
		case bagContainer.ContentInfo == "EncryptedData":
			data, err := decrypt(bagContainer.Content.EncryptedData.EncryptedContentInfo.ContentEncryptionAlgorithm,
				bagContainer.Content.EncryptedData.EncryptedContentInfo.EncryptedContent, password)
			if err != nil {
				return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
			}
			if _, err = asn1.Unmarshal(data, &safeContents); err != nil {
				return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
			}
		default:
			return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for bags encoded in Data and EncryptedData types"))
		}

		bags = append(bags, safeContents...)
	}
	return bags, nil

}
Example #3
0
// ParseCertificatesDER parses a DER encoding of a certificate object and possibly private key,
// either PKCS #7, PKCS #12, or raw x509.
func ParseCertificatesDER(certsDER []byte, password string) ([]*x509.Certificate, crypto.Signer, error) {
	var certs []*x509.Certificate
	var key crypto.Signer
	certsDER = bytes.TrimSpace(certsDER)
	pkcs7data, err := pkcs7.ParsePKCS7(certsDER)
	if err != nil {
		pkcs12data, err := pkcs12.ParsePKCS12(certsDER, []byte(password))
		if err != nil {
			certs, err = x509.ParseCertificates(certsDER)
			if err != nil {
				return nil, nil, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
			}
		} else {
			key = pkcs12data.PrivateKey
			certs = pkcs12data.Certificates
		}
	} else {
		if pkcs7data.ContentInfo != "SignedData" {
			return nil, nil, cferr.Wrap(cferr.CertificateError, cferr.DecodeFailed, errors.New("can only extract certificates from signed data content info"))
		}
		certs = pkcs7data.Content.SignedData.Certificates
	}
	if certs == nil {
		return nil, key, cferr.New(cferr.CertificateError, cferr.DecodeFailed)
	}
	return certs, key, nil
}
Example #4
0
// ParsePKCS12 parses a pkcs12 syntax object
// into a container for a private key, certificate(s), and
// version number
func ParsePKCS12(raw, password []byte) (msg *PKCS12, err error) {
	msg = new(PKCS12)
	password, err = pbkdf.BMPString(password)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
	}
	var Pfx pfx
	_, err = asn1.Unmarshal(raw, &Pfx)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
	}

	if msg.Version = Pfx.Version; msg.Version != 3 {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("Only support for PKCS #12 PFX version 3"))
	}
	authSafe, err := pkcs7.ParsePKCS7(Pfx.AuthSafe.FullBytes)

	if err != nil {
		return nil, err
	}
	if authSafe.ContentInfo != "Data" {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
	}
	var authenticatedSafe []asn1.RawValue
	_, err = asn1.Unmarshal(authSafe.Content.Data, &authenticatedSafe)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)

	}

	if len(authenticatedSafe) != 2 {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
	}
	var bags []safeBag
	bags, err = getBags(authenticatedSafe, password)
	if err != nil {
		return nil, err
	}
	if len(bags) > 2 || bags == nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, errors.New("No support for AuthSafe Format"))
	}

	certs, pkey, err := parseBags(bags, password)
	if err != nil {
		return nil, cferr.Wrap(cferr.CertificateError, cferr.ParseFailed, err)
	}
	msg.Certificates = certs
	msg.PrivateKey = pkey
	return

}