mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 20:26:19 +08:00
add proxy methods for rsa pkcs1 pub/priv keys
This commit is contained in:
parent
0f0eec19d0
commit
82326621ee
@ -1,6 +1,10 @@
|
|||||||
package smx509
|
package smx509
|
||||||
|
|
||||||
import "math/big"
|
import (
|
||||||
|
"crypto/rsa"
|
||||||
|
"crypto/x509"
|
||||||
|
"math/big"
|
||||||
|
)
|
||||||
|
|
||||||
// pkcs1PrivateKey is a structure which mirrors the PKCS #1 ASN.1 for an RSA private key.
|
// pkcs1PrivateKey is a structure which mirrors the PKCS #1 ASN.1 for an RSA private key.
|
||||||
type pkcs1PrivateKey struct {
|
type pkcs1PrivateKey struct {
|
||||||
@ -31,3 +35,33 @@ type pkcs1PublicKey struct {
|
|||||||
N *big.Int
|
N *big.Int
|
||||||
E int
|
E int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParsePKCS1PrivateKey parses an RSA private key in PKCS #1, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY".
|
||||||
|
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
|
||||||
|
return x509.ParsePKCS1PrivateKey(der)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalPKCS1PrivateKey converts an RSA private key to PKCS #1, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "RSA PRIVATE KEY".
|
||||||
|
// For a more flexible key format which is not RSA specific, use
|
||||||
|
// MarshalPKCS8PrivateKey.
|
||||||
|
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
|
||||||
|
return x509.MarshalPKCS1PrivateKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParsePKCS1PublicKey parses an RSA public key in PKCS #1, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY".
|
||||||
|
func ParsePKCS1PublicKey(der []byte) (*rsa.PublicKey, error) {
|
||||||
|
return x509.ParsePKCS1PublicKey(der)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalPKCS1PublicKey converts an RSA public key to PKCS #1, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "RSA PUBLIC KEY".
|
||||||
|
func MarshalPKCS1PublicKey(key *rsa.PublicKey) []byte {
|
||||||
|
return x509.MarshalPKCS1PublicKey(key)
|
||||||
|
}
|
||||||
|
185
smx509/pkcs1_test.go
Normal file
185
smx509/pkcs1_test.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
package smx509
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto/rsa"
|
||||||
|
"encoding/asn1"
|
||||||
|
"encoding/pem"
|
||||||
|
"math/big"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestParsePKCS1PrivateKey(t *testing.T) {
|
||||||
|
block, _ := pem.Decode([]byte(pemPrivateKey))
|
||||||
|
priv, err := ParsePKCS1PrivateKey(block.Bytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Failed to parse private key: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if priv.PublicKey.N.Cmp(rsaPrivateKey.PublicKey.N) != 0 ||
|
||||||
|
priv.PublicKey.E != rsaPrivateKey.PublicKey.E ||
|
||||||
|
priv.D.Cmp(rsaPrivateKey.D) != 0 ||
|
||||||
|
priv.Primes[0].Cmp(rsaPrivateKey.Primes[0]) != 0 ||
|
||||||
|
priv.Primes[1].Cmp(rsaPrivateKey.Primes[1]) != 0 {
|
||||||
|
t.Errorf("got:%+v want:%+v", priv, rsaPrivateKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// This private key includes an invalid prime that
|
||||||
|
// rsa.PrivateKey.Validate should reject.
|
||||||
|
data := []byte("0\x16\x02\x00\x02\x02\u007f\x00\x02\x0200\x02\x0200\x02\x02\x00\x01\x02\x02\u007f\x00")
|
||||||
|
if _, err := ParsePKCS1PrivateKey(data); err == nil {
|
||||||
|
t.Errorf("parsing invalid private key did not result in an error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalRSAPrivateKey(t *testing.T) {
|
||||||
|
priv := &rsa.PrivateKey{
|
||||||
|
PublicKey: rsa.PublicKey{
|
||||||
|
N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
|
||||||
|
E: 3,
|
||||||
|
},
|
||||||
|
D: fromBase10("10897585948254795600358846499957366070880176878341177571733155050184921896034527397712889205732614568234385175145686545381899460748279607074689061600935843283397424506622998458510302603922766336783617368686090042765718290914099334449154829375179958369993407724946186243249568928237086215759259909861748642124071874879861299389874230489928271621259294894142840428407196932444474088857746123104978617098858619445675532587787023228852383149557470077802718705420275739737958953794088728369933811184572620857678792001136676902250566845618813972833750098806496641114644760255910789397593428910198080271317419213080834885003"),
|
||||||
|
Primes: []*big.Int{
|
||||||
|
fromBase10("1025363189502892836833747188838978207017355117492483312747347695538428729137306368764177201532277413433182799108299960196606011786562992097313508180436744488171474690412562218914213688661311117337381958560443"),
|
||||||
|
fromBase10("3467903426626310123395340254094941045497208049900750380025518552334536945536837294961497712862519984786362199788654739924501424784631315081391467293694361474867825728031147665777546570788493758372218019373"),
|
||||||
|
fromBase10("4597024781409332673052708605078359346966325141767460991205742124888960305710298765592730135879076084498363772408626791576005136245060321874472727132746643162385746062759369754202494417496879741537284589047"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
derBytes := MarshalPKCS1PrivateKey(priv)
|
||||||
|
|
||||||
|
priv2, err := ParsePKCS1PrivateKey(derBytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error parsing serialized key: %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if priv.PublicKey.N.Cmp(priv2.PublicKey.N) != 0 ||
|
||||||
|
priv.PublicKey.E != priv2.PublicKey.E ||
|
||||||
|
priv.D.Cmp(priv2.D) != 0 ||
|
||||||
|
len(priv2.Primes) != 3 ||
|
||||||
|
priv.Primes[0].Cmp(priv2.Primes[0]) != 0 ||
|
||||||
|
priv.Primes[1].Cmp(priv2.Primes[1]) != 0 ||
|
||||||
|
priv.Primes[2].Cmp(priv2.Primes[2]) != 0 {
|
||||||
|
t.Errorf("got:%+v want:%+v", priv, priv2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMarshalRSAPublicKey(t *testing.T) {
|
||||||
|
pub := &rsa.PublicKey{
|
||||||
|
N: fromBase10("16346378922382193400538269749936049106320265317511766357599732575277382844051791096569333808598921852351577762718529818072849191122419410612033592401403764925096136759934497687765453905884149505175426053037420486697072448609022753683683718057795566811401938833367954642951433473337066311978821180526439641496973296037000052546108507805269279414789035461158073156772151892452251106173507240488993608650881929629163465099476849643165682709047462010581308719577053905787496296934240246311806555924593059995202856826239801816771116902778517096212527979497399966526283516447337775509777558018145573127308919204297111496233"),
|
||||||
|
E: 3,
|
||||||
|
}
|
||||||
|
derBytes := MarshalPKCS1PublicKey(pub)
|
||||||
|
pub2, err := ParsePKCS1PublicKey(derBytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("ParsePKCS1PublicKey: %s", err)
|
||||||
|
}
|
||||||
|
if pub.N.Cmp(pub2.N) != 0 || pub.E != pub2.E {
|
||||||
|
t.Errorf("ParsePKCS1PublicKey = %+v, want %+v", pub, pub2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's never been documented that asn1.Marshal/Unmarshal on rsa.PublicKey works,
|
||||||
|
// but it does, and we know of code that depends on it.
|
||||||
|
// Lock that in, even though we'd prefer that people use MarshalPKCS1PublicKey and ParsePKCS1PublicKey.
|
||||||
|
derBytes2, err := asn1.Marshal(*pub)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Marshal(rsa.PublicKey): %v", err)
|
||||||
|
} else if !bytes.Equal(derBytes, derBytes2) {
|
||||||
|
t.Errorf("Marshal(rsa.PublicKey) = %x, want %x", derBytes2, derBytes)
|
||||||
|
}
|
||||||
|
pub3 := new(rsa.PublicKey)
|
||||||
|
rest, err := asn1.Unmarshal(derBytes, pub3)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Unmarshal(rsa.PublicKey): %v", err)
|
||||||
|
}
|
||||||
|
if len(rest) != 0 || pub.N.Cmp(pub3.N) != 0 || pub.E != pub3.E {
|
||||||
|
t.Errorf("Unmarshal(rsa.PublicKey) = %+v, %q want %+v, %q", pub, rest, pub2, []byte(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
publicKeys := []struct {
|
||||||
|
derBytes []byte
|
||||||
|
expectedErrSubstr string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 6, // SEQUENCE, 6 bytes
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
17,
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
3, // 3
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 6, // SEQUENCE
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
0xff, // -1
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
3,
|
||||||
|
},
|
||||||
|
expectedErrSubstr: "zero or negative",
|
||||||
|
}, {
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 6, // SEQUENCE
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
17,
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
0xff, // -1
|
||||||
|
},
|
||||||
|
expectedErrSubstr: "zero or negative",
|
||||||
|
}, {
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 6, // SEQUENCE
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
17,
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
3,
|
||||||
|
1,
|
||||||
|
},
|
||||||
|
expectedErrSubstr: "trailing data",
|
||||||
|
}, {
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 9, // SEQUENCE
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
17,
|
||||||
|
0x02, 4, // INTEGER, 4 bytes
|
||||||
|
0x7f, 0xff, 0xff, 0xff,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
derBytes: []byte{
|
||||||
|
0x30, 10, // SEQUENCE
|
||||||
|
0x02, 1, // INTEGER, 1 byte
|
||||||
|
17,
|
||||||
|
0x02, 5, // INTEGER, 5 bytes
|
||||||
|
0x00, 0x80, 0x00, 0x00, 0x00,
|
||||||
|
},
|
||||||
|
// On 64-bit systems, encoding/asn1 will accept the
|
||||||
|
// public exponent, but ParsePKCS1PublicKey will return
|
||||||
|
// an error. On 32-bit systems, encoding/asn1 will
|
||||||
|
// return the error. The common substring of both error
|
||||||
|
// is the word “large”.
|
||||||
|
expectedErrSubstr: "large",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, test := range publicKeys {
|
||||||
|
shouldFail := len(test.expectedErrSubstr) > 0
|
||||||
|
pub, err := ParsePKCS1PublicKey(test.derBytes)
|
||||||
|
if shouldFail {
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("#%d: unexpected success, got %#v", i, pub)
|
||||||
|
} else if !strings.Contains(err.Error(), test.expectedErrSubstr) {
|
||||||
|
t.Errorf("#%d: expected error containing %q, got %s", i, test.expectedErrSubstr, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("#%d: unexpected failure: %s", i, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
reserialized := MarshalPKCS1PublicKey(pub)
|
||||||
|
if !bytes.Equal(reserialized, test.derBytes) {
|
||||||
|
t.Errorf("#%d: failed to reserialize: got %x, expected %x", i, reserialized, test.derBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user