OSDN Git Service

Hulk did something
[bytom/vapor.git] / crypto / sm2 / pkcs1.go
diff --git a/crypto/sm2/pkcs1.go b/crypto/sm2/pkcs1.go
new file mode 100644 (file)
index 0000000..e1cc478
--- /dev/null
@@ -0,0 +1,117 @@
+package sm2
+
+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
+}
+
+// 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
+}
+
+// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
+type rsaPublicKey struct {
+       N *big.Int
+       E int
+}