| 80 | } |
| 81 | |
| 82 | func validateRSAKeyIfPresent(key interface{}, encryptedKey *etree.Element) (*rsa.PrivateKey, error) { |
| 83 | rsaKey, ok := key.(*rsa.PrivateKey) |
| 84 | if !ok { |
| 85 | return nil, errors.New("expected key to be a *rsa.PrivateKey") |
| 86 | } |
| 87 | |
| 88 | // extract and verify that the public key matches the certificate |
| 89 | // this section is included to either let the service know up front |
| 90 | // if the key will work, or let the service provider know which key |
| 91 | // to use to decrypt the message. Either way, verification is not |
| 92 | // security-critical. |
| 93 | if el := encryptedKey.FindElement("./KeyInfo/X509Data/X509Certificate"); el != nil { |
| 94 | certPEMbuf := el.Text() |
| 95 | certPEMbuf = "-----BEGIN CERTIFICATE-----\n" + certPEMbuf + "\n-----END CERTIFICATE-----\n" |
| 96 | certPEM, _ := pem.Decode([]byte(certPEMbuf)) |
| 97 | if certPEM == nil { |
| 98 | return nil, fmt.Errorf("invalid certificate") |
| 99 | } |
| 100 | cert, err := x509.ParseCertificate(certPEM.Bytes) |
| 101 | if err != nil { |
| 102 | return nil, err |
| 103 | } |
| 104 | pubKey, ok := cert.PublicKey.(*rsa.PublicKey) |
| 105 | if !ok { |
| 106 | return nil, fmt.Errorf("expected certificate to be an *rsa.PublicKey") |
| 107 | } |
| 108 | if rsaKey.N.Cmp(pubKey.N) != 0 || rsaKey.E != pubKey.E { |
| 109 | return nil, fmt.Errorf("certificate does not match provided key") |
| 110 | } |
| 111 | } else if el = encryptedKey.FindElement("./KeyInfo/X509Data/X509IssuerSerial"); el != nil { |
| 112 | // TODO: determine how to validate the issuer serial information |
| 113 | } |
| 114 | return rsaKey, nil |
| 115 | } |