Skip to content

Commit

Permalink
ecc add method
Browse files Browse the repository at this point in the history
  • Loading branch information
AbericYang committed Sep 21, 2019
1 parent f51be2f commit f476fba
Show file tree
Hide file tree
Showing 3 changed files with 544 additions and 44 deletions.
240 changes: 233 additions & 7 deletions ecc.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,21 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"crypto/x509"
"encoding/hex"
"encoding/pem"
"errors"
"github.com/ethereum/go-ethereum/crypto/ecies"
"io/ioutil"
"math/big"
"os"
"path/filepath"
"strings"
)

const (
privateECCKeyPemType = "ECC PRIVATE KEY"
publicECCKeyPemType = "PUBLIC KEY"
)

// ECCCommon ECC椭圆加密工具,依赖ETH的包
Expand All @@ -39,36 +47,151 @@ import (
// ECDH在ECC和DH的基础上实现的密钥交换算法
type ECCCommon struct{}

// Generate 生成公私钥对
//
// curve 曲线生成类型,如 crypto.S256()/elliptic.P256()/elliptic.P384()/elliptic.P512()
func (e *ECCCommon) Generate(curve elliptic.Curve) (*ecdsa.PrivateKey, *ecdsa.PublicKey, error) {
var (
privateKey *ecdsa.PrivateKey
err error
)
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, nil, err
}
return privateKey, &privateKey.PublicKey, nil
}

// GenerateKey 生成公私钥对
//
// path 指定公私钥所在生成目录
//
// curve 曲线生成类型,如 crypto.S256()/elliptic.P256()/elliptic.P384()/elliptic.P512()
func (e *ECCCommon) GenerateKey(path, priFileName, pubFileName string, curve elliptic.Curve) (*ecies.PrivateKey, *ecies.PublicKey, error) {
func (e *ECCCommon) GenerateKey(path, priFileName, pubFileName string, curve elliptic.Curve) error {
var (
privateKey *ecdsa.PrivateKey
err error
)
// 创建公私钥生成目录
if !File().PathExists(path) {
if err = os.MkdirAll(path, os.ModePerm); nil != err {
return nil, nil, err
return err
}
}
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return nil, nil, err
return err
}

if err = e.SavePri(filepath.Join(path, priFileName), privateKey); nil != err {
return nil, nil, err
return err
}
if err = e.SavePub(filepath.Join(path, pubFileName), &privateKey.PublicKey, curve); nil != err {
return nil, nil, err
return err
}
return nil
}

pri := ecies.ImportECDSA(privateKey)
return pri, &pri.PublicKey, nil
// GeneratePemKey 生成公私钥对
//
// path 指定公私钥所在生成目录
//
// curve 曲线生成类型,如 crypto.S256()/elliptic.P256()/elliptic.P384()/elliptic.P512()
func (e *ECCCommon) GeneratePemKey(path, priFileName, pubFileName string, curve elliptic.Curve) error {
var (
privateKey *ecdsa.PrivateKey
err error
)
// 创建公私钥生成目录
if !File().PathExists(path) {
if err = os.MkdirAll(path, os.ModePerm); nil != err {
return err
}
}
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return err
}

if err = e.SavePriPem(filepath.Join(path, priFileName), privateKey); nil != err {
return err
}
if err = e.SavePubPem(filepath.Join(path, pubFileName), &privateKey.PublicKey); nil != err {
return err
}
return nil
}

// GeneratePriKey 生成私钥
//
// path 指定私钥所在生成目录
//
// curve 曲线生成类型,如 crypto.S256()/elliptic.P256()/elliptic.P384()/elliptic.P512()
func (e *ECCCommon) GeneratePriKey(path, priFileName string, curve elliptic.Curve) error {
var (
privateKey *ecdsa.PrivateKey
err error
)
// 创建公私钥生成目录
if !File().PathExists(path) {
if err = os.MkdirAll(path, os.ModePerm); nil != err {
return err
}
}
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return err
}
if err = e.SavePri(filepath.Join(path, priFileName), privateKey); nil != err {
return err
}
return nil
}

// GeneratePemPriKey 生成私钥
//
// path 指定私钥所在生成目录
//
// curve 曲线生成类型,如 crypto.S256()/elliptic.P256()/elliptic.P384()/elliptic.P512()
func (e *ECCCommon) GeneratePemPriKey(path, priFileName string, curve elliptic.Curve) error {
var (
privateKey *ecdsa.PrivateKey
err error
)
// 创建公私钥生成目录
if !File().PathExists(path) {
if err = os.MkdirAll(path, os.ModePerm); nil != err {
return err
}
}
privateKey, err = ecdsa.GenerateKey(curve, rand.Reader)
if err != nil {
return err
}
if err = e.SavePriPem(filepath.Join(path, priFileName), privateKey); nil != err {
return err
}
return nil
}

