Add PKCS#1 RSA key related helpers stolen from orkey.
These routines can handle Tor's idea of an RSA key, assuming PEM/Base64 handling is done as appropriate.
This commit is contained in:
parent
28616763d2
commit
f6128d70b6
|
@ -0,0 +1,85 @@
|
||||||
|
//
|
||||||
|
// rsa.go - PKCS#1 RSA key related helpers.
|
||||||
|
//
|
||||||
|
// To the extent possible under law, Yawning Angel has waived all copyright and
|
||||||
|
// related or neighboring rights to bulb, using the creative commons
|
||||||
|
// "cc0" public domain dedication. See LICENSE or
|
||||||
|
// <http://creativecommons.org/publicdomain/zero/1.0/> for full details.
|
||||||
|
|
||||||
|
// Package pkcs1 implements PKCS#1 RSA key marshalling/unmarshalling,
|
||||||
|
// compatibile with Tor's usage.
|
||||||
|
package pkcs1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"encoding/asn1"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
|
type pkcs1RSAPrivKey struct {
|
||||||
|
Version int // version
|
||||||
|
N *big.Int // modulus
|
||||||
|
E int // publicExponent
|
||||||
|
D *big.Int // privateExponent
|
||||||
|
P *big.Int // prime1
|
||||||
|
Q *big.Int // prime2
|
||||||
|
Dp *big.Int // exponent1: d mod (p-1)
|
||||||
|
Dq *big.Int // exponent2: d mod (q-1)
|
||||||
|
Qinv *big.Int // coefficient: (inverse of q) mod p
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodePrivateKeyDER returns the PKCS#1 DER encoding of a rsa.PrivateKey.
|
||||||
|
func EncodePrivateKeyDER(sk *rsa.PrivateKey) ([]byte, error) {
|
||||||
|
// The crypto.RSA structure has a slightly different layout than PKCS#1
|
||||||
|
// private keys, so directly marshaling does not work. Pull out the values
|
||||||
|
// into a strucuture with the correct layout and marshal.
|
||||||
|
sk.Precompute() // Ensure that the structure is fully populated.
|
||||||
|
k := pkcs1RSAPrivKey{
|
||||||
|
Version: 0,
|
||||||
|
N: sk.N,
|
||||||
|
E: sk.E,
|
||||||
|
D: sk.D,
|
||||||
|
P: sk.Primes[0],
|
||||||
|
Q: sk.Primes[1],
|
||||||
|
Dp: sk.Precomputed.Dp,
|
||||||
|
Dq: sk.Precomputed.Dq,
|
||||||
|
Qinv: sk.Precomputed.Qinv,
|
||||||
|
}
|
||||||
|
return asn1.Marshal(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodePrivateKeyDER returns the rsa.PrivateKey decoding of a PKCS#1 DER blob.
|
||||||
|
func DecodePrivateKeyDER(b []byte) (*rsa.PrivateKey, []byte, error) {
|
||||||
|
var k pkcs1RSAPrivKey
|
||||||
|
rest, err := asn1.Unmarshal(b, &k)
|
||||||
|
if err == nil {
|
||||||
|
sk := &rsa.PrivateKey{}
|
||||||
|
sk.Primes = make([]*big.Int, 2)
|
||||||
|
sk.N = k.N
|
||||||
|
sk.E = k.E
|
||||||
|
sk.D = k.D
|
||||||
|
sk.Primes[0] = k.P
|
||||||
|
sk.Primes[1] = k.Q
|
||||||
|
|
||||||
|
// Ignore the precomputed values and just rederive them.
|
||||||
|
sk.Precompute()
|
||||||
|
return sk, rest, nil
|
||||||
|
}
|
||||||
|
return nil, rest, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// EncodePublicKeyDER returns the PKCS#1 DER encoding of a rsa.PublicKey.
|
||||||
|
func EncodePublicKeyDER(pk *rsa.PublicKey) ([]byte, error) {
|
||||||
|
// The crypto.RSA structure is exactly the same as the PCKS#1 public keys,
|
||||||
|
// when the encoding/asn.1 marshaller is done with it.
|
||||||
|
//
|
||||||
|
// DER encoding of (SEQUENCE | INTEGER(n) | INTEGER(e))
|
||||||
|
return asn1.Marshal(*pk)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodePublicKeyDER returns the rsa.PublicKey decoding of a PKCS#1 DER blob.
|
||||||
|
func DecodePublicKeyDER(b []byte) (*rsa.PublicKey, []byte, error) {
|
||||||
|
pk := &rsa.PublicKey{}
|
||||||
|
rest, err := asn1.Unmarshal(b, pk)
|
||||||
|
return pk, rest, err
|
||||||
|
}
|
Reference in New Issue