1 Star 0 Fork 0

妥協 / fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
keys.go 10.15 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package utils
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/asn1"
"encoding/pem"
"errors"
"fmt"
)
// struct to hold info required for PKCS#8
type pkcs8Info struct {
Version int
PrivateKeyAlgorithm []asn1.ObjectIdentifier
PrivateKey []byte
}
type ecPrivateKey struct {
Version int
PrivateKey []byte
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
}
var (
oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
)
var oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
switch curve {
case elliptic.P224():
return oidNamedCurveP224, true
case elliptic.P256():
return oidNamedCurveP256, true
case elliptic.P384():
return oidNamedCurveP384, true
case elliptic.P521():
return oidNamedCurveP521, true
}
return nil, false
}
// PrivateKeyToDER marshals a private key to der
func PrivateKeyToDER(privateKey *ecdsa.PrivateKey) ([]byte, error) {
if privateKey == nil {
return nil, errors.New("Invalid ecdsa private key. It must be different from nil.")
}
return x509.MarshalECPrivateKey(privateKey)
}
// PrivateKeyToPEM converts the private key to PEM format.
// EC private keys are converted to PKCS#8 format.
func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
// Validate inputs
if len(pwd) != 0 {
return PrivateKeyToEncryptedPEM(privateKey, pwd)
}
if privateKey == nil {
return nil, errors.New("Invalid key. It must be different from nil.")
}
switch k := privateKey.(type) {
case *ecdsa.PrivateKey:
if k == nil {
return nil, errors.New("Invalid ecdsa private key. It must be different from nil.")
}
// get the oid for the curve
oidNamedCurve, ok := oidFromNamedCurve(k.Curve)
if !ok {
return nil, errors.New("unknown elliptic curve")
}
// based on https://golang.org/src/crypto/x509/sec1.go
privateKeyBytes := k.D.Bytes()
paddedPrivateKey := make([]byte, (k.Curve.Params().N.BitLen()+7)/8)
copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
// omit NamedCurveOID for compatibility as it's optional
asn1Bytes, err := asn1.Marshal(ecPrivateKey{
Version: 1,
PrivateKey: paddedPrivateKey,
PublicKey: asn1.BitString{Bytes: elliptic.Marshal(k.Curve, k.X, k.Y)},
})
if err != nil {
return nil, fmt.Errorf("error marshaling EC key to asn1 [%s]", err)
}
var pkcs8Key pkcs8Info
pkcs8Key.Version = 0
pkcs8Key.PrivateKeyAlgorithm = make([]asn1.ObjectIdentifier, 2)
pkcs8Key.PrivateKeyAlgorithm[0] = oidPublicKeyECDSA
pkcs8Key.PrivateKeyAlgorithm[1] = oidNamedCurve
pkcs8Key.PrivateKey = asn1Bytes
pkcs8Bytes, err := asn1.Marshal(pkcs8Key)
if err != nil {
return nil, fmt.Errorf("error marshaling EC key to asn1 [%s]", err)
}
return pem.EncodeToMemory(
&pem.Block{
Type: "PRIVATE KEY",
Bytes: pkcs8Bytes,
},
), nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PrivateKey")
}
}
// PrivateKeyToEncryptedPEM converts a private key to an encrypted PEM
func PrivateKeyToEncryptedPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
if privateKey == nil {
return nil, errors.New("Invalid private key. It must be different from nil.")
}
switch k := privateKey.(type) {
case *ecdsa.PrivateKey:
if k == nil {
return nil, errors.New("Invalid ecdsa private key. It must be different from nil.")
}
raw, err := x509.MarshalECPrivateKey(k)
if err != nil {
return nil, err
}
block, err := x509.EncryptPEMBlock(
rand.Reader,
"PRIVATE KEY",
raw,
pwd,
x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(block), nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PrivateKey")
}
}
// DERToPrivateKey unmarshals a der to private key
func DERToPrivateKey(der []byte) (key interface{}, err error) {
if key, err = x509.ParsePKCS1PrivateKey(der); err == nil {
return key, nil
}
if key, err = x509.ParsePKCS8PrivateKey(der); err == nil {
switch key.(type) {
case *ecdsa.PrivateKey:
return
default:
return nil, errors.New("Found unknown private key type in PKCS#8 wrapping")
}
}
if key, err = x509.ParseECPrivateKey(der); err == nil {
return
}
return nil, errors.New("Invalid key type. The DER must contain an ecdsa.PrivateKey")
}
// PEMtoPrivateKey unmarshals a pem to private key
func PEMtoPrivateKey(raw []byte, pwd []byte) (interface{}, error) {
if len(raw) == 0 {
return nil, errors.New("Invalid PEM. It must be different from nil.")
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, fmt.Errorf("Failed decoding PEM. Block must be different from nil. [% x]", raw)
}
// TODO: derive from header the type of the key
if x509.IsEncryptedPEMBlock(block) {
if len(pwd) == 0 {
return nil, errors.New("Encrypted Key. Need a password")
}
decrypted, err := x509.DecryptPEMBlock(block, pwd)
if err != nil {
return nil, fmt.Errorf("Failed PEM decryption [%s]", err)
}
key, err := DERToPrivateKey(decrypted)
if err != nil {
return nil, err
}
return key, err
}
cert, err := DERToPrivateKey(block.Bytes)
if err != nil {
return nil, err
}
return cert, err
}
// PEMtoAES extracts from the PEM an AES key
func PEMtoAES(raw []byte, pwd []byte) ([]byte, error) {
if len(raw) == 0 {
return nil, errors.New("Invalid PEM. It must be different from nil.")
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, fmt.Errorf("Failed decoding PEM. Block must be different from nil. [% x]", raw)
}
if x509.IsEncryptedPEMBlock(block) {
if len(pwd) == 0 {
return nil, errors.New("Encrypted Key. Password must be different fom nil")
}
decrypted, err := x509.DecryptPEMBlock(block, pwd)
if err != nil {
return nil, fmt.Errorf("Failed PEM decryption. [%s]", err)
}
return decrypted, nil
}
return block.Bytes, nil
}
// AEStoPEM encapsulates an AES key in the PEM format
func AEStoPEM(raw []byte) []byte {
return pem.EncodeToMemory(&pem.Block{Type: "AES PRIVATE KEY", Bytes: raw})
}
// AEStoEncryptedPEM encapsulates an AES key in the encrypted PEM format
func AEStoEncryptedPEM(raw []byte, pwd []byte) ([]byte, error) {
if len(raw) == 0 {
return nil, errors.New("Invalid aes key. It must be different from nil")
}
if len(pwd) == 0 {
return AEStoPEM(raw), nil
}
block, err := x509.EncryptPEMBlock(
rand.Reader,
"AES PRIVATE KEY",
raw,
pwd,
x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(block), nil
}
// PublicKeyToPEM marshals a public key to the pem format
func PublicKeyToPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
if len(pwd) != 0 {
return PublicKeyToEncryptedPEM(publicKey, pwd)
}
if publicKey == nil {
return nil, errors.New("Invalid public key. It must be different from nil.")
}
switch k := publicKey.(type) {
case *ecdsa.PublicKey:
if k == nil {
return nil, errors.New("Invalid ecdsa public key. It must be different from nil.")
}
PubASN1, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(
&pem.Block{
Type: "PUBLIC KEY",
Bytes: PubASN1,
},
), nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PublicKey")
}
}
// PublicKeyToDER marshals a public key to the der format
func PublicKeyToDER(publicKey interface{}) ([]byte, error) {
if publicKey == nil {
return nil, errors.New("Invalid public key. It must be different from nil.")
}
switch k := publicKey.(type) {
case *ecdsa.PublicKey:
if k == nil {
return nil, errors.New("Invalid ecdsa public key. It must be different from nil.")
}
PubASN1, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
return PubASN1, nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PublicKey")
}
}
// PublicKeyToEncryptedPEM converts a public key to encrypted pem
func PublicKeyToEncryptedPEM(publicKey interface{}, pwd []byte) ([]byte, error) {
if publicKey == nil {
return nil, errors.New("Invalid public key. It must be different from nil.")
}
if len(pwd) == 0 {
return nil, errors.New("Invalid password. It must be different from nil.")
}
switch k := publicKey.(type) {
case *ecdsa.PublicKey:
if k == nil {
return nil, errors.New("Invalid ecdsa public key. It must be different from nil.")
}
raw, err := x509.MarshalPKIXPublicKey(k)
if err != nil {
return nil, err
}
block, err := x509.EncryptPEMBlock(
rand.Reader,
"PUBLIC KEY",
raw,
pwd,
x509.PEMCipherAES256)
if err != nil {
return nil, err
}
return pem.EncodeToMemory(block), nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PublicKey")
}
}
// PEMtoPublicKey unmarshals a pem to public key
func PEMtoPublicKey(raw []byte, pwd []byte) (interface{}, error) {
if len(raw) == 0 {
return nil, errors.New("Invalid PEM. It must be different from nil.")
}
block, _ := pem.Decode(raw)
if block == nil {
return nil, fmt.Errorf("Failed decoding. Block must be different from nil. [% x]", raw)
}
// TODO: derive from header the type of the key
if x509.IsEncryptedPEMBlock(block) {
if len(pwd) == 0 {
return nil, errors.New("Encrypted Key. Password must be different from nil")
}
decrypted, err := x509.DecryptPEMBlock(block, pwd)
if err != nil {
return nil, fmt.Errorf("Failed PEM decryption. [%s]", err)
}
key, err := DERToPublicKey(decrypted)
if err != nil {
return nil, err
}
return key, err
}
cert, err := DERToPublicKey(block.Bytes)
if err != nil {
return nil, err
}
return cert, err
}
// DERToPublicKey unmarshals a der to public key
func DERToPublicKey(raw []byte) (pub interface{}, err error) {
if len(raw) == 0 {
return nil, errors.New("Invalid DER. It must be different from nil.")
}
key, err := x509.ParsePKIXPublicKey(raw)
return key, err
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/liurenhao/fabric.git
git@gitee.com:liurenhao/fabric.git
liurenhao
fabric
fabric
v2.0.1

搜索帮助

344bd9b3 5694891 D2dac590 5694891