| // Copyright 2011 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package x509 |
| |
| import ( |
| "crypto/rsa" |
| "encoding/asn1" |
| "errors" |
| "math/big" |
| ) |
| |
| // pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key. |
| type pkcs1PrivateKey struct { |
| Version int |
| N *big.Int |
| E int |
| D *big.Int |
| P *big.Int |
| Q *big.Int |
| // We ignore these values, if present, because rsa will calculate them. |
| Dp *big.Int `asn1:"optional"` |
| Dq *big.Int `asn1:"optional"` |
| Qinv *big.Int `asn1:"optional"` |
| |
| AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"` |
| } |
| |
| type pkcs1AdditionalRSAPrime struct { |
| Prime *big.Int |
| |
| // We ignore these values because rsa will calculate them. |
| Exp *big.Int |
| Coeff *big.Int |
| } |
| |
| // pkcs1PublicKey reflects the ASN.1 structure of a PKCS#1 public key. |
| type pkcs1PublicKey struct { |
| N *big.Int |
| E int |
| } |
| |
| // ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. |
| func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) { |
| var priv pkcs1PrivateKey |
| rest, err := asn1.Unmarshal(der, &priv) |
| if len(rest) > 0 { |
| return nil, asn1.SyntaxError{Msg: "trailing data"} |
| } |
| if err != nil { |
| return nil, err |
| } |
| |
| if priv.Version > 1 { |
| return nil, errors.New("x509: unsupported private key version") |
| } |
| |
| if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { |
| return nil, errors.New("x509: private key contains zero or negative value") |
| } |
| |
| key := new(rsa.PrivateKey) |
| key.PublicKey = rsa.PublicKey{ |
| E: priv.E, |
| N: priv.N, |
| } |
| |
| key.D = priv.D |
| key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) |
| key.Primes[0] = priv.P |
| key.Primes[1] = priv.Q |
| for i, a := range priv.AdditionalPrimes { |
| if a.Prime.Sign() <= 0 { |
| return nil, errors.New("x509: private key contains zero or negative prime") |
| } |
| key.Primes[i+2] = a.Prime |
| // We ignore the other two values because rsa will calculate |
| // them as needed. |
| } |
| |
| err = key.Validate() |
| if err != nil { |
| return nil, err |
| } |
| key.Precompute() |
| |
| return key, nil |
| } |
| |
| // MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form. |
| func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte { |
| key.Precompute() |
| |
| version := 0 |
| if len(key.Primes) > 2 { |
| version = 1 |
| } |
| |
| priv := pkcs1PrivateKey{ |
| Version: version, |
| N: key.N, |
| E: key.PublicKey.E, |
| D: key.D, |
| P: key.Primes[0], |
| Q: key.Primes[1], |
| Dp: key.Precomputed.Dp, |
| Dq: key.Precomputed.Dq, |
| Qinv: key.Precomputed.Qinv, |
| } |
| |
| priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues)) |
| for i, values := range key.Precomputed.CRTValues { |
| priv.AdditionalPrimes[i].Prime = key.Primes[2+i] |
| priv.AdditionalPrimes[i].Exp = values.Exp |
| priv.AdditionalPrimes[i].Coeff = values.Coeff |
| } |
| |
| b, _ := asn1.Marshal(priv) |
| return b |
| } |
| |
| // ParsePKCS1PublicKey parses a PKCS#1 public key in ASN.1 DER form. |
| func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) { |
| var pub pkcs1PublicKey |
| rest, err := asn1.Unmarshal(der, &pub) |
| if err != nil { |
| return nil, err |
| } |
| if len(rest) > 0 { |
| return nil, asn1.SyntaxError{Msg: "trailing data"} |
| } |
| |
| if pub.N.Sign() <= 0 || pub.E <= 0 { |
| return nil, errors.New("x509: public key contains zero or negative value") |
| } |
| if pub.E > 1<<31-1 { |
| return nil, errors.New("x509: public key contains large public exponent") |
| } |
| |
| return &rsa.PublicKey{ |
| E: pub.E, |
| N: pub.N, |
| }, nil |
| } |
| |
| // MarshalPKCS1PublicKey converts an RSA public key to PKCS#1, ASN.1 DER form. |
| func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte { |
| derBytes, _ := asn1.Marshal(pkcs1PublicKey{ |
| N: key.N, |
| E: key.E, |
| }) |
| return derBytes |
| } |