smx509: ParseTypedECPrivateKey, return real privae key type

This commit is contained in:
Sun Yimin 2023-02-14 16:03:05 +08:00 committed by GitHub
parent bf037a329e
commit dd8b2f61dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 6 deletions

View File

@ -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]

View File

@ -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
} }

View File

@ -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".

View File

@ -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)
}
}
}