github.com/turingchain2020/turingchain@v1.1.21/executor/authority/authority.go (about)

     1  // Copyright Turing Corp. 2018 All Rights Reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package authority
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"path"
    12  
    13  	"github.com/turingchain2020/turingchain/common"
    14  	"github.com/turingchain2020/turingchain/executor/authority/core"
    15  	"github.com/turingchain2020/turingchain/executor/authority/utils"
    16  
    17  	"github.com/turingchain2020/turingchain/common/crypto"
    18  	log "github.com/turingchain2020/turingchain/common/log/log15"
    19  	"github.com/turingchain2020/turingchain/types"
    20  )
    21  
    22  var (
    23  	alog = log.New("module", "authority")
    24  
    25  	// Author 全局证书校验器
    26  	Author = &Authority{}
    27  
    28  	// IsAuthEnable 是否开启全局校验开关
    29  	IsAuthEnable = false
    30  )
    31  
    32  // Authority 证书校验器主要结构
    33  type Authority struct {
    34  	// 证书文件路径
    35  	cryptoPath string
    36  	// certByte缓存
    37  	authConfig *core.AuthConfig
    38  	// 校验器
    39  	validator core.Validator
    40  	// 签名类型
    41  	signType int
    42  	// 有效证书缓存
    43  	validCertCache [][]byte
    44  	// 历史证书缓存
    45  	HistoryCertCache *HistoryCertData
    46  }
    47  
    48  // HistoryCertData 历史变更记录
    49  type HistoryCertData struct {
    50  	CryptoCfg *core.AuthConfig
    51  	CurHeight int64
    52  	NxtHeight int64
    53  }
    54  
    55  // Init 初始化auth
    56  func (auth *Authority) Init(conf *types.AuthorityCfg) error {
    57  	if conf == nil || !conf.Enable {
    58  		return nil
    59  	}
    60  
    61  	if len(conf.CryptoPath) == 0 {
    62  		alog.Error("Crypto config path can not be null")
    63  		return types.ErrInvalidParam
    64  	}
    65  	auth.cryptoPath = conf.CryptoPath
    66  
    67  	sign := types.GetSignType("cert", conf.SignType)
    68  	if sign == types.Invalid {
    69  		alog.Error(fmt.Sprintf("Invalid sign type:%s", conf.SignType))
    70  		return types.ErrInvalidParam
    71  	}
    72  	auth.signType = sign
    73  
    74  	authConfig, err := core.GetAuthConfig(conf.CryptoPath)
    75  	if err != nil {
    76  		alog.Error("Get authority crypto config failed")
    77  		return err
    78  	}
    79  	auth.authConfig = authConfig
    80  
    81  	vldt, err := core.GetLocalValidator(authConfig, auth.signType)
    82  	if err != nil {
    83  		alog.Error(fmt.Sprintf("Get loacal validator failed. err:%s", err.Error()))
    84  		return err
    85  	}
    86  	auth.validator = vldt
    87  
    88  	auth.validCertCache = make([][]byte, 0)
    89  	auth.HistoryCertCache = &HistoryCertData{authConfig, -1, -1}
    90  
    91  	IsAuthEnable = true
    92  	return nil
    93  }
    94  
    95  // newAuthConfig store数据转成authConfig数据
    96  func newAuthConfig(store *types.HistoryCertStore) *core.AuthConfig {
    97  	ret := &core.AuthConfig{}
    98  	ret.RootCerts = make([][]byte, len(store.Rootcerts))
    99  	for i, v := range store.Rootcerts {
   100  		ret.RootCerts[i] = append(ret.RootCerts[i], v...)
   101  	}
   102  
   103  	ret.IntermediateCerts = make([][]byte, len(store.IntermediateCerts))
   104  	for i, v := range store.IntermediateCerts {
   105  		ret.IntermediateCerts[i] = append(ret.IntermediateCerts[i], v...)
   106  	}
   107  
   108  	ret.RevocationList = make([][]byte, len(store.RevocationList))
   109  	for i, v := range store.RevocationList {
   110  		ret.RevocationList[i] = append(ret.RevocationList[i], v...)
   111  	}
   112  
   113  	return ret
   114  }
   115  
   116  // ReloadCert 从数据库中的记录数据恢复证书,用于证书回滚
   117  func (auth *Authority) ReloadCert(store *types.HistoryCertStore) error {
   118  	if !IsAuthEnable {
   119  		return nil
   120  	}
   121  
   122  	//判断是否回滚到无证书区块
   123  	if len(store.Rootcerts) == 0 {
   124  		auth.authConfig = nil
   125  		auth.validator, _ = core.NewNoneValidator()
   126  	} else {
   127  		auth.authConfig = newAuthConfig(store)
   128  		// 加载校验器
   129  		vldt, err := core.GetLocalValidator(auth.authConfig, auth.signType)
   130  		if err != nil {
   131  			return err
   132  		}
   133  		auth.validator = vldt
   134  	}
   135  
   136  	// 清空有效证书缓存
   137  	auth.validCertCache = auth.validCertCache[:0]
   138  
   139  	// 更新最新历史数据
   140  	auth.HistoryCertCache = &HistoryCertData{auth.authConfig, store.CurHeigth, store.NxtHeight}
   141  
   142  	return nil
   143  }
   144  
   145  // ReloadCertByHeght 从新的authdir下的文件更新证书,用于证书更新
   146  func (auth *Authority) ReloadCertByHeght(currentHeight int64) error {
   147  	if !IsAuthEnable {
   148  		return nil
   149  	}
   150  
   151  	authConfig, err := core.GetAuthConfig(auth.cryptoPath)
   152  	if err != nil {
   153  		alog.Error("Get authority crypto config failed")
   154  		return err
   155  	}
   156  	auth.authConfig = authConfig
   157  
   158  	// 加载校验器
   159  	vldt, err := core.GetLocalValidator(auth.authConfig, auth.signType)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	auth.validator = vldt
   164  
   165  	// 清空有效证书缓存
   166  	auth.validCertCache = auth.validCertCache[:0]
   167  
   168  	// 更新最新历史数据
   169  	auth.HistoryCertCache = &HistoryCertData{auth.authConfig, currentHeight, -1}
   170  
   171  	return nil
   172  }
   173  
   174  // Validate 检验证书
   175  func (auth *Authority) Validate(signature *types.Signature) error {
   176  	// 从proto中解码signature
   177  	cert, err := auth.validator.GetCertFromSignature(signature.Signature)
   178  	if err != nil {
   179  		return err
   180  	}
   181  
   182  	// 是否在有效证书缓存中
   183  	for _, v := range auth.validCertCache {
   184  		if bytes.Equal(v, cert) {
   185  			return nil
   186  		}
   187  	}
   188  
   189  	// 校验
   190  	err = auth.validator.Validate(cert, signature.GetPubkey())
   191  	if err != nil {
   192  		alog.Error(fmt.Sprintf("validate cert failed. %s", err.Error()))
   193  		return fmt.Errorf("validate cert failed. error:%s", err.Error())
   194  	}
   195  	auth.validCertCache = append(auth.validCertCache, cert)
   196  
   197  	return nil
   198  }
   199  
   200  // User 用户关联的证书私钥信息
   201  type User struct {
   202  	ID   string
   203  	Cert []byte
   204  	Key  crypto.PrivKey
   205  }
   206  
   207  // UserLoader SKD加载user使用
   208  type UserLoader struct {
   209  	configPath string
   210  	userMap    map[string]*User
   211  	signType   int
   212  }
   213  
   214  // Init userloader初始化
   215  func (loader *UserLoader) Init(configPath string, signType string) error {
   216  	loader.configPath = configPath
   217  	loader.userMap = make(map[string]*User)
   218  
   219  	sign := types.GetSignType("cert", signType)
   220  	if sign == types.Invalid {
   221  		alog.Error(fmt.Sprintf("Invalid sign type:%s", signType))
   222  		return types.ErrInvalidParam
   223  	}
   224  	loader.signType = sign
   225  
   226  	return loader.loadUsers()
   227  }
   228  
   229  func (loader *UserLoader) loadUsers() error {
   230  	certDir := path.Join(loader.configPath, "signcerts")
   231  	dir, err := ioutil.ReadDir(certDir)
   232  	if err != nil {
   233  		return err
   234  	}
   235  
   236  	keyDir := path.Join(loader.configPath, "keystore")
   237  	for _, file := range dir {
   238  		filePath := path.Join(certDir, file.Name())
   239  		certBytes, err := utils.ReadFile(filePath)
   240  		if err != nil {
   241  			continue
   242  		}
   243  
   244  		ski, err := utils.GetPublicKeySKIFromCert(certBytes, loader.signType)
   245  		if err != nil {
   246  			alog.Error(err.Error())
   247  			continue
   248  		}
   249  		filePath = path.Join(keyDir, ski+"_sk")
   250  		keyBytes, err := utils.ReadFile(filePath)
   251  		if err != nil {
   252  			continue
   253  		}
   254  
   255  		priv, err := loader.genCryptoPriv(keyBytes)
   256  		if err != nil {
   257  			alog.Error(fmt.Sprintf("Generate crypto private failed. error:%s", err.Error()))
   258  			continue
   259  		}
   260  
   261  		loader.userMap[file.Name()] = &User{file.Name(), certBytes, priv}
   262  	}
   263  
   264  	return nil
   265  }
   266  
   267  func (loader *UserLoader) genCryptoPriv(keyBytes []byte) (crypto.PrivKey, error) {
   268  	cr, err := crypto.New(types.GetSignName("cert", loader.signType))
   269  	if err != nil {
   270  		return nil, fmt.Errorf("create crypto %s failed, error:%s", types.GetSignName("cert", loader.signType), err)
   271  	}
   272  	//privKeyByte, err := utils.PrivKeyByteFromRaw(keyBytes, loader.signType)
   273  	//if err != nil {
   274  	//	return nil, err
   275  	//}
   276  
   277  	privkeyBytes, err := common.FromHex(string(keyBytes))
   278  	if err != nil {
   279  		return nil, err
   280  	}
   281  
   282  	priv, err := cr.PrivKeyFromBytes(privkeyBytes)
   283  	if err != nil {
   284  		return nil, fmt.Errorf("get private key failed, error:%s", err)
   285  	}
   286  
   287  	return priv, nil
   288  }
   289  
   290  // Get 根据用户名获取user结构
   291  func (loader *UserLoader) Get(userName, orgName string) (*User, error) {
   292  	keyvalue := fmt.Sprintf("%s@%s-cert.pem", userName, orgName)
   293  	user, ok := loader.userMap[keyvalue]
   294  	if !ok {
   295  		return nil, types.ErrInvalidParam
   296  	}
   297  
   298  	resp := &User{}
   299  	resp.Cert = append(resp.Cert, user.Cert...)
   300  	resp.Key = user.Key
   301  
   302  	return resp, nil
   303  }