func pkixNameToString(name *pkix.Name) string { seq := name.ToRDNSequence() var s bytes.Buffer for _, rdnSet := range seq { for _, rdn := range rdnSet { if s.Len() != 0 { s.WriteString(",") } key := "" t := rdn.Type if len(t) == 4 && t[0] == 2 && t[1] == 5 && t[2] == 4 { switch t[3] { case 3: key = "cn" case 5: key = "serial" case 6: key = "c" case 7: key = "l" case 10: key = "o" case 11: key = "ou" } } if key == "" { key = t.String() } s.WriteString(fmt.Sprintf("%v=%v", key, rdn.Value)) } } return s.String() }
// signPKCS7 does the minimal amount of work necessary to embed an RSA // signature into a PKCS#7 certificate. // // We prepare the certificate using the x509 package, read it back in // to our custom data type and then write it back out with the signature. func signPKCS7(rand io.Reader, priv *rsa.PrivateKey, msg []byte) ([]byte, error) { const serialNumber = 0x5462c4dd // arbitrary name := pkix.Name{CommonName: "gomobile"} template := &x509.Certificate{ SerialNumber: big.NewInt(serialNumber), SignatureAlgorithm: x509.SHA1WithRSA, Subject: name, } b, err := x509.CreateCertificate(rand, template, template, priv.Public(), priv) if err != nil { return nil, err } c := certificate{} if _, err := asn1.Unmarshal(b, &c); err != nil { return nil, err } h := sha1.New() h.Write(msg) hashed := h.Sum(nil) signed, err := rsa.SignPKCS1v15(rand, priv, crypto.SHA1, hashed) if err != nil { return nil, err } content := pkcs7SignedData{ ContentType: oidSignedData, Content: signedData{ Version: 1, DigestAlgorithms: []pkix.AlgorithmIdentifier{{ Algorithm: oidSHA1, Parameters: asn1.RawValue{Tag: 5}, }}, ContentInfo: contentInfo{Type: oidData}, Certificates: c, SignerInfos: []signerInfo{{ Version: 1, IssuerAndSerialNumber: issuerAndSerialNumber{ Issuer: name.ToRDNSequence(), SerialNumber: serialNumber, }, DigestAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: oidSHA1, Parameters: asn1.RawValue{Tag: 5}, }, DigestEncryptionAlgorithm: pkix.AlgorithmIdentifier{ Algorithm: oidRSAEncryption, Parameters: asn1.RawValue{Tag: 5}, }, EncryptedDigest: signed, }}, }, } return asn1.Marshal(content) }