Commit 09366cfa authored by pengjun's avatar pengjun Committed by vipwzw

#955 证书工具添加中间证书的生成

parent 5b40dfaa
......@@ -47,4 +47,5 @@ require (
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect
google.golang.org/grpc v1.29.1
gopkg.in/yaml.v2 v2.2.4
)
......@@ -25,9 +25,6 @@ var (
alog = log.New("module", "authority")
cpuNum = runtime.NumCPU()
// OrgName 默认证书组织名
OrgName = "Chain33"
// Author 全局证书校验器
Author = &Authority{}
......@@ -369,12 +366,12 @@ func (loader *UserLoader) genCryptoPriv(keyBytes []byte) (crypto.PrivKey, error)
if err != nil {
return nil, fmt.Errorf("create crypto %s failed, error:%s", types.GetSignName("cert", loader.signType), err)
}
privKeyByte, err := utils.PrivKeyByteFromRaw(keyBytes, loader.signType)
if err != nil {
return nil, err
}
//privKeyByte, err := utils.PrivKeyByteFromRaw(keyBytes, loader.signType)
//if err != nil {
// return nil, err
//}
priv, err := cr.PrivKeyFromBytes(privKeyByte)
priv, err := cr.PrivKeyFromBytes(keyBytes)
if err != nil {
return nil, fmt.Errorf("get private key failed, error:%s", err)
}
......@@ -383,8 +380,8 @@ func (loader *UserLoader) genCryptoPriv(keyBytes []byte) (crypto.PrivKey, error)
}
// Get 根据用户名获取user结构
func (loader *UserLoader) Get(userName string) (*User, error) {
keyvalue := fmt.Sprintf("%s@%s-cert.pem", userName, OrgName)
func (loader *UserLoader) Get(userName, orgName string) (*User, error) {
keyvalue := fmt.Sprintf("%s@%s-cert.pem", userName, orgName)
user, ok := loader.userMap[keyvalue]
if !ok {
return nil, types.ErrInvalidParam
......
......@@ -54,7 +54,8 @@ var (
}
)
var USERNAME = "User"
var USERNAME = "user1"
var ORGNAME = "org1"
var SIGNTYPE = ct.AuthSM2
func signtx(tx *types.Transaction, priv crypto.PrivKey, cert []byte) {
......@@ -98,7 +99,7 @@ func initEnv() (*types.Chain33Config, error) {
return nil, err
}
user, err := userLoader.Get(USERNAME)
user, err := userLoader.Get(USERNAME, ORGNAME)
if err != nil {
fmt.Printf("Get user failed")
return nil, err
......@@ -124,10 +125,7 @@ func TestChckSign(t *testing.T) {
}
cfg.SetMinFee(0)
if !tx1.CheckSign() {
t.Error("check signature failed")
return
}
assert.Equal(t, true, tx1.CheckSign())
}
/**
......
-----BEGIN CERTIFICATE-----
MIIB7DCCAZGgAwIBAgIQETH0EMzvdWOEEg3FoAe/iDAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NTIwWjBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzELMAkGA1UEAxMCY2EwWTATBgcqhkjOPQIBBggqgRzP
VQGCLQNCAAQlKmH6RVHN/nBE4qR+uF7lHmlc62jQA4kpoAwtJFRiFbczZx/KNDaD
9+USLAo9ecxcdOKR4lIcuT7jvKX6tXQ7o18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYD
VR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTADAQH/MCkGA1UdDgQiBCC8fKlLiayf
+80blLEiRIzTyY7uYDUpP5K2RtOmfY0NKjAKBggqgRzPVQGDdQNJADBGAiEA8vh+
3joELxPxq0n1h07XFGeEnmpxutVoIocuky2HkF4CIQDnWIavlpJOq3tU76cmn3ur
KQeyi9GM7Uoi25S1QIxu9A==
MIIB8jCCAZigAwIBAgIRANAVs0iZuoUGkmEpb9KbDHgwCgYIKoEcz1UBg3UwSjEO
MAwGA1UEBhMFQ2hpbmExETAPBgNVBAgTCFpoZWppYW5nMREwDwYDVQQHEwhIYW5n
emhvdTESMBAGA1UEAxMJQ2hhaW4zM0NBMB4XDTIxMDIwNTA5NTAyOFoXDTIxMDUx
NjA5NTAyOFowSjEOMAwGA1UEBhMFQ2hpbmExETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEAxMJQ2hhaW4zM0NBMFkwEwYHKoZIzj0C
AQYIKoEcz1UBgi0DQgAEu+f1TgnsUOKPmI6f9V2iTTMm0SoJuPXV/oG88jwVUh9e
viiugGXJ+WSL58KceRmZT5zTvzJ5OzjsfxJFb9G4PqNfMF0wDgYDVR0PAQH/BAQD
AgGmMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQg
ocyVo2jZzw/MNHGLXlWoWTweHuDfGQ9YduMQvhC7qlUwCgYIKoEcz1UBg3UDSAAw
RQIhAIAOBIKqOK5R0lt/h9G/SlgzGSazEOStJ6Q1hGuhEctAAiBGVtGHlOwV0L8g
6pMvlk46rpq3BNHFQiW1MeALRb+qqg==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB8TCCAZigAwIBAgIRANBfNdKA1MB2NGdS6W6HLZAwCgYIKoEcz1UBg3UwSjEO
MAwGA1UEBhMFQ2hpbmExETAPBgNVBAgTCFpoZWppYW5nMREwDwYDVQQHEwhIYW5n
emhvdTESMBAGA1UEAxMJQ2hhaW4zM0NBMB4XDTIxMDIwNTA5NTAyOFoXDTIxMDUx
NjA5NTAyOFowSjEOMAwGA1UEBhMFQ2hpbmExETAPBgNVBAgTCFpoZWppYW5nMREw
DwYDVQQHEwhIYW5nemhvdTESMBAGA1UEAxMJQ2hhaW4zM0NBMFkwEwYHKoZIzj0C
AQYIKoEcz1UBgi0DQgAEE7meX04w0TkLMxVhKDIHNosXUp0Ko1XOXd8rm+SaMSjQ
dFyAO98YZcR+pVjzT2hs/8JHm8UtEt5MSsNA80pG7KNfMF0wDgYDVR0PAQH/BAQD
AgGmMA8GA1UdJQQIMAYGBFUdJQAwDwYDVR0TAQH/BAUwAwEB/zApBgNVHQ4EIgQg
k+DGCc4DXJrEhGEK0K2DhBRiNsJX1VNqCQdp1dplx5QwCgYIKoEcz1UBg3UDRwAw
RAIgRTG6r1EPLmvaX8VKKDDIIUthYKWY4gao4e2QBYvTFGcCICcxdwnDdDTwo8N+
KKWn1mulB/+1uVFa8ur8K7C2juJA
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg4Ork9oT6d6CRxg0f
EbHlr5eQPUcHWniEgRhDCi2dA/GgCgYIKoEcz1UBgi2hRANCAAQqXuEWh+sW/YtP
FlHmxiFhYi0o3Tb8He9NAaJ6uKe+OF5/eXa+VmRrKKGeE+dG8LrMiJ5+AlIj+ryd
blX5UKZ8
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIB4zCCAYmgAwIBAgIQVs0txvOG+iVu/oISaV2KyzAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NTIwWjBRMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEAwwMVXNlckBDaGFpbjMzMFkwEwYHKoZI
zj0CAQYIKoEcz1UBgi0DQgAEKl7hFofrFv2LTxZR5sYhYWItKN02/B3vTQGierin
vjhef3l2vlZkayihnhPnRvC6zIiefgJSI/q8nW5V+VCmfKNNMEswDgYDVR0PAQH/
BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgvHypS4msn/vNG5SxIkSM
08mO7mA1KT+StkbTpn2NDSowCgYIKoEcz1UBg3UDSAAwRQIhAND6HO/EN/dTeokX
mIvczQBcxPHTAq3+QIa2NHIC8bYvAiAZ5N4C4rwRJCqTw8J6As69MFO10XixWHxH
qrTJ9LnI3g==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIB2zCCAYKgAwIBAgIQBfpCKYMGwcsdTSfiRMUEvjAKBggqgRzPVQGDdTBKMQ4w
DAYDVQQGEwVDaGluYTERMA8GA1UECBMIWmhlamlhbmcxETAPBgNVBAcTCEhhbmd6
aG91MRIwEAYDVQQDEwlDaGFpbjMzQ0EwHhcNMjEwMjA1MDk1MDI4WhcNMjEwNTE2
MDk1MDI4WjBHMQ4wDAYDVQQGEwVDaGluYTERMA8GA1UECBMIWmhlamlhbmcxETAP
BgNVBAcTCEhhbmd6aG91MQ8wDQYDVQQDEwZvcmcxQ0EwWTATBgcqhkjOPQIBBggq
gRzPVQGCLQNCAAQ89ud/ijDdF+TTxMGOLhhFy7qpEF/ALFaXmrDB0kZ4xJSzcMVz
BHLJK+TQPfUYkIvDJGIWCQcozKHT+UbzvAtjo00wSzAOBgNVHQ8BAf8EBAMCB4Aw
DAYDVR0TAQH/BAIwADArBgNVHSMEJDAigCCT4MYJzgNcmsSEYQrQrYOEFGI2wlfV
U2oJB2nV2mXHlDAKBggqgRzPVQGDdQNHADBEAiBKKc5DPV2F73fwe8oZqiIOc9U8
xX+jMZPCOqMzFxZ/UwIgRARNhW60dHNse7zYvC49gIMsDfVxbHYfNxiRzsl6168=
-----END CERTIFICATE-----
## 用户名,可配置多用户
name = ["User"]
## 签名类型,支持"auth_ecdsa", "auth_sm2"
signType = "auth_sm2"
\ No newline at end of file
SignType: auth_sm2
Root:
Name: ca
CA:
CommonName: Chain33CA
Country: China
Province: Zhejiang
Locality: Hangzhou
Expire: 100
User:
- Name: org1
- Name: org2
Organizations:
- Name: org1
CA:
CommonName: org1CA
Country: China
Province: Zhejiang
Locality: Hangzhou
Expire: 100
User:
- Name: user1
- Name: user2
- Name: org2
CA:
CommonName: org2CA
Country: China
Province: Zhejiang
Locality: Hangzhou
Expire: 100
User:
- Name: user1
- Name: user2
\ No newline at end of file
......@@ -6,49 +6,43 @@ package main
import (
"fmt"
log "github.com/33cn/chain33/common/log/log15"
"gopkg.in/yaml.v2"
"os"
"path/filepath"
"github.com/33cn/chain33/types"
_ "github.com/33cn/plugin/plugin/crypto/init"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/generator"
ca "github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/generator/impl"
"github.com/BurntSushi/toml"
"github.com/spf13/cobra"
)
const (
// CANAME 默认CA名称
CANAME = "ca"
// CONFIGFILENAME 配置文件名
CONFIGFILENAME = "chain33.cryptogen.toml"
CONFIGFILENAME = "chain33.cryptogen.yaml"
// OUTPUTDIR 证书文件输出路径
OUTPUTDIR = "./authdir/crypto"
// ORGNAME 默认组织名
ORGNAME = "Chain33"
)
// Config 证书生成工具配置
type Config struct {
Name []string
SignType string
}
var (
cmd = &cobra.Command{
Use: "cryptogen [-f configfile] [-o output directory]",
Short: "chain33 crypto tool for generating key and certificate",
Run: generate,
}
cfg Config
cfg *generator.GenConfig
logger = log.New("module", "main")
)
func initCfg(path string) *Config {
if _, err := toml.DecodeFile(path, &cfg); err != nil {
fmt.Println(err)
os.Exit(0)
func initCfg(path string) (*generator.GenConfig, error) {
conf := &generator.GenConfig{}
f, err := os.Open(path)
if err != nil {
return nil, err
}
return &cfg
yaml.NewDecoder(f).Decode(conf)
return conf, nil
}
func main() {
......@@ -65,19 +59,22 @@ func generate(cmd *cobra.Command, args []string) {
configfile, _ := cmd.Flags().GetString("configfile")
outputdir, _ := cmd.Flags().GetString("outputdir")
initCfg(configfile)
fmt.Println(cfg.Name)
var err error
cfg, err = initCfg(configfile)
if err != nil {
panic(err)
}
generateCert(outputdir)
generateUsers(outputdir, ORGNAME)
}
func generateUsers(baseDir string, orgName string) {
fmt.Printf("generateUsers\n")
fmt.Println(baseDir)
func generateCert(baseDir string) {
logger.Info("generate certs", "dir", baseDir)
err := os.RemoveAll(baseDir)
if err != nil {
fmt.Printf("Clean directory %s error", baseDir)
logger.Error("clean directory", "error", err.Error())
os.Exit(1)
}
......@@ -85,26 +82,37 @@ func generateUsers(baseDir string, orgName string) {
signType := types.GetSignType("cert", cfg.SignType)
if signType == types.Invalid {
fmt.Printf("Invalid sign type:%s", cfg.SignType)
logger.Error("invalid sign type", "type", cfg.SignType)
return
}
signCA, err := ca.NewCA(caDir, CANAME, signType)
signCA, err := generator.NewCA(caDir, &cfg.Root, signType)
if err != nil {
fmt.Printf("Error generating signCA:%s", err.Error())
logger.Error("generating signCA", "error", err.Error())
os.Exit(1)
}
generateNodes(baseDir, signCA, orgName)
for _, org := range cfg.Root.User {
generateOrgs(baseDir, signCA, cfg.GetOrgCertConfig(org.Name))
}
}
func generateNodes(baseDir string, signCA generator.CAGenerator, orgName string) {
for _, name := range cfg.Name {
userDir := filepath.Join(baseDir, name)
fileName := fmt.Sprintf("%s@%s", name, orgName)
err := signCA.GenerateLocalUser(userDir, fileName)
func generateOrgs(baseDir string, signCA generator.CAGenerator, orgCfg *generator.CertConfig) {
orgDir := filepath.Join(baseDir, orgCfg.Name)
fileName := fmt.Sprintf("%s@%s", orgCfg.Name, cfg.Root.Name)
orgSignCA, err := signCA.GenerateLocalOrg(orgDir, fileName, orgCfg)
if err != nil {
logger.Error("generating local org", "org", orgCfg.Name, "error", err.Error())
os.Exit(1)
}
for _, user := range orgCfg.User {
userDir := filepath.Join(orgDir, user.Name)
fileName = fmt.Sprintf("%s@%s", user.Name, orgCfg.Name)
err := orgSignCA.GenerateLocalUser(userDir, fileName)
if err != nil {
fmt.Printf("Error generating local user")
logger.Error("generating local user", "user", user.Name, "error", err.Error())
os.Exit(1)
}
}
......
......@@ -20,7 +20,7 @@ import (
auth "github.com/33cn/plugin/plugin/dapp/cert/authority/utils"
)
var logger = log.New("tools", "cryptogen")
var logger = log.New("module", "tools")
// NewFileBasedKeyStore 创建key存储器
func NewFileBasedKeyStore(pwd []byte, path string, readOnly bool) (KeyStore, error) {
......@@ -65,6 +65,7 @@ func (ks *fileBasedKeyStore) Init(pwd []byte, path string, readOnly bool) error
}
ks.readOnly = readOnly
logger.Info("generate keystore file", "path", path)
return nil
}
......@@ -85,7 +86,7 @@ func (ks *fileBasedKeyStore) StoreKey(k Key) (err error) {
case *ecdsaPrivateKey:
kk := k.(*ecdsaPrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.privKey)
err = ks.storePrivateKeyByte(hex.EncodeToString(k.SKI()), kk.privKey)
if err != nil {
return fmt.Errorf("Failed storing ECDSA private key [%s]", err)
}
......@@ -100,7 +101,7 @@ func (ks *fileBasedKeyStore) StoreKey(k Key) (err error) {
case *SM2PrivateKey:
kk := k.(*SM2PrivateKey)
err = ks.storePrivateKey(hex.EncodeToString(k.SKI()), kk.PrivKey)
err = ks.storePrivateKeyByte(hex.EncodeToString(k.SKI()), kk.PrivKey)
if err != nil {
return fmt.Errorf("Failed storing SM2 private key [%s]", err)
}
......@@ -119,16 +120,32 @@ func (ks *fileBasedKeyStore) StoreKey(k Key) (err error) {
return
}
func (ks *fileBasedKeyStore) storePrivateKeyByte(alias string, privateKey interface{}) error {
rawKey, err := utils.PrivateKeyToByte(privateKey)
if err != nil {
logger.Error("Failed converting private key to PEM","name", alias, "error", err)
return err
}
err = ioutil.WriteFile(ks.getPathForAlias(alias, "sk"), rawKey, 0700)
if err != nil {
logger.Error("Failed storing private key", "name", alias, "error", err)
return err
}
return nil
}
func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{}) error {
rawKey, err := utils.PrivateKeyToPEM(privateKey, ks.pwd)
if err != nil {
logger.Error("Failed converting private key to PEM [%s]: [%s]", alias, err)
logger.Error("Failed converting private key to PEM", "name", alias, "error", err)
return err
}
err = ioutil.WriteFile(ks.getPathForAlias(alias, "sk"), rawKey, 0700)
if err != nil {
logger.Error("Failed storing private key [%s]: [%s]", alias, err)
logger.Error("Failed storing private key", "name", alias, "error", err)
return err
}
......@@ -138,13 +155,13 @@ func (ks *fileBasedKeyStore) storePrivateKey(alias string, privateKey interface{
func (ks *fileBasedKeyStore) storePublicKey(alias string, publicKey interface{}) error {
rawKey, err := utils.PublicKeyToPEM(publicKey, ks.pwd)
if err != nil {
logger.Error("Failed converting public key to PEM [%s]: [%s]", alias, err)
logger.Error("Failed converting public key to PEM", "name", alias, "error", err)
return err
}
err = ioutil.WriteFile(ks.getPathForAlias(alias, "pk"), rawKey, 0700)
if err != nil {
logger.Error("Failed storing private key [%s]: [%s]", alias, err)
logger.Error("Failed storing public key", "name", alias, "error", err)
return err
}
......@@ -157,7 +174,7 @@ func (ks *fileBasedKeyStore) createKeyStoreIfNotExists() error {
if missing {
err := ks.createKeyStore()
if err != nil {
logger.Error("Failed creating KeyStore At [%s]: [%s]", ksPath, err.Error())
logger.Error("Failed creating KeyStore At", "path", ksPath, "error", err.Error())
return err
}
}
......
......@@ -41,10 +41,17 @@ type sm2KeyGenerator struct {
}
func (kg *sm2KeyGenerator) KeyGen(opts int) (k Key, err error) {
privKey, err := sm2.GenerateKey()
if err != nil {
return nil, fmt.Errorf("Failed generating SM2 key for: [%s]", err)
ln := big.NewInt(0).Rsh(sm2.P256Sm2().Params().N, 1)
for {
privKey, err := sm2.GenerateKey()
if err != nil {
return nil, fmt.Errorf("Failed generating SM2 key for: [%s]", err)
}
if ln.Cmp(privKey.D) == 1 {
//fmt.Println("priv:"+common.ToHex(privKey.D.Bytes()))
return &SM2PrivateKey{privKey}, nil
}
}
return &SM2PrivateKey{privKey}, nil
}
......@@ -12,7 +12,9 @@ import (
"encoding/asn1"
"encoding/pem"
"fmt"
pkecdsa "github.com/33cn/plugin/plugin/crypto/ecdsa"
pkesm2 "github.com/33cn/plugin/plugin/crypto/sm2"
"github.com/33cn/plugin/plugin/dapp/evm/executor/vm/common"
"github.com/pkg/errors"
"github.com/tjfoc/gmsm/sm2"
)
......@@ -44,6 +46,21 @@ func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
return nil, false
}
func PrivateKeyToByte(privateKey interface{}) ([]byte, error) {
if privateKey == nil {
return nil, errors.New("Invalid key. It must be different from nil")
}
switch k := privateKey.(type) {
case *ecdsa.PrivateKey:
return []byte(common.Bytes2Hex(pkecdsa.SerializePrivateKey(k))), nil
case *sm2.PrivateKey:
return []byte(common.Bytes2Hex(pkesm2.SerializePrivateKey(k))), nil
default:
return nil, errors.New("Invalid key type. It must be *ecdsa.PrivateKey or *rsa.PrivateKey")
}
}
// PrivateKeyToPEM 私钥转pem
func PrivateKeyToPEM(privateKey interface{}, pwd []byte) ([]byte, error) {
if len(pwd) != 0 {
......
package generator
type UserConfig struct {
Name string `yaml:"Name"`
}
type CAConfig struct {
CommonName string `yaml:"CommonName"`
Country string `yaml:"Country"`
Province string `yaml:"Province"`
Locality string `yaml:"Locality"`
Expire int `yaml:"Expire"`
}
type CertConfig struct {
Name string `yaml:"Name"`
CA CAConfig `yaml:"CA"`
User []UserConfig `yaml:"User"`
}
type GenConfig struct {
SignType string `yaml:"SignType"`
Root CertConfig `yaml:"Root"`
Organizations []CertConfig `yaml:"Organizations"`
}
func (cfg *GenConfig) GetOrgCertConfig(orgName string) *CertConfig {
for _, certCfg := range cfg.Organizations {
if certCfg.Name == orgName {
return &certCfg
}
}
return nil
}
......@@ -8,7 +8,9 @@ import "crypto/x509"
// CAGenerator CA生成器接口
type CAGenerator interface {
SignCertificate(baseDir, name string, sans []string, pub interface{}) (*x509.Certificate, error)
SignCertificate(baseDir, fileName string, sans []string, pub interface{}, isCA bool) (*x509.Certificate, error)
GenerateLocalUser(baseDir, name string) error
GenerateLocalOrg(baseDir, fileName string, orgCfg *CertConfig) (CAGenerator, error)
GenerateLocalUser(baseDir, fileName string) error
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package generator
import (
"crypto"
"crypto/ecdsa"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"os"
"time"
"path/filepath"
"fmt"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/factory/csp"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/generator/utils"
ut "github.com/33cn/plugin/plugin/dapp/cert/authority/utils"
ty "github.com/33cn/plugin/plugin/dapp/cert/types"
"github.com/tjfoc/gmsm/sm2"
)
// EcdsaCA ecdsa CA结构
type EcdsaCA struct {
Name string
Signer crypto.Signer
SignCert *x509.Certificate
CertConfig *CertConfig
}
// SM2CA SM2 CA结构
type SM2CA struct {
Name string
Signer crypto.Signer
SignCert *sm2.Certificate
Sm2Key csp.Key
CertConfig *CertConfig
}
// NewCA 根据类型生成CA生成器
func NewCA(baseDir string, cacfg *CertConfig, signType int) (CAGenerator, error) {
if signType == ty.AuthECDSA {
return newEcdsaCA(baseDir, cacfg)
} else if signType == ty.AuthSM2 {
return newSM2CA(baseDir, cacfg)
} else {
return nil, fmt.Errorf("Invalid sign type")
}
}
func newEcdsaCA(baseDir string, certConfig *CertConfig) (*EcdsaCA, error) {
err := os.MkdirAll(baseDir, 0750)
if err != nil {
return nil, err
}
var ca *EcdsaCA
priv, signer, err := utils.GeneratePrivateKey(baseDir, csp.ECDSAP256KeyGen)
if err != nil {
return nil, err
}
ecPubKey, err := utils.GetECPublicKey(priv)
if err != nil {
return nil, err
}
template := x509Template(certConfig.CA.Expire)
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
subject := pkix.Name{
Country: []string{certConfig.CA.Country},
Locality: []string{certConfig.CA.Locality},
Province: []string{certConfig.CA.Province},
}
subject.CommonName = certConfig.CA.CommonName
template.Subject = subject
template.SubjectKeyId = priv.SKI()
template.PublicKey = ecPubKey
x509Cert, err := genCertificateECDSA(baseDir, certConfig.Name, &template, &template, signer)
if err != nil {
return nil, err
}
ca = &EcdsaCA{
Name: certConfig.Name,
Signer: signer,
SignCert: x509Cert,
CertConfig: certConfig,
}
return ca, nil
}
// SignCertificate 证书签名
func (ca *EcdsaCA) SignCertificate(baseDir, fileName string, sans []string, pub interface{}, isCA bool) (*x509.Certificate, error) {
template := x509Template(ca.CertConfig.CA.Expire)
if isCA {
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
template.SubjectKeyId = ut.SKI(pub.(*ecdsa.PublicKey).Curve, pub.(*ecdsa.PublicKey).X, pub.(*ecdsa.PublicKey).Y)
} else {
template.KeyUsage = x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{}
}
subject := pkix.Name{
Country: []string{ca.CertConfig.CA.Country},
Locality: []string{ca.CertConfig.CA.Locality},
Province: []string{ca.CertConfig.CA.Province},
}
subject.CommonName = ca.CertConfig.CA.CommonName
template.Subject = subject
template.DNSNames = sans
template.PublicKey = pub
cert, err := genCertificateECDSA(baseDir, fileName, &template, ca.SignCert, ca.Signer)
if err != nil {
return nil, err
}
return cert, nil
}
// GenerateLocalOrg 生成组织证书
func (ca *EcdsaCA) GenerateLocalOrg(baseDir, fileName string, orgCfg *CertConfig) (CAGenerator, error) {
err := createFolderStructure(baseDir, true)
if err != nil {
return nil, err
}
keystore := filepath.Join(baseDir, "keystore")
priv, signer, err := utils.GeneratePrivateKey(keystore, csp.ECDSAP256KeyGen)
if err != nil {
return nil, err
}
ecPubKey, err := utils.GetECPublicKey(priv)
if err != nil {
return nil, err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), fileName, []string{}, ecPubKey, true)
if err != nil || cert == nil {
return nil, err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(fileName)), ca.SignCert.Raw)
if err != nil {
return nil, err
}
err = x509Export(filepath.Join(baseDir, "intermediatecerts", x509Filename(orgCfg.Name)), cert.Raw)
if err != nil {
return nil, err
}
orgCA := &EcdsaCA{
Name: ca.Name,
Signer: signer,
SignCert: cert,
CertConfig: orgCfg,
}
return orgCA, nil
}
// GenerateLocalUser 生成本地用户
func (ca *EcdsaCA) GenerateLocalUser(baseDir, fileName string) error {
err := createFolderStructure(baseDir, false)
if err != nil {
return err
}
keystore := filepath.Join(baseDir, "keystore")
priv, _, err := utils.GeneratePrivateKey(keystore, csp.ECDSAP256KeyGen)
if err != nil {
return err
}
ecPubKey, err := utils.GetECPublicKey(priv)
if err != nil {
return err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), fileName, []string{}, ecPubKey, false)
if err != nil || cert == nil {
return err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(ca.Name)), ca.SignCert.Raw)
return err
}
func x509Template(expire int) x509.Certificate {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
expiry := time.Duration(expire) * 24 * time.Hour
notBefore := time.Now().Add(-5 * time.Minute).UTC()
x509 := x509.Certificate{
SerialNumber: serialNumber,
NotBefore: notBefore,
NotAfter: notBefore.Add(expiry).UTC(),
BasicConstraintsValid: true,
}
return x509
}
func genCertificateECDSA(baseDir, fileName string, template, parent *x509.Certificate, priv interface{}) (*x509.Certificate, error) {
certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, template.PublicKey, priv)
if err != nil {
return nil, err
}
fullName := filepath.Join(baseDir, fileName+"-cert.pem")
certFile, err := os.Create(fullName)
if err != nil {
return nil, err
}
defer certFile.Close()
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
if err != nil {
return nil, err
}
x509Cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
return x509Cert, nil
}
func newSM2CA(baseDir string, certConfig *CertConfig) (*SM2CA, error) {
var ca *SM2CA
priv, signer, err := utils.GeneratePrivateKey(baseDir, csp.SM2P256KygGen)
if err != nil {
return nil, err
}
smPubKey, err := utils.GetSM2PublicKey(priv)
if err != nil {
return nil, err
}
template := x509Template(certConfig.CA.Expire)
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
subject := pkix.Name{
Country: []string{certConfig.CA.Country},
Locality: []string{certConfig.CA.Locality},
Province: []string{certConfig.CA.Province},
}
subject.CommonName = certConfig.CA.CommonName
template.Subject = subject
template.SubjectKeyId = priv.SKI()
sm2cert := utils.ParseX509CertificateToSm2(&template)
sm2cert.PublicKey = smPubKey
x509Cert, err := genCertificateGMSM2(baseDir, certConfig.Name, sm2cert, sm2cert, signer)
if err != nil {
return nil, err
}
ca = &SM2CA{
Name: certConfig.Name,
Signer: signer,
SignCert: x509Cert,
Sm2Key: priv,
CertConfig: certConfig,
}
return ca, nil
}
// SignCertificate 证书签名
func (ca *SM2CA) SignCertificate(baseDir, fileName string, sans []string, pub interface{}, isCA bool) (*x509.Certificate, error) {
template := x509Template(ca.CertConfig.CA.Expire)
if isCA {
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
template.SubjectKeyId = ut.SKI(pub.(*sm2.PublicKey).Curve, pub.(*sm2.PublicKey).X, pub.(*sm2.PublicKey).Y)
} else {
template.KeyUsage = x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{}
}
subject := pkix.Name{
Country: []string{ca.CertConfig.CA.Country},
Locality: []string{ca.CertConfig.CA.Locality},
Province: []string{ca.CertConfig.CA.Province},
}
subject.CommonName = ca.CertConfig.CA.CommonName
template.Subject = subject
template.DNSNames = sans
template.PublicKey = pub
sm2Tpl := utils.ParseX509CertificateToSm2(&template)
cert, err := genCertificateGMSM2(baseDir, fileName, sm2Tpl, ca.SignCert, ca.Signer)
if err != nil {
return nil, err
}
return utils.ParseSm2CertificateToX509(cert), nil
}
// GenerateLocalOrg 生成组织证书
func (ca *SM2CA) GenerateLocalOrg(baseDir, fileName string, orgCfg *CertConfig) (CAGenerator, error) {
err := createFolderStructure(baseDir, true)
if err != nil {
return nil, err
}
keystore := filepath.Join(baseDir, "keystore")
priv, signer, err := utils.GeneratePrivateKey(keystore, csp.SM2P256KygGen)
if err != nil {
return nil, err
}
sm2PubKey, err := utils.GetSM2PublicKey(priv)
if err != nil {
return nil, err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), fileName, []string{}, sm2PubKey, true)
if err != nil || cert == nil {
return nil, err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(ca.Name)), ca.SignCert.Raw)
if err != nil {
return nil, err
}
err = x509Export(filepath.Join(baseDir, "intermediatecerts", x509Filename(orgCfg.Name)), cert.Raw)
if err != nil {
return nil, err
}
orgCA := &SM2CA{
Name: orgCfg.Name,
Signer: signer,
SignCert: utils.ParseX509CertificateToSm2(cert),
CertConfig: orgCfg,
}
return orgCA, nil
}
// GenerateLocalUser 生成本地用户
func (ca *SM2CA) GenerateLocalUser(baseDir, fileName string) error {
err := createFolderStructure(baseDir, false)
if err != nil {
return err
}
keystore := filepath.Join(baseDir, "keystore")
priv, _, err := utils.GeneratePrivateKey(keystore, csp.SM2P256KygGen)
if err != nil {
return err
}
sm2PubKey, err := utils.GetSM2PublicKey(priv)
if err != nil {
return err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), fileName, []string{}, sm2PubKey, false)
if err != nil || cert == nil {
return err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(ca.Name)), ca.SignCert.Raw)
return err
}
func genCertificateGMSM2(baseDir, fileName string, template, parent *sm2.Certificate, key crypto.Signer) (*sm2.Certificate, error) {
certBytes, err := utils.CreateCertificateToMem(template, parent, key)
if err != nil {
return nil, err
}
fullName := filepath.Join(baseDir, fileName+"-cert.pem")
err = utils.CreateCertificateToPem(fullName, template, parent, key)
if err != nil {
return nil, err
}
x509Cert, err := sm2.ReadCertificateFromMem(certBytes)
if err != nil {
return nil, err
}
return x509Cert, nil
}
func createFolderStructure(rootDir string, isOrg bool) error {
var folders = []string{
filepath.Join(rootDir, "cacerts"),
filepath.Join(rootDir, "keystore"),
filepath.Join(rootDir, "signcerts"),
}
if isOrg {
folders = append(folders, filepath.Join(rootDir, "intermediatecerts"),)
}
for _, folder := range folders {
err := os.MkdirAll(folder, 0750)
if err != nil {
return err
}
}
return nil
}
func x509Filename(name string) string {
return name + "-cert.pem"
}
func x509Export(path string, cert []byte) error {
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
return pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
}
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package impl
import (
"crypto"
"crypto/rand"
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"math/big"
"os"
"time"
"path/filepath"
"fmt"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/factory/csp"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/generator"
"github.com/33cn/plugin/plugin/dapp/cert/authority/tools/cryptogen/generator/utils"
ty "github.com/33cn/plugin/plugin/dapp/cert/types"
"github.com/tjfoc/gmsm/sm2"
)
// EcdsaCA ecdsa CA结构
type EcdsaCA struct {
Name string
Signer crypto.Signer
SignCert *x509.Certificate
}
// SM2CA SM2 CA结构
type SM2CA struct {
Name string
Signer crypto.Signer
SignCert *sm2.Certificate
Sm2Key csp.Key
}
// NewCA 根据类型生成CA生成器
func NewCA(baseDir, name string, signType int) (generator.CAGenerator, error) {
if signType == ty.AuthECDSA {
return newEcdsaCA(baseDir, name)
} else if signType == ty.AuthSM2 {
return newSM2CA(baseDir, name)
} else {
return nil, fmt.Errorf("Invalid sign type")
}
}
func newEcdsaCA(baseDir, name string) (*EcdsaCA, error) {
err := os.MkdirAll(baseDir, 0750)
if err != nil {
return nil, err
}
var ca *EcdsaCA
priv, signer, err := utils.GeneratePrivateKey(baseDir, csp.ECDSAP256KeyGen)
if err != nil {
return nil, err
}
ecPubKey, err := utils.GetECPublicKey(priv)
if err != nil {
return nil, err
}
template := x509Template()
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
subject := subjectTemplate()
subject.CommonName = name
template.Subject = subject
template.SubjectKeyId = priv.SKI()
template.PublicKey = ecPubKey
x509Cert, err := genCertificateECDSA(baseDir, name, &template, &template, signer)
if err != nil {
return nil, err
}
ca = &EcdsaCA{
Name: name,
Signer: signer,
SignCert: x509Cert,
}
return ca, nil
}
// SignCertificate 证书签名
func (ca *EcdsaCA) SignCertificate(baseDir, name string, sans []string, pub interface{}) (*x509.Certificate, error) {
template := x509Template()
template.KeyUsage = x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{}
subject := subjectTemplate()
subject.CommonName = name
template.Subject = subject
template.DNSNames = sans
template.PublicKey = pub
cert, err := genCertificateECDSA(baseDir, name, &template, ca.SignCert, ca.Signer)
if err != nil {
return nil, err
}
return cert, nil
}
// GenerateLocalUser 生成本地用户
func (ca *EcdsaCA) GenerateLocalUser(baseDir, name string) error {
err := createFolderStructure(baseDir, true)
if err != nil {
return err
}
keystore := filepath.Join(baseDir, "keystore")
priv, _, err := utils.GeneratePrivateKey(keystore, csp.ECDSAP256KeyGen)
if err != nil {
return err
}
ecPubKey, err := utils.GetECPublicKey(priv)
if err != nil {
return err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), name, []string{}, ecPubKey)
if err != nil || cert == nil {
return err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(ca.Name)), ca.SignCert.Raw)
return err
}
func subjectTemplate() pkix.Name {
return pkix.Name{
Country: []string{"US"},
Locality: []string{"San Francisco"},
Province: []string{"California"},
}
}
func x509Template() x509.Certificate {
serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128)
serialNumber, _ := rand.Int(rand.Reader, serialNumberLimit)
expiry := 3650 * 24 * time.Hour
notBefore := time.Now().Add(-5 * time.Minute).UTC()
x509 := x509.Certificate{
SerialNumber: serialNumber,
NotBefore: notBefore,
NotAfter: notBefore.Add(expiry).UTC(),
BasicConstraintsValid: true,
}
return x509
}
func genCertificateECDSA(baseDir, name string, template, parent *x509.Certificate, priv interface{}) (*x509.Certificate, error) {
certBytes, err := x509.CreateCertificate(rand.Reader, template, parent, template.PublicKey, priv)
if err != nil {
return nil, err
}
fileName := filepath.Join(baseDir, name+"-cert.pem")
certFile, err := os.Create(fileName)
if err != nil {
return nil, err
}
defer certFile.Close()
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: certBytes})
if err != nil {
return nil, err
}
x509Cert, err := x509.ParseCertificate(certBytes)
if err != nil {
return nil, err
}
return x509Cert, nil
}
func newSM2CA(baseDir, name string) (*SM2CA, error) {
var ca *SM2CA
priv, signer, err := utils.GeneratePrivateKey(baseDir, csp.SM2P256KygGen)
if err != nil {
return nil, err
}
smPubKey, err := utils.GetSM2PublicKey(priv)
if err != nil {
return nil, err
}
template := x509Template()
template.IsCA = true
template.KeyUsage |= x509.KeyUsageDigitalSignature |
x509.KeyUsageKeyEncipherment | x509.KeyUsageCertSign |
x509.KeyUsageCRLSign
template.ExtKeyUsage = []x509.ExtKeyUsage{x509.ExtKeyUsageAny}
subject := subjectTemplate()
subject.CommonName = name
template.Subject = subject
template.SubjectKeyId = priv.SKI()
sm2cert := utils.ParseX509CertificateToSm2(&template)
sm2cert.PublicKey = smPubKey
x509Cert, err := genCertificateGMSM2(baseDir, name, sm2cert, sm2cert, signer)
if err == nil {
ca = &SM2CA{
Name: name,
Signer: signer,
SignCert: x509Cert,
Sm2Key: priv,
}
}
return ca, nil
}
// SignCertificate 证书签名
func (ca *SM2CA) SignCertificate(baseDir, name string, sans []string, pub interface{}) (*x509.Certificate, error) {
template := x509Template()
template.KeyUsage = x509.KeyUsageDigitalSignature
template.ExtKeyUsage = []x509.ExtKeyUsage{}
subject := subjectTemplate()
subject.CommonName = name
template.Subject = subject
template.DNSNames = sans
template.PublicKey = pub
sm2Tpl := utils.ParseX509CertificateToSm2(&template)
cert, err := genCertificateGMSM2(baseDir, name, sm2Tpl, ca.SignCert, ca.Signer)
if err != nil {
return nil, err
}
return utils.ParseSm2CertificateToX509(cert), nil
}
// GenerateLocalUser 生成本地用户
func (ca *SM2CA) GenerateLocalUser(baseDir, name string) error {
err := createFolderStructure(baseDir, true)
if err != nil {
return err
}
keystore := filepath.Join(baseDir, "keystore")
priv, _, err := utils.GeneratePrivateKey(keystore, csp.SM2P256KygGen)
if err != nil {
return err
}
sm2PubKey, err := utils.GetSM2PublicKey(priv)
if err != nil {
return err
}
cert, err := ca.SignCertificate(filepath.Join(baseDir, "signcerts"), name, []string{}, sm2PubKey)
if err != nil || cert == nil {
return err
}
err = x509Export(filepath.Join(baseDir, "cacerts", x509Filename(ca.Name)), ca.SignCert.Raw)
return err
}
func genCertificateGMSM2(baseDir, name string, template, parent *sm2.Certificate, key crypto.Signer) (*sm2.Certificate, error) {
certBytes, err := utils.CreateCertificateToMem(template, parent, key)
if err != nil {
return nil, err
}
fileName := filepath.Join(baseDir, name+"-cert.pem")
err = utils.CreateCertificateToPem(fileName, template, parent, key)
if err != nil {
return nil, err
}
x509Cert, err := sm2.ReadCertificateFromMem(certBytes)
if err != nil {
return nil, err
}
return x509Cert, nil
}
func createFolderStructure(rootDir string, local bool) error {
var folders = []string{
filepath.Join(rootDir, "cacerts"),
}
if local {
folders = append(folders, filepath.Join(rootDir, "keystore"),
filepath.Join(rootDir, "signcerts"))
}
for _, folder := range folders {
err := os.MkdirAll(folder, 0750)
if err != nil {
return err
}
}
return nil
}
func x509Filename(name string) string {
return name + "-cert.pem"
}
func x509Export(path string, cert []byte) error {
file, err := os.Create(path)
if err != nil {
return err
}
defer file.Close()
return pem.Encode(file, &pem.Block{Type: "CERTIFICATE", Bytes: cert})
}
......@@ -24,7 +24,7 @@ func Init(name string, cfg *types.Chain33Config, sub []byte) {
}
err := authority.Author.Init(&scfg)
if err != nil {
clog.Error("error to initialize authority", err)
clog.Error("error to initialize authority", "error", err)
return
}
drivers.Register(cfg, driverName, newCert, cfg.GetDappFork(driverName, "Enable"))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment