mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-28 05:06:18 +08:00
smx509: ParseTypedECPrivateKey, return real privae key type
This commit is contained in:
parent
bf037a329e
commit
dd8b2f61dd
@ -22,7 +22,7 @@ type EncrypterOpts interface {
|
|||||||
Decrypt(key, ciphertext []byte) ([]byte, error)
|
Decrypt(key, ciphertext []byte) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// XOREncrypterOpts represents XOR encrypt type/mode.
|
// XOREncrypterOpts represents XOR mode.
|
||||||
type XOREncrypterOpts struct{}
|
type XOREncrypterOpts struct{}
|
||||||
|
|
||||||
func (opts *XOREncrypterOpts) GetEncryptType() encryptType {
|
func (opts *XOREncrypterOpts) GetEncryptType() encryptType {
|
||||||
@ -62,6 +62,7 @@ func (opts *baseBlockEncrypterOpts) GetKeySize(plaintext []byte) int {
|
|||||||
return opts.cipherKeySize
|
return opts.cipherKeySize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CBCEncrypterOpts represents CBC (Cipher block chaining) mode.
|
||||||
type CBCEncrypterOpts struct {
|
type CBCEncrypterOpts struct {
|
||||||
baseBlockEncrypterOpts
|
baseBlockEncrypterOpts
|
||||||
padding padding.Padding
|
padding padding.Padding
|
||||||
@ -76,6 +77,7 @@ func NewCBCEncrypterOpts(padding padding.Padding, cipherFactory CipherFactory, k
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
|
||||||
func (opts *CBCEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
func (opts *CBCEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
||||||
block, err := opts.cipherFactory(key)
|
block, err := opts.cipherFactory(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -99,7 +101,7 @@ func (opts *CBCEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
blockSize := block.BlockSize()
|
blockSize := block.BlockSize()
|
||||||
if len(ciphertext) < blockSize {
|
if len(ciphertext) <= blockSize {
|
||||||
return nil, ErrDecryption
|
return nil, ErrDecryption
|
||||||
}
|
}
|
||||||
iv := ciphertext[:blockSize]
|
iv := ciphertext[:blockSize]
|
||||||
@ -110,6 +112,7 @@ func (opts *CBCEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return opts.padding.Unpad(plaintext)
|
return opts.padding.Unpad(plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ECBEncrypterOpts represents ECB (Electronic Code Book) mode.
|
||||||
type ECBEncrypterOpts struct {
|
type ECBEncrypterOpts struct {
|
||||||
baseBlockEncrypterOpts
|
baseBlockEncrypterOpts
|
||||||
padding padding.Padding
|
padding padding.Padding
|
||||||
@ -150,6 +153,7 @@ func (opts *ECBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return opts.padding.Unpad(plaintext)
|
return opts.padding.Unpad(plaintext)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CFBEncrypterOpts represents CFB (Cipher Feedback) mode.
|
||||||
type CFBEncrypterOpts struct {
|
type CFBEncrypterOpts struct {
|
||||||
baseBlockEncrypterOpts
|
baseBlockEncrypterOpts
|
||||||
}
|
}
|
||||||
@ -162,6 +166,7 @@ func NewCFBEncrypterOpts(cipherFactory CipherFactory, keySize int) EncrypterOpts
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
|
||||||
func (opts *CFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
func (opts *CFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
||||||
block, err := opts.cipherFactory(key)
|
block, err := opts.cipherFactory(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -184,7 +189,7 @@ func (opts *CFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
blockSize := block.BlockSize()
|
blockSize := block.BlockSize()
|
||||||
if len(ciphertext) < blockSize {
|
if len(ciphertext) <= blockSize {
|
||||||
return nil, ErrDecryption
|
return nil, ErrDecryption
|
||||||
}
|
}
|
||||||
iv := ciphertext[:blockSize]
|
iv := ciphertext[:blockSize]
|
||||||
@ -195,6 +200,7 @@ func (opts *CFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return plaintext, nil
|
return plaintext, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OFBEncrypterOpts represents OFB (Output Feedback) mode.
|
||||||
type OFBEncrypterOpts struct {
|
type OFBEncrypterOpts struct {
|
||||||
baseBlockEncrypterOpts
|
baseBlockEncrypterOpts
|
||||||
}
|
}
|
||||||
@ -207,6 +213,7 @@ func NewOFBEncrypterOpts(cipherFactory CipherFactory, keySize int) EncrypterOpts
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Encrypt encrypts the plaintext with the key, includes generated IV at the beginning of the ciphertext.
|
||||||
func (opts *OFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
func (opts *OFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
|
||||||
block, err := opts.cipherFactory(key)
|
block, err := opts.cipherFactory(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -229,7 +236,7 @@ func (opts *OFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
blockSize := block.BlockSize()
|
blockSize := block.BlockSize()
|
||||||
if len(ciphertext) < blockSize {
|
if len(ciphertext) <= blockSize {
|
||||||
return nil, ErrDecryption
|
return nil, ErrDecryption
|
||||||
}
|
}
|
||||||
iv := ciphertext[:blockSize]
|
iv := ciphertext[:blockSize]
|
||||||
|
@ -1716,7 +1716,7 @@ func makeConstraintsLeafCert(leaf leafSpec, key *ecdsa.PrivateKey, parent *Certi
|
|||||||
parent = template
|
parent = template
|
||||||
}
|
}
|
||||||
|
|
||||||
derBytes, err := CreateCertificate(rand.Reader, template.asX509(), parent.asX509(), &key.PublicKey, parentKey)
|
derBytes, err := CreateCertificate(rand.Reader, template, parent, &key.PublicKey, parentKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ func ParseECPrivateKey(der []byte) (*ecdsa.PrivateKey, error) {
|
|||||||
return parseECPrivateKey(nil, der)
|
return parseECPrivateKey(nil, der)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseSM2PrivateKey parses an SM2 private key
|
// ParseSM2PrivateKey parses an SM2 private key in SEC 1, ASN.1 DER form.
|
||||||
func ParseSM2PrivateKey(der []byte) (*sm2.PrivateKey, error) {
|
func ParseSM2PrivateKey(der []byte) (*sm2.PrivateKey, error) {
|
||||||
key, err := parseECPrivateKey(nil, der)
|
key, err := parseECPrivateKey(nil, der)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -43,6 +43,22 @@ func ParseSM2PrivateKey(der []byte) (*sm2.PrivateKey, error) {
|
|||||||
return new(sm2.PrivateKey).FromECPrivateKey(key)
|
return new(sm2.PrivateKey).FromECPrivateKey(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ParseTypedECPrivateKey parses an EC private key in SEC 1, ASN.1 DER form.
|
||||||
|
//
|
||||||
|
// It returns a *ecdsa.PrivateKey or a *sm2.PrivateKey.
|
||||||
|
//
|
||||||
|
// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
|
||||||
|
func ParseTypedECPrivateKey(der []byte) (interface{}, error) {
|
||||||
|
key, err := parseECPrivateKey(nil, der)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if key.Curve == sm2.P256() {
|
||||||
|
return new(sm2.PrivateKey).FromECPrivateKey(key)
|
||||||
|
}
|
||||||
|
return key, nil
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form.
|
// MarshalECPrivateKey converts an EC private key to SEC 1, ASN.1 DER form.
|
||||||
//
|
//
|
||||||
// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
|
// This kind of key is commonly encoded in PEM blocks of type "EC PRIVATE KEY".
|
||||||
|
@ -2,6 +2,7 @@ package smx509
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"crypto/ecdsa"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -75,3 +76,30 @@ func TestMarshalSM2PrivateKey(t *testing.T) {
|
|||||||
}
|
}
|
||||||
fmt.Printf("%s\n", hex.EncodeToString(res))
|
fmt.Printf("%s\n", hex.EncodeToString(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestParseTypedECPrivateKey(t *testing.T) {
|
||||||
|
for i, test := range ecKeyTests {
|
||||||
|
derBytes, _ := hex.DecodeString(test.derHex)
|
||||||
|
key, err := ParseTypedECPrivateKey(derBytes)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("#%d: failed to decode EC private key: %s", i, err)
|
||||||
|
}
|
||||||
|
var serialized []byte
|
||||||
|
switch privKey := key.(type) {
|
||||||
|
case *ecdsa.PrivateKey:
|
||||||
|
serialized, err = MarshalECPrivateKey(privKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("#%d: failed to encode EC private key: %s", i, err)
|
||||||
|
}
|
||||||
|
case *sm2.PrivateKey:
|
||||||
|
serialized, err = MarshalSM2PrivateKey(privKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("#%d: failed to encode SM2 private key: %s", i, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
matches := bytes.Equal(serialized, derBytes)
|
||||||
|
if matches != test.shouldReserialize {
|
||||||
|
t.Fatalf("#%d: when serializing key: matches=%t, should match=%t: original %x, reserialized %x", i, matches, test.shouldReserialize, serialized, derBytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user