// GeneratePubKey 生成公钥
//
// path 指定公钥所在生成目录
func (e *ECCCommon) GeneratePubKey(privateKey *ecdsa.PrivateKey, path, pubFileName string, curve elliptic.Curve) error {
if err := e.SavePub(filepath.Join(path, pubFileName), &privateKey.PublicKey, curve); nil != err {
return err
}
return nil
}

// GeneratePemPubKey 生成公钥
//
// path 指定公钥所在生成目录
func (e *ECCCommon) GeneratePemPubKey(privateKey *ecdsa.PrivateKey, path, pubFileName string) error {
if err := e.SavePubPem(filepath.Join(path, pubFileName), &privateKey.PublicKey); nil != err {
return err
}
return nil
}

// SavePri 将私钥保存到给定文件,密钥数据保存为hex编码
Expand All @@ -94,6 +217,97 @@ func (e *ECCCommon) LoadPri(file string, curve elliptic.Curve) (*ecdsa.PrivateKe
//return crypto.LoadECDSA(file)
}

// SavePriPem 将私钥保存到给定文件
func (e *ECCCommon) SavePriPem(file string, privateKey *ecdsa.PrivateKey) error {
var fileIO *os.File
// 将私钥转换为ASN.1 DER编码的形式
derStream, err := x509.MarshalECPrivateKey(privateKey)
if nil != err {
return err
}
// block表示PEM编码的结构
block := &pem.Block{
Type: privateECCKeyPemType,
Bytes: derStream,
}
defer func() { _ = fileIO.Close() }()
if fileIO, err = os.OpenFile(file, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600); nil != err {
return err
}
// 将block的PEM编码写入fileIO
if err = pem.Encode(fileIO, block); nil != err {
return err
}
return nil
}

// LoadPriPem 从文件中加载私钥
//
// file 文件路径
func (e *ECCCommon) LoadPriPem(file string) (*ecdsa.PrivateKey, error) {
keyData, err := ioutil.ReadFile(file)
if nil != err {
return nil, err
}
pemData, err := e.pemParse(keyData, privateECCKeyPemType)
if err != nil {
return nil, err
}
pri, err := x509.ParseECPrivateKey(pemData)
if nil != err {
return nil, err
}
return pri, nil
}

// SavePubPem 将公钥保存到给定文件
//
// file 文件路径
func (e *ECCCommon) SavePubPem(file string, publicKey *ecdsa.PublicKey) error {
var fileIO *os.File
// 将公钥序列化为der编码的PKIX格式
derPkiX, err := x509.MarshalPKIXPublicKey(publicKey)
if nil != err {
return err
}
block := &pem.Block{
Type: publicECCKeyPemType,
Bytes: derPkiX,
}
defer func() { _ = fileIO.Close() }()
if fileIO, err = os.Create(file); nil != err {
return err
}
// 将block的PEM编码写入fileIO
if err = pem.Encode(fileIO, block); nil != err {
return err
}
return nil
}

// LoadPubPem 从文件中加载公钥
//
// file 文件路径
func (e *ECCCommon) LoadPubPem(file string) (*ecdsa.PublicKey, error) {
pubData, err := ioutil.ReadFile(file)
if nil != err {
return nil, err
}
pemData, err := e.pemParse(pubData, publicECCKeyPemType)
if err != nil {
return nil, err
}
keyInterface, err := x509.ParsePKIXPublicKey(pemData)
if err != nil {
return nil, err
}
pubKey, ok := keyInterface.(*ecdsa.PublicKey)
if !ok {
return nil, errors.New("could not cast parsed key to *rsa.PublicKey")
}
return pubKey, nil
}

// SavePub 将公钥保存到给定文件,密钥数据保存为hex编码
//
// file 文件路径
Expand Down Expand Up @@ -230,3 +444,15 @@ func (e *ECCCommon) Verify(publicKey *ecdsa.PublicKey, data, sign []byte) (bool,
v := ecdsa.Verify(publicKey, data, &rint, &sint)
return v, nil
}

// pemParse 解密pem格式密钥并验证pem类型
func (e *ECCCommon) pemParse(key []byte, pemType string) ([]byte, error) {
block, _ := pem.Decode(key)
if block == nil {
return nil, errors.New("no pem block found")
}
if pemType != "" && block.Type != pemType {
return nil, errors.New(strings.Join([]string{"Key's type is ", block.Type, ", expected ", pemType}, ""))
}
return block.Bytes, nil
}
Loading

0 comments on commit f476fba

Please sign in to comment.