mirror of
https://github.com/fatedier/frp.git
synced 2025-07-27 07:35:07 +00:00
using glide
This commit is contained in:
45
vendor/github.com/tjfoc/gmsm/.travis.yml
generated
vendored
Normal file
45
vendor/github.com/tjfoc/gmsm/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
sudo: false
|
||||
language:
|
||||
- go
|
||||
go:
|
||||
- 1.8.3
|
||||
|
||||
#before_install:
|
||||
#- git rm -r --cached .
|
||||
#- git add .
|
||||
#- git commit -m 'update .gitignore'
|
||||
|
||||
install:
|
||||
- go get -v github.com/golang/lint/golint
|
||||
- go get -v golang.org/x/crypto/ripemd160
|
||||
- go get -v golang.org/x/crypto/sha3
|
||||
- go build -v ./sm2
|
||||
- go build -v ./sm3
|
||||
- go build -v ./sm4
|
||||
|
||||
script:
|
||||
- go vet ./sm2
|
||||
- go vet ./sm3
|
||||
- go vet ./sm4
|
||||
- $HOME/gopath/bin/golint .
|
||||
- export GOPATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace:$GOPATH"
|
||||
- export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$PATH"
|
||||
- ls /home/travis/gopath/src/
|
||||
- go test -v ./sm2
|
||||
- go test -v ./sm3
|
||||
- go test -v ./sm4
|
||||
|
||||
after_failure:
|
||||
|
||||
- |
|
||||
echo "Error!"
|
||||
notifications:
|
||||
email:
|
||||
recipients:
|
||||
- zhiqiang@tj-fintech.com
|
||||
- yanwenze@tj-fintech.com
|
||||
- maoxiuze@tj-fintech.com
|
||||
- yewei@tj-fintech.com
|
||||
|
||||
on_success: never # default: change
|
||||
on_failure: never # default: always
|
17
vendor/github.com/tjfoc/gmsm/CHANGELOG.md
generated
vendored
Normal file
17
vendor/github.com/tjfoc/gmsm/CHANGELOG.md
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
## 更新日志
|
||||
|
||||
主要更新:
|
||||
- 添加以下oid<br>
|
||||
SM3WithSM2 1.2.156.10197.1.501<br>
|
||||
SHA1WithSM2 1.2.156.10197.1.502<br>
|
||||
SHA256WithSM2 1.2.156.10197.1.503<br>
|
||||
|
||||
- x509生成的证书如今可以使用SM3作为hash算法
|
||||
|
||||
- 引入了以下hash算法
|
||||
RIPEMD160<br>
|
||||
SHA3_256<br>
|
||||
SHA3_384<br>
|
||||
SHA3_512<br>
|
||||
SHA3_SM3<br>
|
||||
用户需要自己安装golang.org/x/crypto
|
42
vendor/github.com/tjfoc/gmsm/README.md
generated
vendored
Normal file
42
vendor/github.com/tjfoc/gmsm/README.md
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
|
||||
GM SM2/3/4 library based on Golang
|
||||
|
||||
Process Results
|
||||
[](https://travis-ci.org/tjfoc/gmsm)
|
||||
|
||||
基于Go语言的国密SM2/SM3/SM4加密算法库
|
||||
|
||||
版权所有 苏州同济区块链研究院有限公司(http://www.tj-fintech.com)
|
||||
|
||||
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
See the License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
|
||||
GMSM包含以下主要功能
|
||||
|
||||
SM2: 国密椭圆曲线算法库
|
||||
. 支持Generate Key, Sign, Verify基础操作
|
||||
. 支持加密和不加密的pem文件格式(加密方法参见RFC5958, 具体实现参加代码)
|
||||
. 支持证书的生成,证书的读写(接口兼容rsa和ecdsa的证书)
|
||||
. 支持证书链的操作(接口兼容rsa和ecdsa)
|
||||
. 支持crypto.Signer接口
|
||||
|
||||
SM3: 国密hash算法库
|
||||
. 支持基础的sm3Sum操作
|
||||
. 支持hash.Hash接口
|
||||
|
||||
SM4: 国密分组密码算法库
|
||||
. 支持Generate Key, Encrypt, Decrypt基础操作
|
||||
. 提供Cipher.Block接口
|
||||
. 支持加密和不加密的pem文件格式(加密方法为pem block加密, 具体函数为x509.EncryptPEMBlock)
|
||||
|
||||
|
||||
关于GMSM交流: [](https://gitter.im/tjfoc/gmsm?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
229
vendor/github.com/tjfoc/gmsm/sm2/cert_pool.go
generated
vendored
Normal file
229
vendor/github.com/tjfoc/gmsm/sm2/cert_pool.go
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// Possible certificate files; stop after finding one.
|
||||
var certFiles = []string{
|
||||
"/etc/ssl/certs/ca-certificates.crt", // Debian/Ubuntu/Gentoo etc.
|
||||
"/etc/pki/tls/certs/ca-bundle.crt", // Fedora/RHEL 6
|
||||
"/etc/ssl/ca-bundle.pem", // OpenSUSE
|
||||
"/etc/pki/tls/cacert.pem", // OpenELEC
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem", // CentOS/RHEL 7
|
||||
}
|
||||
|
||||
// CertPool is a set of certificates.
|
||||
type CertPool struct {
|
||||
bySubjectKeyId map[string][]int
|
||||
byName map[string][]int
|
||||
certs []*Certificate
|
||||
}
|
||||
|
||||
// NewCertPool returns a new, empty CertPool.
|
||||
func NewCertPool() *CertPool {
|
||||
return &CertPool{
|
||||
bySubjectKeyId: make(map[string][]int),
|
||||
byName: make(map[string][]int),
|
||||
}
|
||||
}
|
||||
|
||||
// Possible directories with certificate files; stop after successfully
|
||||
// reading at least one file from a directory.
|
||||
var certDirectories = []string{
|
||||
"/etc/ssl/certs", // SLES10/SLES11, https://golang.org/issue/12139
|
||||
"/system/etc/security/cacerts", // Android
|
||||
}
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
systemRoots *CertPool
|
||||
systemRootsErr error
|
||||
)
|
||||
|
||||
func systemRootsPool() *CertPool {
|
||||
once.Do(initSystemRoots)
|
||||
return systemRoots
|
||||
}
|
||||
|
||||
func initSystemRoots() {
|
||||
systemRoots, systemRootsErr = loadSystemRoots()
|
||||
}
|
||||
|
||||
func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func loadSystemRoots() (*CertPool, error) {
|
||||
roots := NewCertPool()
|
||||
var firstErr error
|
||||
for _, file := range certFiles {
|
||||
data, err := ioutil.ReadFile(file)
|
||||
if err == nil {
|
||||
roots.AppendCertsFromPEM(data)
|
||||
return roots, nil
|
||||
}
|
||||
if firstErr == nil && !os.IsNotExist(err) {
|
||||
firstErr = err
|
||||
}
|
||||
}
|
||||
|
||||
for _, directory := range certDirectories {
|
||||
fis, err := ioutil.ReadDir(directory)
|
||||
if err != nil {
|
||||
if firstErr == nil && !os.IsNotExist(err) {
|
||||
firstErr = err
|
||||
}
|
||||
continue
|
||||
}
|
||||
rootsAdded := false
|
||||
for _, fi := range fis {
|
||||
data, err := ioutil.ReadFile(directory + "/" + fi.Name())
|
||||
if err == nil && roots.AppendCertsFromPEM(data) {
|
||||
rootsAdded = true
|
||||
}
|
||||
}
|
||||
if rootsAdded {
|
||||
return roots, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, firstErr
|
||||
}
|
||||
|
||||
// SystemCertPool returns a copy of the system cert pool.
|
||||
//
|
||||
// Any mutations to the returned pool are not written to disk and do
|
||||
// not affect any other pool.
|
||||
func SystemCertPool() (*CertPool, error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
// Issue 16736, 18609:
|
||||
return nil, errors.New("crypto/x509: system root pool is not available on Windows")
|
||||
}
|
||||
|
||||
return loadSystemRoots()
|
||||
}
|
||||
|
||||
// findVerifiedParents attempts to find certificates in s which have signed the
|
||||
// given certificate. If any candidates were rejected then errCert will be set
|
||||
// to one of them, arbitrarily, and err will contain the reason that it was
|
||||
// rejected.
|
||||
func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int, errCert *Certificate, err error) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
var candidates []int
|
||||
|
||||
if len(cert.AuthorityKeyId) > 0 {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[string(cert.RawIssuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
if err = cert.CheckSignatureFrom(s.certs[c]); err == nil {
|
||||
parents = append(parents, c)
|
||||
} else {
|
||||
errCert = s.certs[c]
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *CertPool) contains(cert *Certificate) bool {
|
||||
if s == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
candidates := s.byName[string(cert.RawSubject)]
|
||||
for _, c := range candidates {
|
||||
if s.certs[c].Equal(cert) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// AddCert adds a certificate to a pool.
|
||||
func (s *CertPool) AddCert(cert *Certificate) {
|
||||
if cert == nil {
|
||||
panic("adding nil Certificate to CertPool")
|
||||
}
|
||||
|
||||
// Check that the certificate isn't being added twice.
|
||||
if s.contains(cert) {
|
||||
return
|
||||
}
|
||||
|
||||
n := len(s.certs)
|
||||
s.certs = append(s.certs, cert)
|
||||
|
||||
if len(cert.SubjectKeyId) > 0 {
|
||||
keyId := string(cert.SubjectKeyId)
|
||||
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
|
||||
}
|
||||
name := string(cert.RawSubject)
|
||||
s.byName[name] = append(s.byName[name], n)
|
||||
}
|
||||
|
||||
// AppendCertsFromPEM attempts to parse a series of PEM encoded certificates.
|
||||
// It appends any certificates found to s and reports whether any certificates
|
||||
// were successfully parsed.
|
||||
//
|
||||
// On many Linux systems, /etc/ssl/cert.pem will contain the system wide set
|
||||
// of root CAs in a format suitable for this function.
|
||||
func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) {
|
||||
for len(pemCerts) > 0 {
|
||||
var block *pem.Block
|
||||
block, pemCerts = pem.Decode(pemCerts)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" || len(block.Headers) != 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
cert, err := ParseCertificate(block.Bytes)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
s.AddCert(cert)
|
||||
ok = true
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Subjects returns a list of the DER-encoded subjects of
|
||||
// all of the certificates in the pool.
|
||||
func (s *CertPool) Subjects() [][]byte {
|
||||
res := make([][]byte, len(s.certs))
|
||||
for i, c := range s.certs {
|
||||
res[i] = c.RawSubject
|
||||
}
|
||||
return res
|
||||
}
|
43
vendor/github.com/tjfoc/gmsm/sm2/p256.go
generated
vendored
Normal file
43
vendor/github.com/tjfoc/gmsm/sm2/p256.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"math/big"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var initonce sync.Once
|
||||
var p256Sm2Params *elliptic.CurveParams
|
||||
|
||||
// 取自elliptic的p256.go文件,修改曲线参数为sm2
|
||||
// See FIPS 186-3, section D.2.3
|
||||
func initP256Sm2() {
|
||||
p256Sm2Params = &elliptic.CurveParams{Name: "SM2-P-256"} // 注明为SM2
|
||||
//SM2椭 椭 圆 曲 线 公 钥 密 码 算 法 推 荐 曲 线 参 数
|
||||
p256Sm2Params.P, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", 16)
|
||||
p256Sm2Params.N, _ = new(big.Int).SetString("FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", 16)
|
||||
p256Sm2Params.B, _ = new(big.Int).SetString("28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", 16)
|
||||
p256Sm2Params.Gx, _ = new(big.Int).SetString("32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", 16)
|
||||
p256Sm2Params.Gy, _ = new(big.Int).SetString("BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", 16)
|
||||
p256Sm2Params.BitSize = 256
|
||||
}
|
||||
|
||||
func P256Sm2() elliptic.Curve {
|
||||
initonce.Do(initP256Sm2)
|
||||
return p256Sm2Params
|
||||
}
|
132
vendor/github.com/tjfoc/gmsm/sm2/pkcs1.go
generated
vendored
Normal file
132
vendor/github.com/tjfoc/gmsm/sm2/pkcs1.go
generated
vendored
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// pkcs1PrivateKey is a structure which mirrors the PKCS#1 ASN.1 for an RSA private key.
|
||||
type pkcs1PrivateKey struct {
|
||||
Version int
|
||||
N *big.Int
|
||||
E int
|
||||
D *big.Int
|
||||
P *big.Int
|
||||
Q *big.Int
|
||||
// We ignore these values, if present, because rsa will calculate them.
|
||||
Dp *big.Int `asn1:"optional"`
|
||||
Dq *big.Int `asn1:"optional"`
|
||||
Qinv *big.Int `asn1:"optional"`
|
||||
|
||||
AdditionalPrimes []pkcs1AdditionalRSAPrime `asn1:"optional,omitempty"`
|
||||
}
|
||||
|
||||
type pkcs1AdditionalRSAPrime struct {
|
||||
Prime *big.Int
|
||||
|
||||
// We ignore these values because rsa will calculate them.
|
||||
Exp *big.Int
|
||||
Coeff *big.Int
|
||||
}
|
||||
|
||||
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form.
|
||||
func ParsePKCS1PrivateKey(der []byte) (*rsa.PrivateKey, error) {
|
||||
var priv pkcs1PrivateKey
|
||||
rest, err := asn1.Unmarshal(der, &priv)
|
||||
if len(rest) > 0 {
|
||||
return nil, asn1.SyntaxError{Msg: "trailing data"}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if priv.Version > 1 {
|
||||
return nil, errors.New("x509: unsupported private key version")
|
||||
}
|
||||
|
||||
if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 {
|
||||
return nil, errors.New("x509: private key contains zero or negative value")
|
||||
}
|
||||
|
||||
key := new(rsa.PrivateKey)
|
||||
key.PublicKey = rsa.PublicKey{
|
||||
E: priv.E,
|
||||
N: priv.N,
|
||||
}
|
||||
|
||||
key.D = priv.D
|
||||
key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes))
|
||||
key.Primes[0] = priv.P
|
||||
key.Primes[1] = priv.Q
|
||||
for i, a := range priv.AdditionalPrimes {
|
||||
if a.Prime.Sign() <= 0 {
|
||||
return nil, errors.New("x509: private key contains zero or negative prime")
|
||||
}
|
||||
key.Primes[i+2] = a.Prime
|
||||
// We ignore the other two values because rsa will calculate
|
||||
// them as needed.
|
||||
}
|
||||
|
||||
err = key.Validate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key.Precompute()
|
||||
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// MarshalPKCS1PrivateKey converts a private key to ASN.1 DER encoded form.
|
||||
func MarshalPKCS1PrivateKey(key *rsa.PrivateKey) []byte {
|
||||
key.Precompute()
|
||||
|
||||
version := 0
|
||||
if len(key.Primes) > 2 {
|
||||
version = 1
|
||||
}
|
||||
|
||||
priv := pkcs1PrivateKey{
|
||||
Version: version,
|
||||
N: key.N,
|
||||
E: key.PublicKey.E,
|
||||
D: key.D,
|
||||
P: key.Primes[0],
|
||||
Q: key.Primes[1],
|
||||
Dp: key.Precomputed.Dp,
|
||||
Dq: key.Precomputed.Dq,
|
||||
Qinv: key.Precomputed.Qinv,
|
||||
}
|
||||
|
||||
priv.AdditionalPrimes = make([]pkcs1AdditionalRSAPrime, len(key.Precomputed.CRTValues))
|
||||
for i, values := range key.Precomputed.CRTValues {
|
||||
priv.AdditionalPrimes[i].Prime = key.Primes[2+i]
|
||||
priv.AdditionalPrimes[i].Exp = values.Exp
|
||||
priv.AdditionalPrimes[i].Coeff = values.Coeff
|
||||
}
|
||||
|
||||
b, _ := asn1.Marshal(priv)
|
||||
return b
|
||||
}
|
||||
|
||||
// rsaPublicKey reflects the ASN.1 structure of a PKCS#1 public key.
|
||||
type rsaPublicKey struct {
|
||||
N *big.Int
|
||||
E int
|
||||
}
|
488
vendor/github.com/tjfoc/gmsm/sm2/pkcs8.go
generated
vendored
Normal file
488
vendor/github.com/tjfoc/gmsm/sm2/pkcs8.go
generated
vendored
Normal file
@@ -0,0 +1,488 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/elliptic"
|
||||
"crypto/hmac"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"crypto/sha1"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/pem"
|
||||
"errors"
|
||||
"hash"
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"os"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
/*
|
||||
* reference to RFC5959 and RFC2898
|
||||
*/
|
||||
|
||||
var (
|
||||
oidPBES1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 3} // pbeWithMD5AndDES-CBC(PBES1)
|
||||
oidPBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13} // id-PBES2(PBES2)
|
||||
oidPBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12} // id-PBKDF2
|
||||
|
||||
oidKEYMD5 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5}
|
||||
oidKEYSHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
|
||||
oidKEYSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
|
||||
oidKEYSHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 11}
|
||||
|
||||
oidAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
|
||||
oidAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
|
||||
|
||||
oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
|
||||
)
|
||||
|
||||
// reference to https://www.rfc-editor.org/rfc/rfc5958.txt
|
||||
type PrivateKeyInfo struct {
|
||||
Version int // v1 or v2
|
||||
PrivateKeyAlgorithm []asn1.ObjectIdentifier
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// reference to https://www.rfc-editor.org/rfc/rfc5958.txt
|
||||
type EncryptedPrivateKeyInfo struct {
|
||||
EncryptionAlgorithm Pbes2Algorithms
|
||||
EncryptedData []byte
|
||||
}
|
||||
|
||||
// reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||
type Pbes2Algorithms struct {
|
||||
IdPBES2 asn1.ObjectIdentifier
|
||||
Pbes2Params Pbes2Params
|
||||
}
|
||||
|
||||
// reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||
type Pbes2Params struct {
|
||||
KeyDerivationFunc Pbes2KDfs // PBES2-KDFs
|
||||
EncryptionScheme Pbes2Encs // PBES2-Encs
|
||||
}
|
||||
|
||||
// reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||
type Pbes2KDfs struct {
|
||||
IdPBKDF2 asn1.ObjectIdentifier
|
||||
Pkdf2Params Pkdf2Params
|
||||
}
|
||||
|
||||
type Pbes2Encs struct {
|
||||
EncryAlgo asn1.ObjectIdentifier
|
||||
IV []byte
|
||||
}
|
||||
|
||||
// reference to https://www.ietf.org/rfc/rfc2898.txt
|
||||
type Pkdf2Params struct {
|
||||
Salt []byte
|
||||
IterationCount int
|
||||
Prf pkix.AlgorithmIdentifier
|
||||
}
|
||||
|
||||
type sm2PrivateKey struct {
|
||||
Version int
|
||||
PrivateKey []byte
|
||||
NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
|
||||
PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
|
||||
}
|
||||
|
||||
type pkcs8 struct {
|
||||
Version int
|
||||
Algo pkix.AlgorithmIdentifier
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// copy from crypto/pbkdf2.go
|
||||
func pbkdf(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
|
||||
prf := hmac.New(h, password)
|
||||
hashLen := prf.Size()
|
||||
numBlocks := (keyLen + hashLen - 1) / hashLen
|
||||
|
||||
var buf [4]byte
|
||||
dk := make([]byte, 0, numBlocks*hashLen)
|
||||
U := make([]byte, hashLen)
|
||||
for block := 1; block <= numBlocks; block++ {
|
||||
// N.B.: || means concatenation, ^ means XOR
|
||||
// for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
|
||||
// U_1 = PRF(password, salt || uint(i))
|
||||
prf.Reset()
|
||||
prf.Write(salt)
|
||||
buf[0] = byte(block >> 24)
|
||||
buf[1] = byte(block >> 16)
|
||||
buf[2] = byte(block >> 8)
|
||||
buf[3] = byte(block)
|
||||
prf.Write(buf[:4])
|
||||
dk = prf.Sum(dk)
|
||||
T := dk[len(dk)-hashLen:]
|
||||
copy(U, T)
|
||||
|
||||
// U_n = PRF(password, U_(n-1))
|
||||
for n := 2; n <= iter; n++ {
|
||||
prf.Reset()
|
||||
prf.Write(U)
|
||||
U = U[:0]
|
||||
U = prf.Sum(U)
|
||||
for x := range U {
|
||||
T[x] ^= U[x]
|
||||
}
|
||||
}
|
||||
}
|
||||
return dk[:keyLen]
|
||||
}
|
||||
|
||||
func ParseSm2PublicKey(der []byte) (*PublicKey, error) {
|
||||
var pubkey pkixPublicKey
|
||||
|
||||
if _, err := asn1.Unmarshal(der, &pubkey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !reflect.DeepEqual(pubkey.Algo.Algorithm, oidSM2) {
|
||||
return nil, errors.New("x509: not sm2 elliptic curve")
|
||||
}
|
||||
curve := P256Sm2()
|
||||
x, y := elliptic.Unmarshal(curve, pubkey.BitString.Bytes)
|
||||
pub := PublicKey{
|
||||
Curve: curve,
|
||||
X: x,
|
||||
Y: y,
|
||||
}
|
||||
return &pub, nil
|
||||
}
|
||||
|
||||
func MarshalSm2PublicKey(key *PublicKey) ([]byte, error) {
|
||||
var r pkixPublicKey
|
||||
var algo pkix.AlgorithmIdentifier
|
||||
|
||||
algo.Algorithm = oidSM2
|
||||
algo.Parameters.Class = 0
|
||||
algo.Parameters.Tag = 6
|
||||
algo.Parameters.IsCompound = false
|
||||
algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
|
||||
r.Algo = algo
|
||||
r.BitString = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
|
||||
return asn1.Marshal(r)
|
||||
}
|
||||
|
||||
func ParseSm2PrivateKey(der []byte) (*PrivateKey, error) {
|
||||
var privKey sm2PrivateKey
|
||||
|
||||
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
|
||||
return nil, errors.New("x509: failed to parse SM2 private key: " + err.Error())
|
||||
}
|
||||
curve := P256Sm2()
|
||||
k := new(big.Int).SetBytes(privKey.PrivateKey)
|
||||
curveOrder := curve.Params().N
|
||||
if k.Cmp(curveOrder) >= 0 {
|
||||
return nil, errors.New("x509: invalid elliptic curve private key value")
|
||||
}
|
||||
priv := new(PrivateKey)
|
||||
priv.Curve = curve
|
||||
priv.D = k
|
||||
privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
|
||||
for len(privKey.PrivateKey) > len(privateKey) {
|
||||
if privKey.PrivateKey[0] != 0 {
|
||||
return nil, errors.New("x509: invalid private key length")
|
||||
}
|
||||
privKey.PrivateKey = privKey.PrivateKey[1:]
|
||||
}
|
||||
copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
|
||||
priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
func ParsePKCS8UnecryptedPrivateKey(der []byte) (*PrivateKey, error) {
|
||||
var privKey pkcs8
|
||||
|
||||
if _, err := asn1.Unmarshal(der, &privKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !reflect.DeepEqual(privKey.Algo.Algorithm, oidSM2) {
|
||||
return nil, errors.New("x509: not sm2 elliptic curve")
|
||||
}
|
||||
return ParseSm2PrivateKey(privKey.PrivateKey)
|
||||
}
|
||||
|
||||
func ParsePKCS8EcryptedPrivateKey(der, pwd []byte) (*PrivateKey, error) {
|
||||
var keyInfo EncryptedPrivateKeyInfo
|
||||
|
||||
_, err := asn1.Unmarshal(der, &keyInfo)
|
||||
if err != nil {
|
||||
return nil, errors.New("x509: unknown format")
|
||||
}
|
||||
if !reflect.DeepEqual(keyInfo.EncryptionAlgorithm.IdPBES2, oidPBES2) {
|
||||
return nil, errors.New("x509: only support PBES2")
|
||||
}
|
||||
encryptionScheme := keyInfo.EncryptionAlgorithm.Pbes2Params.EncryptionScheme
|
||||
keyDerivationFunc := keyInfo.EncryptionAlgorithm.Pbes2Params.KeyDerivationFunc
|
||||
if !reflect.DeepEqual(keyDerivationFunc.IdPBKDF2, oidPBKDF2) {
|
||||
return nil, errors.New("x509: only support PBKDF2")
|
||||
}
|
||||
pkdf2Params := keyDerivationFunc.Pkdf2Params
|
||||
if !reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES128CBC) &&
|
||||
!reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES256CBC) {
|
||||
return nil, errors.New("x509: unknow encryption algorithm")
|
||||
}
|
||||
iv := encryptionScheme.IV
|
||||
salt := pkdf2Params.Salt
|
||||
iter := pkdf2Params.IterationCount
|
||||
encryptedKey := keyInfo.EncryptedData
|
||||
var key []byte
|
||||
switch {
|
||||
case pkdf2Params.Prf.Algorithm.Equal(oidKEYMD5):
|
||||
key = pbkdf(pwd, salt, iter, 32, md5.New)
|
||||
break
|
||||
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA1):
|
||||
key = pbkdf(pwd, salt, iter, 32, sha1.New)
|
||||
break
|
||||
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA256):
|
||||
key = pbkdf(pwd, salt, iter, 32, sha256.New)
|
||||
break
|
||||
case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA512):
|
||||
key = pbkdf(pwd, salt, iter, 32, sha512.New)
|
||||
break
|
||||
default:
|
||||
return nil, errors.New("x509: unknown hash algorithm")
|
||||
}
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(encryptedKey, encryptedKey)
|
||||
rKey, err := ParsePKCS8UnecryptedPrivateKey(encryptedKey)
|
||||
if err != nil {
|
||||
return nil, errors.New("pkcs8: incorrect password")
|
||||
}
|
||||
return rKey, nil
|
||||
}
|
||||
|
||||
func ParsePKCS8PrivateKey(der, pwd []byte) (*PrivateKey, error) {
|
||||
if pwd == nil {
|
||||
return ParsePKCS8UnecryptedPrivateKey(der)
|
||||
}
|
||||
return ParsePKCS8EcryptedPrivateKey(der, pwd)
|
||||
}
|
||||
|
||||
func MarshalSm2UnecryptedPrivateKey(key *PrivateKey) ([]byte, error) {
|
||||
var r pkcs8
|
||||
var priv sm2PrivateKey
|
||||
var algo pkix.AlgorithmIdentifier
|
||||
|
||||
algo.Algorithm = oidSM2
|
||||
algo.Parameters.Class = 0
|
||||
algo.Parameters.Tag = 6
|
||||
algo.Parameters.IsCompound = false
|
||||
algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
|
||||
priv.Version = 1
|
||||
priv.NamedCurveOID = oidNamedCurveP256SM2
|
||||
priv.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
|
||||
priv.PrivateKey = key.D.Bytes()
|
||||
r.Version = 0
|
||||
r.Algo = algo
|
||||
r.PrivateKey, _ = asn1.Marshal(priv)
|
||||
return asn1.Marshal(r)
|
||||
}
|
||||
|
||||
func MarshalSm2EcryptedPrivateKey(PrivKey *PrivateKey, pwd []byte) ([]byte, error) {
|
||||
der, err := MarshalSm2UnecryptedPrivateKey(PrivKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
iter := 2048
|
||||
salt := make([]byte, 8)
|
||||
iv := make([]byte, 16)
|
||||
rand.Reader.Read(salt)
|
||||
rand.Reader.Read(iv)
|
||||
key := pbkdf(pwd, salt, iter, 32, sha1.New) // 默认是SHA1
|
||||
padding := aes.BlockSize - len(der)%aes.BlockSize
|
||||
if padding > 0 {
|
||||
n := len(der)
|
||||
der = append(der, make([]byte, padding)...)
|
||||
for i := 0; i < padding; i++ {
|
||||
der[n+i] = byte(padding)
|
||||
}
|
||||
}
|
||||
encryptedKey := make([]byte, len(der))
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(encryptedKey, der)
|
||||
var algorithmIdentifier pkix.AlgorithmIdentifier
|
||||
algorithmIdentifier.Algorithm = oidKEYSHA1
|
||||
algorithmIdentifier.Parameters.Tag = 5
|
||||
algorithmIdentifier.Parameters.IsCompound = false
|
||||
algorithmIdentifier.Parameters.FullBytes = []byte{5, 0}
|
||||
keyDerivationFunc := Pbes2KDfs{
|
||||
oidPBKDF2,
|
||||
Pkdf2Params{
|
||||
salt,
|
||||
iter,
|
||||
algorithmIdentifier,
|
||||
},
|
||||
}
|
||||
encryptionScheme := Pbes2Encs{
|
||||
oidAES256CBC,
|
||||
iv,
|
||||
}
|
||||
pbes2Algorithms := Pbes2Algorithms{
|
||||
oidPBES2,
|
||||
Pbes2Params{
|
||||
keyDerivationFunc,
|
||||
encryptionScheme,
|
||||
},
|
||||
}
|
||||
encryptedPkey := EncryptedPrivateKeyInfo{
|
||||
pbes2Algorithms,
|
||||
encryptedKey,
|
||||
}
|
||||
return asn1.Marshal(encryptedPkey)
|
||||
}
|
||||
|
||||
func MarshalSm2PrivateKey(key *PrivateKey, pwd []byte) ([]byte, error) {
|
||||
if pwd == nil {
|
||||
return MarshalSm2UnecryptedPrivateKey(key)
|
||||
}
|
||||
return MarshalSm2EcryptedPrivateKey(key, pwd)
|
||||
}
|
||||
|
||||
func ReadPrivateKeyFromMem(data []byte, pwd []byte) (*PrivateKey, error) {
|
||||
var block *pem.Block
|
||||
|
||||
block, _ = pem.Decode(data)
|
||||
if block == nil {
|
||||
return nil, errors.New("failed to decode private key")
|
||||
}
|
||||
priv, err := ParsePKCS8PrivateKey(block.Bytes, pwd)
|
||||
return priv, err
|
||||
}
|
||||
|
||||
func ReadPrivateKeyFromPem(FileName string, pwd []byte) (*PrivateKey, error) {
|
||||
data, err := ioutil.ReadFile(FileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ReadPrivateKeyFromMem(data, pwd)
|
||||
}
|
||||
|
||||
func WritePrivateKeytoMem(key *PrivateKey, pwd []byte) ([]byte, error) {
|
||||
var block *pem.Block
|
||||
|
||||
der, err := MarshalSm2PrivateKey(key, pwd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if pwd != nil {
|
||||
block = &pem.Block{
|
||||
Type: "ENCRYPTED PRIVATE KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
} else {
|
||||
block = &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
}
|
||||
return pem.EncodeToMemory(block), nil
|
||||
}
|
||||
|
||||
func WritePrivateKeytoPem(FileName string, key *PrivateKey, pwd []byte) (bool, error) {
|
||||
var block *pem.Block
|
||||
|
||||
der, err := MarshalSm2PrivateKey(key, pwd)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if pwd != nil {
|
||||
block = &pem.Block{
|
||||
Type: "ENCRYPTED PRIVATE KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
} else {
|
||||
block = &pem.Block{
|
||||
Type: "PRIVATE KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
}
|
||||
file, err := os.Create(FileName)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
defer file.Close()
|
||||
err = pem.Encode(file, block)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func ReadPublicKeyFromMem(data []byte, _ []byte) (*PublicKey, error) {
|
||||
block, _ := pem.Decode(data)
|
||||
if block == nil || block.Type != "PUBLIC KEY" {
|
||||
return nil, errors.New("failed to decode public key")
|
||||
}
|
||||
pub, err := ParseSm2PublicKey(block.Bytes)
|
||||
return pub, err
|
||||
}
|
||||
|
||||
func ReadPublicKeyFromPem(FileName string, pwd []byte) (*PublicKey, error) {
|
||||
data, err := ioutil.ReadFile(FileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ReadPublicKeyFromMem(data, pwd)
|
||||
}
|
||||
|
||||
func WritePublicKeytoMem(key *PublicKey, _ []byte) ([]byte, error) {
|
||||
der, err := MarshalSm2PublicKey(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
block := &pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
return pem.EncodeToMemory(block), nil
|
||||
}
|
||||
|
||||
func WritePublicKeytoPem(FileName string, key *PublicKey, _ []byte) (bool, error) {
|
||||
der, err := MarshalSm2PublicKey(key)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
block := &pem.Block{
|
||||
Type: "PUBLIC KEY",
|
||||
Bytes: der,
|
||||
}
|
||||
file, err := os.Create(FileName)
|
||||
defer file.Close()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = pem.Encode(file, block)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
222
vendor/github.com/tjfoc/gmsm/sm2/sm2.go
generated
vendored
Normal file
222
vendor/github.com/tjfoc/gmsm/sm2/sm2.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
// reference to ecdsa
|
||||
import (
|
||||
"crypto"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"crypto/sha512"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type combinedMult interface {
|
||||
CombinedMult(bigX, bigY *big.Int, baseScalar, scalar []byte) (x, y *big.Int)
|
||||
}
|
||||
|
||||
const (
|
||||
aesIV = "IV for <SM2> CTR"
|
||||
)
|
||||
|
||||
type PublicKey struct {
|
||||
elliptic.Curve
|
||||
X, Y *big.Int
|
||||
}
|
||||
|
||||
type PrivateKey struct {
|
||||
PublicKey
|
||||
D *big.Int
|
||||
}
|
||||
|
||||
type sm2Signature struct {
|
||||
R, S *big.Int
|
||||
}
|
||||
|
||||
// The SM2's private key contains the public key
|
||||
func (priv *PrivateKey) Public() crypto.PublicKey {
|
||||
return &priv.PublicKey
|
||||
}
|
||||
|
||||
// sign format = 30 + len(z) + 02 + len(r) + r + 02 + len(s) + s, z being what follows its size, ie 02+len(r)+r+02+len(s)+s
|
||||
func (priv *PrivateKey) Sign(rand io.Reader, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
r, s, err := Sign(priv, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return asn1.Marshal(sm2Signature{r, s})
|
||||
}
|
||||
|
||||
func (pub *PublicKey) Verify(msg []byte, sign []byte) bool {
|
||||
var sm2Sign sm2Signature
|
||||
_, err := asn1.Unmarshal(sign, &sm2Sign)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return Verify(pub, msg, sm2Sign.R, sm2Sign.S)
|
||||
}
|
||||
|
||||
var one = new(big.Int).SetInt64(1)
|
||||
|
||||
func randFieldElement(c elliptic.Curve, rand io.Reader) (k *big.Int, err error) {
|
||||
params := c.Params()
|
||||
b := make([]byte, params.BitSize/8+8)
|
||||
_, err = io.ReadFull(rand, b)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
k = new(big.Int).SetBytes(b)
|
||||
n := new(big.Int).Sub(params.N, one)
|
||||
k.Mod(k, n)
|
||||
k.Add(k, one)
|
||||
return
|
||||
}
|
||||
|
||||
func GenerateKey() (*PrivateKey, error) {
|
||||
c := P256Sm2()
|
||||
k, err := randFieldElement(c, rand.Reader)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv := new(PrivateKey)
|
||||
priv.PublicKey.Curve = c
|
||||
priv.D = k
|
||||
priv.PublicKey.X, priv.PublicKey.Y = c.ScalarBaseMult(k.Bytes())
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
var errZeroParam = errors.New("zero parameter")
|
||||
|
||||
func Sign(priv *PrivateKey, hash []byte) (r, s *big.Int, err error) {
|
||||
entropylen := (priv.Curve.Params().BitSize + 7) / 16
|
||||
if entropylen > 32 {
|
||||
entropylen = 32
|
||||
}
|
||||
entropy := make([]byte, entropylen)
|
||||
_, err = io.ReadFull(rand.Reader, entropy)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Initialize an SHA-512 hash context; digest ...
|
||||
md := sha512.New()
|
||||
md.Write(priv.D.Bytes()) // the private key,
|
||||
md.Write(entropy) // the entropy,
|
||||
md.Write(hash) // and the input hash;
|
||||
key := md.Sum(nil)[:32] // and compute ChopMD-256(SHA-512),
|
||||
// which is an indifferentiable MAC.
|
||||
|
||||
// Create an AES-CTR instance to use as a CSPRNG.
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Create a CSPRNG that xors a stream of zeros with
|
||||
// the output of the AES-CTR instance.
|
||||
csprng := cipher.StreamReader{
|
||||
R: zeroReader,
|
||||
S: cipher.NewCTR(block, []byte(aesIV)),
|
||||
}
|
||||
|
||||
// See [NSA] 3.4.1
|
||||
c := priv.PublicKey.Curve
|
||||
N := c.Params().N
|
||||
if N.Sign() == 0 {
|
||||
return nil, nil, errZeroParam
|
||||
}
|
||||
var k *big.Int
|
||||
e := new(big.Int).SetBytes(hash)
|
||||
for { // 调整算法细节以实现SM2
|
||||
for {
|
||||
k, err = randFieldElement(c, csprng)
|
||||
if err != nil {
|
||||
r = nil
|
||||
return
|
||||
}
|
||||
r, _ = priv.Curve.ScalarBaseMult(k.Bytes())
|
||||
r.Add(r, e)
|
||||
r.Mod(r, N)
|
||||
if r.Sign() != 0 {
|
||||
break
|
||||
}
|
||||
if t := new(big.Int).Add(r, k); t.Cmp(N) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
rD := new(big.Int).Mul(priv.D, r)
|
||||
s = new(big.Int).Sub(k, rD)
|
||||
d1 := new(big.Int).Add(priv.D, one)
|
||||
d1Inv := new(big.Int).ModInverse(d1, N)
|
||||
s.Mul(s, d1Inv)
|
||||
s.Mod(s, N)
|
||||
if s.Sign() != 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func Verify(pub *PublicKey, hash []byte, r, s *big.Int) bool {
|
||||
c := pub.Curve
|
||||
N := c.Params().N
|
||||
|
||||
if r.Sign() <= 0 || s.Sign() <= 0 {
|
||||
return false
|
||||
}
|
||||
if r.Cmp(N) >= 0 || s.Cmp(N) >= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// 调整算法细节以实现SM2
|
||||
t := new(big.Int).Add(r, s)
|
||||
t.Mod(t, N)
|
||||
if N.Sign() == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var x *big.Int
|
||||
if opt, ok := c.(combinedMult); ok {
|
||||
x, _ = opt.CombinedMult(pub.X, pub.Y, s.Bytes(), t.Bytes())
|
||||
} else {
|
||||
x1, y1 := c.ScalarBaseMult(s.Bytes())
|
||||
x2, y2 := c.ScalarMult(pub.X, pub.Y, t.Bytes())
|
||||
x, _ = c.Add(x1, y1, x2, y2)
|
||||
}
|
||||
|
||||
e := new(big.Int).SetBytes(hash)
|
||||
x.Add(x, e)
|
||||
x.Mod(x, N)
|
||||
return x.Cmp(r) == 0
|
||||
}
|
||||
|
||||
type zr struct {
|
||||
io.Reader
|
||||
}
|
||||
|
||||
func (z *zr) Read(dst []byte) (n int, err error) {
|
||||
for i := range dst {
|
||||
dst[i] = 0
|
||||
}
|
||||
return len(dst), nil
|
||||
}
|
||||
|
||||
var zeroReader = &zr{}
|
184
vendor/github.com/tjfoc/gmsm/sm2/sm2_test.go
generated
vendored
Normal file
184
vendor/github.com/tjfoc/gmsm/sm2/sm2_test.go
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"net"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestSm2(t *testing.T) {
|
||||
priv, err := GenerateKey() // 生成密钥对
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ok, err := WritePrivateKeytoPem("priv.pem", priv, nil) // 生成密钥文件
|
||||
if ok != true {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pubKey, _ := priv.Public().(*PublicKey)
|
||||
ok, err = WritePublicKeytoPem("pub.pem", pubKey, nil) // 生成公钥文件
|
||||
if ok != true {
|
||||
log.Fatal(err)
|
||||
}
|
||||
msg := []byte("test")
|
||||
err = ioutil.WriteFile("ifile", msg, os.FileMode(0644)) // 生成测试文件
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
privKey, err := ReadPrivateKeyFromPem("priv.pem", nil) // 读取密钥
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
pubKey, err = ReadPublicKeyFromPem("pub.pem", nil) // 读取公钥
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
msg, _ = ioutil.ReadFile("ifile") // 从文件读取数据
|
||||
sign, err := privKey.Sign(rand.Reader, msg, nil) // 签名
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = ioutil.WriteFile("ofile", sign, os.FileMode(0644))
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
signdata, _ := ioutil.ReadFile("ofile")
|
||||
ok = privKey.Verify(msg, signdata) // 密钥验证
|
||||
if ok != true {
|
||||
fmt.Printf("Verify error\n")
|
||||
} else {
|
||||
fmt.Printf("Verify ok\n")
|
||||
}
|
||||
ok = pubKey.Verify(msg, signdata) // 公钥验证
|
||||
if ok != true {
|
||||
fmt.Printf("Verify error\n")
|
||||
} else {
|
||||
fmt.Printf("Verify ok\n")
|
||||
}
|
||||
templateReq := CertificateRequest{
|
||||
Subject: pkix.Name{
|
||||
CommonName: "test.example.com",
|
||||
Organization: []string{"Test"},
|
||||
},
|
||||
// SignatureAlgorithm: ECDSAWithSHA256,
|
||||
SignatureAlgorithm: SM2WithSM3,
|
||||
}
|
||||
_, err = CreateCertificateRequestToPem("req.pem", &templateReq, privKey)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
req, err := ReadCertificateRequestFromPem("req.pem")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
err = req.CheckSignature()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
fmt.Printf("CheckSignature ok\n")
|
||||
}
|
||||
testExtKeyUsage := []ExtKeyUsage{ExtKeyUsageClientAuth, ExtKeyUsageServerAuth}
|
||||
testUnknownExtKeyUsage := []asn1.ObjectIdentifier{[]int{1, 2, 3}, []int{2, 59, 1}}
|
||||
extraExtensionData := []byte("extra extension")
|
||||
commonName := "test.example.com"
|
||||
template := Certificate{
|
||||
// SerialNumber is negative to ensure that negative
|
||||
// values are parsed. This is due to the prevalence of
|
||||
// buggy code that produces certificates with negative
|
||||
// serial numbers.
|
||||
SerialNumber: big.NewInt(-1),
|
||||
Subject: pkix.Name{
|
||||
CommonName: commonName,
|
||||
Organization: []string{"TEST"},
|
||||
Country: []string{"China"},
|
||||
ExtraNames: []pkix.AttributeTypeAndValue{
|
||||
{
|
||||
Type: []int{2, 5, 4, 42},
|
||||
Value: "Gopher",
|
||||
},
|
||||
// This should override the Country, above.
|
||||
{
|
||||
Type: []int{2, 5, 4, 6},
|
||||
Value: "NL",
|
||||
},
|
||||
},
|
||||
},
|
||||
NotBefore: time.Unix(1000, 0),
|
||||
NotAfter: time.Unix(100000, 0),
|
||||
|
||||
// SignatureAlgorithm: ECDSAWithSHA256,
|
||||
SignatureAlgorithm: SM2WithSM3,
|
||||
|
||||
SubjectKeyId: []byte{1, 2, 3, 4},
|
||||
KeyUsage: KeyUsageCertSign,
|
||||
|
||||
ExtKeyUsage: testExtKeyUsage,
|
||||
UnknownExtKeyUsage: testUnknownExtKeyUsage,
|
||||
|
||||
BasicConstraintsValid: true,
|
||||
IsCA: true,
|
||||
|
||||
OCSPServer: []string{"http://ocsp.example.com"},
|
||||
IssuingCertificateURL: []string{"http://crt.example.com/ca1.crt"},
|
||||
|
||||
DNSNames: []string{"test.example.com"},
|
||||
EmailAddresses: []string{"gopher@golang.org"},
|
||||
IPAddresses: []net.IP{net.IPv4(127, 0, 0, 1).To4(), net.ParseIP("2001:4860:0:2001::68")},
|
||||
|
||||
PolicyIdentifiers: []asn1.ObjectIdentifier{[]int{1, 2, 3}},
|
||||
PermittedDNSDomains: []string{".example.com", "example.com"},
|
||||
|
||||
CRLDistributionPoints: []string{"http://crl1.example.com/ca1.crl", "http://crl2.example.com/ca1.crl"},
|
||||
|
||||
ExtraExtensions: []pkix.Extension{
|
||||
{
|
||||
Id: []int{1, 2, 3, 4},
|
||||
Value: extraExtensionData,
|
||||
},
|
||||
// This extension should override the SubjectKeyId, above.
|
||||
{
|
||||
Id: oidExtensionSubjectKeyId,
|
||||
Critical: false,
|
||||
Value: []byte{0x04, 0x04, 4, 3, 2, 1},
|
||||
},
|
||||
},
|
||||
}
|
||||
pubKey, _ = priv.Public().(*PublicKey)
|
||||
ok, _ = CreateCertificateToPem("cert.pem", &template, &template, pubKey, privKey)
|
||||
if ok != true {
|
||||
fmt.Printf("failed to create cert file\n")
|
||||
}
|
||||
cert, err := ReadCertificateFromPem("cert.pem")
|
||||
if err != nil {
|
||||
fmt.Printf("failed to read cert file")
|
||||
}
|
||||
err = cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
fmt.Printf("CheckSignature ok\n")
|
||||
}
|
||||
}
|
568
vendor/github.com/tjfoc/gmsm/sm2/verify.go
generated
vendored
Normal file
568
vendor/github.com/tjfoc/gmsm/sm2/verify.go
generated
vendored
Normal file
@@ -0,0 +1,568 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm2
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type InvalidReason int
|
||||
|
||||
const (
|
||||
// NotAuthorizedToSign results when a certificate is signed by another
|
||||
// which isn't marked as a CA certificate.
|
||||
NotAuthorizedToSign InvalidReason = iota
|
||||
// Expired results when a certificate has expired, based on the time
|
||||
// given in the VerifyOptions.
|
||||
Expired
|
||||
// CANotAuthorizedForThisName results when an intermediate or root
|
||||
// certificate has a name constraint which doesn't include the name
|
||||
// being checked.
|
||||
CANotAuthorizedForThisName
|
||||
// TooManyIntermediates results when a path length constraint is
|
||||
// violated.
|
||||
TooManyIntermediates
|
||||
// IncompatibleUsage results when the certificate's key usage indicates
|
||||
// that it may only be used for a different purpose.
|
||||
IncompatibleUsage
|
||||
// NameMismatch results when the subject name of a parent certificate
|
||||
// does not match the issuer name in the child.
|
||||
NameMismatch
|
||||
)
|
||||
|
||||
// CertificateInvalidError results when an odd error occurs. Users of this
|
||||
// library probably want to handle all these errors uniformly.
|
||||
type CertificateInvalidError struct {
|
||||
Cert *Certificate
|
||||
Reason InvalidReason
|
||||
}
|
||||
|
||||
func (e CertificateInvalidError) Error() string {
|
||||
switch e.Reason {
|
||||
case NotAuthorizedToSign:
|
||||
return "x509: certificate is not authorized to sign other certificates"
|
||||
case Expired:
|
||||
return "x509: certificate has expired or is not yet valid"
|
||||
case CANotAuthorizedForThisName:
|
||||
return "x509: a root or intermediate certificate is not authorized to sign in this domain"
|
||||
case TooManyIntermediates:
|
||||
return "x509: too many intermediates for path length constraint"
|
||||
case IncompatibleUsage:
|
||||
return "x509: certificate specifies an incompatible key usage"
|
||||
case NameMismatch:
|
||||
return "x509: issuer name does not match subject from issuing certificate"
|
||||
}
|
||||
return "x509: unknown error"
|
||||
}
|
||||
|
||||
// HostnameError results when the set of authorized names doesn't match the
|
||||
// requested name.
|
||||
type HostnameError struct {
|
||||
Certificate *Certificate
|
||||
Host string
|
||||
}
|
||||
|
||||
func (h HostnameError) Error() string {
|
||||
c := h.Certificate
|
||||
|
||||
var valid string
|
||||
if ip := net.ParseIP(h.Host); ip != nil {
|
||||
// Trying to validate an IP
|
||||
if len(c.IPAddresses) == 0 {
|
||||
return "x509: cannot validate certificate for " + h.Host + " because it doesn't contain any IP SANs"
|
||||
}
|
||||
for _, san := range c.IPAddresses {
|
||||
if len(valid) > 0 {
|
||||
valid += ", "
|
||||
}
|
||||
valid += san.String()
|
||||
}
|
||||
} else {
|
||||
if len(c.DNSNames) > 0 {
|
||||
valid = strings.Join(c.DNSNames, ", ")
|
||||
} else {
|
||||
valid = c.Subject.CommonName
|
||||
}
|
||||
}
|
||||
|
||||
if len(valid) == 0 {
|
||||
return "x509: certificate is not valid for any names, but wanted to match " + h.Host
|
||||
}
|
||||
return "x509: certificate is valid for " + valid + ", not " + h.Host
|
||||
}
|
||||
|
||||
// UnknownAuthorityError results when the certificate issuer is unknown
|
||||
type UnknownAuthorityError struct {
|
||||
Cert *Certificate
|
||||
// hintErr contains an error that may be helpful in determining why an
|
||||
// authority wasn't found.
|
||||
hintErr error
|
||||
// hintCert contains a possible authority certificate that was rejected
|
||||
// because of the error in hintErr.
|
||||
hintCert *Certificate
|
||||
}
|
||||
|
||||
func (e UnknownAuthorityError) Error() string {
|
||||
s := "x509: certificate signed by unknown authority"
|
||||
if e.hintErr != nil {
|
||||
certName := e.hintCert.Subject.CommonName
|
||||
if len(certName) == 0 {
|
||||
if len(e.hintCert.Subject.Organization) > 0 {
|
||||
certName = e.hintCert.Subject.Organization[0]
|
||||
} else {
|
||||
certName = "serial:" + e.hintCert.SerialNumber.String()
|
||||
}
|
||||
}
|
||||
s += fmt.Sprintf(" (possibly because of %q while trying to verify candidate authority certificate %q)", e.hintErr, certName)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// SystemRootsError results when we fail to load the system root certificates.
|
||||
type SystemRootsError struct {
|
||||
Err error
|
||||
}
|
||||
|
||||
func (se SystemRootsError) Error() string {
|
||||
msg := "x509: failed to load system roots and no roots provided"
|
||||
if se.Err != nil {
|
||||
return msg + "; " + se.Err.Error()
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// errNotParsed is returned when a certificate without ASN.1 contents is
|
||||
// verified. Platform-specific verification needs the ASN.1 contents.
|
||||
var errNotParsed = errors.New("x509: missing ASN.1 contents; use ParseCertificate")
|
||||
|
||||
// VerifyOptions contains parameters for Certificate.Verify. It's a structure
|
||||
// because other PKIX verification APIs have ended up needing many options.
|
||||
type VerifyOptions struct {
|
||||
DNSName string
|
||||
Intermediates *CertPool
|
||||
Roots *CertPool // if nil, the system roots are used
|
||||
CurrentTime time.Time // if zero, the current time is used
|
||||
// KeyUsage specifies which Extended Key Usage values are acceptable.
|
||||
// An empty list means ExtKeyUsageServerAuth. Key usage is considered a
|
||||
// constraint down the chain which mirrors Windows CryptoAPI behavior,
|
||||
// but not the spec. To accept any key usage, include ExtKeyUsageAny.
|
||||
KeyUsages []ExtKeyUsage
|
||||
}
|
||||
|
||||
const (
|
||||
leafCertificate = iota
|
||||
intermediateCertificate
|
||||
rootCertificate
|
||||
)
|
||||
|
||||
func matchNameConstraint(domain, constraint string) bool {
|
||||
// The meaning of zero length constraints is not specified, but this
|
||||
// code follows NSS and accepts them as valid for everything.
|
||||
if len(constraint) == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
if len(domain) < len(constraint) {
|
||||
return false
|
||||
}
|
||||
|
||||
prefixLen := len(domain) - len(constraint)
|
||||
if !strings.EqualFold(domain[prefixLen:], constraint) {
|
||||
return false
|
||||
}
|
||||
|
||||
if prefixLen == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
isSubdomain := domain[prefixLen-1] == '.'
|
||||
constraintHasLeadingDot := constraint[0] == '.'
|
||||
return isSubdomain != constraintHasLeadingDot
|
||||
}
|
||||
|
||||
// isValid performs validity checks on the c.
|
||||
func (c *Certificate) isValid(certType int, currentChain []*Certificate, opts *VerifyOptions) error {
|
||||
if len(currentChain) > 0 {
|
||||
child := currentChain[len(currentChain)-1]
|
||||
if !bytes.Equal(child.RawIssuer, c.RawSubject) {
|
||||
return CertificateInvalidError{c, NameMismatch}
|
||||
}
|
||||
}
|
||||
now := opts.CurrentTime
|
||||
if now.IsZero() {
|
||||
now = time.Now()
|
||||
}
|
||||
if now.Before(c.NotBefore) || now.After(c.NotAfter) {
|
||||
return CertificateInvalidError{c, Expired}
|
||||
}
|
||||
if len(c.PermittedDNSDomains) > 0 {
|
||||
ok := false
|
||||
for _, constraint := range c.PermittedDNSDomains {
|
||||
ok = matchNameConstraint(opts.DNSName, constraint)
|
||||
if ok {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !ok {
|
||||
return CertificateInvalidError{c, CANotAuthorizedForThisName}
|
||||
}
|
||||
}
|
||||
|
||||
// KeyUsage status flags are ignored. From Engineering Security, Peter
|
||||
// Gutmann: A European government CA marked its signing certificates as
|
||||
// being valid for encryption only, but no-one noticed. Another
|
||||
// European CA marked its signature keys as not being valid for
|
||||
// signatures. A different CA marked its own trusted root certificate
|
||||
// as being invalid for certificate signing. Another national CA
|
||||
// distributed a certificate to be used to encrypt data for the
|
||||
// country’s tax authority that was marked as only being usable for
|
||||
// digital signatures but not for encryption. Yet another CA reversed
|
||||
// the order of the bit flags in the keyUsage due to confusion over
|
||||
// encoding endianness, essentially setting a random keyUsage in
|
||||
// certificates that it issued. Another CA created a self-invalidating
|
||||
// certificate by adding a certificate policy statement stipulating
|
||||
// that the certificate had to be used strictly as specified in the
|
||||
// keyUsage, and a keyUsage containing a flag indicating that the RSA
|
||||
// encryption key could only be used for Diffie-Hellman key agreement.
|
||||
|
||||
if certType == intermediateCertificate && (!c.BasicConstraintsValid || !c.IsCA) {
|
||||
return CertificateInvalidError{c, NotAuthorizedToSign}
|
||||
}
|
||||
|
||||
if c.BasicConstraintsValid && c.MaxPathLen >= 0 {
|
||||
numIntermediates := len(currentChain) - 1
|
||||
if numIntermediates > c.MaxPathLen {
|
||||
return CertificateInvalidError{c, TooManyIntermediates}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify attempts to verify c by building one or more chains from c to a
|
||||
// certificate in opts.Roots, using certificates in opts.Intermediates if
|
||||
// needed. If successful, it returns one or more chains where the first
|
||||
// element of the chain is c and the last element is from opts.Roots.
|
||||
//
|
||||
// If opts.Roots is nil and system roots are unavailable the returned error
|
||||
// will be of type SystemRootsError.
|
||||
//
|
||||
// WARNING: this doesn't do any revocation checking.
|
||||
func (c *Certificate) Verify(opts VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
// Platform-specific verification needs the ASN.1 contents so
|
||||
// this makes the behavior consistent across platforms.
|
||||
if len(c.Raw) == 0 {
|
||||
return nil, errNotParsed
|
||||
}
|
||||
if opts.Intermediates != nil {
|
||||
for _, intermediate := range opts.Intermediates.certs {
|
||||
if len(intermediate.Raw) == 0 {
|
||||
return nil, errNotParsed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Use Windows's own verification and chain building.
|
||||
if opts.Roots == nil && runtime.GOOS == "windows" {
|
||||
return c.systemVerify(&opts)
|
||||
}
|
||||
|
||||
if len(c.UnhandledCriticalExtensions) > 0 {
|
||||
return nil, UnhandledCriticalExtension{}
|
||||
}
|
||||
|
||||
if opts.Roots == nil {
|
||||
opts.Roots = systemRootsPool()
|
||||
if opts.Roots == nil {
|
||||
return nil, SystemRootsError{systemRootsErr}
|
||||
}
|
||||
}
|
||||
|
||||
err = c.isValid(leafCertificate, nil, &opts)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(opts.DNSName) > 0 {
|
||||
err = c.VerifyHostname(opts.DNSName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
var candidateChains [][]*Certificate
|
||||
if opts.Roots.contains(c) {
|
||||
candidateChains = append(candidateChains, []*Certificate{c})
|
||||
} else {
|
||||
if candidateChains, err = c.buildChains(make(map[int][][]*Certificate), []*Certificate{c}, &opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
keyUsages := opts.KeyUsages
|
||||
if len(keyUsages) == 0 {
|
||||
keyUsages = []ExtKeyUsage{ExtKeyUsageServerAuth}
|
||||
}
|
||||
|
||||
// If any key usage is acceptable then we're done.
|
||||
for _, usage := range keyUsages {
|
||||
if usage == ExtKeyUsageAny {
|
||||
chains = candidateChains
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
for _, candidate := range candidateChains {
|
||||
if checkChainForKeyUsage(candidate, keyUsages) {
|
||||
chains = append(chains, candidate)
|
||||
}
|
||||
}
|
||||
|
||||
if len(chains) == 0 {
|
||||
err = CertificateInvalidError{c, IncompatibleUsage}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func appendToFreshChain(chain []*Certificate, cert *Certificate) []*Certificate {
|
||||
n := make([]*Certificate, len(chain)+1)
|
||||
copy(n, chain)
|
||||
n[len(chain)] = cert
|
||||
return n
|
||||
}
|
||||
|
||||
func (c *Certificate) buildChains(cache map[int][][]*Certificate, currentChain []*Certificate, opts *VerifyOptions) (chains [][]*Certificate, err error) {
|
||||
possibleRoots, failedRoot, rootErr := opts.Roots.findVerifiedParents(c)
|
||||
nextRoot:
|
||||
for _, rootNum := range possibleRoots {
|
||||
root := opts.Roots.certs[rootNum]
|
||||
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(root) {
|
||||
continue nextRoot
|
||||
}
|
||||
}
|
||||
|
||||
err = root.isValid(rootCertificate, currentChain, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
chains = append(chains, appendToFreshChain(currentChain, root))
|
||||
}
|
||||
|
||||
possibleIntermediates, failedIntermediate, intermediateErr := opts.Intermediates.findVerifiedParents(c)
|
||||
nextIntermediate:
|
||||
for _, intermediateNum := range possibleIntermediates {
|
||||
intermediate := opts.Intermediates.certs[intermediateNum]
|
||||
for _, cert := range currentChain {
|
||||
if cert.Equal(intermediate) {
|
||||
continue nextIntermediate
|
||||
}
|
||||
}
|
||||
err = intermediate.isValid(intermediateCertificate, currentChain, opts)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
var childChains [][]*Certificate
|
||||
childChains, ok := cache[intermediateNum]
|
||||
if !ok {
|
||||
childChains, err = intermediate.buildChains(cache, appendToFreshChain(currentChain, intermediate), opts)
|
||||
cache[intermediateNum] = childChains
|
||||
}
|
||||
chains = append(chains, childChains...)
|
||||
}
|
||||
|
||||
if len(chains) > 0 {
|
||||
err = nil
|
||||
}
|
||||
|
||||
if len(chains) == 0 && err == nil {
|
||||
hintErr := rootErr
|
||||
hintCert := failedRoot
|
||||
if hintErr == nil {
|
||||
hintErr = intermediateErr
|
||||
hintCert = failedIntermediate
|
||||
}
|
||||
err = UnknownAuthorityError{c, hintErr, hintCert}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func matchHostnames(pattern, host string) bool {
|
||||
host = strings.TrimSuffix(host, ".")
|
||||
pattern = strings.TrimSuffix(pattern, ".")
|
||||
|
||||
if len(pattern) == 0 || len(host) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
patternParts := strings.Split(pattern, ".")
|
||||
hostParts := strings.Split(host, ".")
|
||||
|
||||
if len(patternParts) != len(hostParts) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i, patternPart := range patternParts {
|
||||
if i == 0 && patternPart == "*" {
|
||||
continue
|
||||
}
|
||||
if patternPart != hostParts[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// toLowerCaseASCII returns a lower-case version of in. See RFC 6125 6.4.1. We use
|
||||
// an explicitly ASCII function to avoid any sharp corners resulting from
|
||||
// performing Unicode operations on DNS labels.
|
||||
func toLowerCaseASCII(in string) string {
|
||||
// If the string is already lower-case then there's nothing to do.
|
||||
isAlreadyLowerCase := true
|
||||
for _, c := range in {
|
||||
if c == utf8.RuneError {
|
||||
// If we get a UTF-8 error then there might be
|
||||
// upper-case ASCII bytes in the invalid sequence.
|
||||
isAlreadyLowerCase = false
|
||||
break
|
||||
}
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
isAlreadyLowerCase = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if isAlreadyLowerCase {
|
||||
return in
|
||||
}
|
||||
|
||||
out := []byte(in)
|
||||
for i, c := range out {
|
||||
if 'A' <= c && c <= 'Z' {
|
||||
out[i] += 'a' - 'A'
|
||||
}
|
||||
}
|
||||
return string(out)
|
||||
}
|
||||
|
||||
// VerifyHostname returns nil if c is a valid certificate for the named host.
|
||||
// Otherwise it returns an error describing the mismatch.
|
||||
func (c *Certificate) VerifyHostname(h string) error {
|
||||
// IP addresses may be written in [ ].
|
||||
candidateIP := h
|
||||
if len(h) >= 3 && h[0] == '[' && h[len(h)-1] == ']' {
|
||||
candidateIP = h[1 : len(h)-1]
|
||||
}
|
||||
if ip := net.ParseIP(candidateIP); ip != nil {
|
||||
// We only match IP addresses against IP SANs.
|
||||
// https://tools.ietf.org/html/rfc6125#appendix-B.2
|
||||
for _, candidate := range c.IPAddresses {
|
||||
if ip.Equal(candidate) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return HostnameError{c, candidateIP}
|
||||
}
|
||||
|
||||
lowered := toLowerCaseASCII(h)
|
||||
|
||||
if len(c.DNSNames) > 0 {
|
||||
for _, match := range c.DNSNames {
|
||||
if matchHostnames(toLowerCaseASCII(match), lowered) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
// If Subject Alt Name is given, we ignore the common name.
|
||||
} else if matchHostnames(toLowerCaseASCII(c.Subject.CommonName), lowered) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return HostnameError{c, h}
|
||||
}
|
||||
|
||||
func checkChainForKeyUsage(chain []*Certificate, keyUsages []ExtKeyUsage) bool {
|
||||
usages := make([]ExtKeyUsage, len(keyUsages))
|
||||
copy(usages, keyUsages)
|
||||
|
||||
if len(chain) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
usagesRemaining := len(usages)
|
||||
|
||||
// We walk down the list and cross out any usages that aren't supported
|
||||
// by each certificate. If we cross out all the usages, then the chain
|
||||
// is unacceptable.
|
||||
|
||||
NextCert:
|
||||
for i := len(chain) - 1; i >= 0; i-- {
|
||||
cert := chain[i]
|
||||
if len(cert.ExtKeyUsage) == 0 && len(cert.UnknownExtKeyUsage) == 0 {
|
||||
// The certificate doesn't have any extended key usage specified.
|
||||
continue
|
||||
}
|
||||
|
||||
for _, usage := range cert.ExtKeyUsage {
|
||||
if usage == ExtKeyUsageAny {
|
||||
// The certificate is explicitly good for any usage.
|
||||
continue NextCert
|
||||
}
|
||||
}
|
||||
|
||||
const invalidUsage ExtKeyUsage = -1
|
||||
|
||||
NextRequestedUsage:
|
||||
for i, requestedUsage := range usages {
|
||||
if requestedUsage == invalidUsage {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, usage := range cert.ExtKeyUsage {
|
||||
if requestedUsage == usage {
|
||||
continue NextRequestedUsage
|
||||
} else if requestedUsage == ExtKeyUsageServerAuth &&
|
||||
(usage == ExtKeyUsageNetscapeServerGatedCrypto ||
|
||||
usage == ExtKeyUsageMicrosoftServerGatedCrypto) {
|
||||
// In order to support COMODO
|
||||
// certificate chains, we have to
|
||||
// accept Netscape or Microsoft SGC
|
||||
// usages as equal to ServerAuth.
|
||||
continue NextRequestedUsage
|
||||
}
|
||||
}
|
||||
|
||||
usages[i] = invalidUsage
|
||||
usagesRemaining--
|
||||
if usagesRemaining == 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
2526
vendor/github.com/tjfoc/gmsm/sm2/x509.go
generated
vendored
Normal file
2526
vendor/github.com/tjfoc/gmsm/sm2/x509.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
vendor/github.com/tjfoc/gmsm/sm3/ifile
generated
vendored
Normal file
1
vendor/github.com/tjfoc/gmsm/sm3/ifile
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
test
|
207
vendor/github.com/tjfoc/gmsm/sm3/sm3.go
generated
vendored
Normal file
207
vendor/github.com/tjfoc/gmsm/sm3/sm3.go
generated
vendored
Normal file
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm3
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"hash"
|
||||
)
|
||||
|
||||
type SM3 struct {
|
||||
digest [8]uint32 // digest represents the partial evaluation of V
|
||||
length uint64 // length of the message
|
||||
unhandleMsg []byte // uint8 //
|
||||
}
|
||||
|
||||
func (sm3 *SM3) ff0(x, y, z uint32) uint32 { return x ^ y ^ z }
|
||||
|
||||
func (sm3 *SM3) ff1(x, y, z uint32) uint32 { return (x & y) | (x & z) | (y & z) }
|
||||
|
||||
func (sm3 *SM3) gg0(x, y, z uint32) uint32 { return x ^ y ^ z }
|
||||
|
||||
func (sm3 *SM3) gg1(x, y, z uint32) uint32 { return (x & y) | (^x & z) }
|
||||
|
||||
func (sm3 *SM3) p0(x uint32) uint32 { return x ^ sm3.leftRotate(x, 9) ^ sm3.leftRotate(x, 17) }
|
||||
|
||||
func (sm3 *SM3) p1(x uint32) uint32 { return x ^ sm3.leftRotate(x, 15) ^ sm3.leftRotate(x, 23) }
|
||||
|
||||
func (sm3 *SM3) leftRotate(x uint32, i uint32) uint32 { return (x<<(i%32) | x>>(32-i%32)) }
|
||||
|
||||
func (sm3 *SM3) pad() []byte {
|
||||
msg := sm3.unhandleMsg
|
||||
msg = append(msg, 0x80) // Append '1'
|
||||
blockSize := 64 // Append until the resulting message length (in bits) is congruent to 448 (mod 512)
|
||||
for len(msg)%blockSize != 56 {
|
||||
msg = append(msg, 0x00)
|
||||
}
|
||||
// append message length
|
||||
msg = append(msg, uint8(sm3.length>>56&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>48&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>40&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>32&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>24&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>16&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>8&0xff))
|
||||
msg = append(msg, uint8(sm3.length>>0&0xff))
|
||||
|
||||
if len(msg)%64 != 0 {
|
||||
panic("------SM3 Pad: error msgLen =")
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func (sm3 *SM3) update(msg []byte, nblocks int) {
|
||||
var w [68]uint32
|
||||
var w1 [64]uint32
|
||||
|
||||
a, b, c, d, e, f, g, h := sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7]
|
||||
for len(msg) >= 64 {
|
||||
for i := 0; i < 16; i++ {
|
||||
w[i] = binary.BigEndian.Uint32(msg[4*i : 4*(i+1)])
|
||||
}
|
||||
for i := 16; i < 68; i++ {
|
||||
w[i] = sm3.p1(w[i-16]^w[i-9]^sm3.leftRotate(w[i-3], 15)) ^ sm3.leftRotate(w[i-13], 7) ^ w[i-6]
|
||||
}
|
||||
for i := 0; i < 64; i++ {
|
||||
w1[i] = w[i] ^ w[i+4]
|
||||
}
|
||||
A, B, C, D, E, F, G, H := a, b, c, d, e, f, g, h
|
||||
for i := 0; i < 16; i++ {
|
||||
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x79cc4519, uint32(i)), 7)
|
||||
SS2 := SS1 ^ sm3.leftRotate(A, 12)
|
||||
TT1 := sm3.ff0(A, B, C) + D + SS2 + w1[i]
|
||||
TT2 := sm3.gg0(E, F, G) + H + SS1 + w[i]
|
||||
D = C
|
||||
C = sm3.leftRotate(B, 9)
|
||||
B = A
|
||||
A = TT1
|
||||
H = G
|
||||
G = sm3.leftRotate(F, 19)
|
||||
F = E
|
||||
E = sm3.p0(TT2)
|
||||
}
|
||||
for i := 16; i < 64; i++ {
|
||||
SS1 := sm3.leftRotate(sm3.leftRotate(A, 12)+E+sm3.leftRotate(0x7a879d8a, uint32(i)), 7)
|
||||
SS2 := SS1 ^ sm3.leftRotate(A, 12)
|
||||
TT1 := sm3.ff1(A, B, C) + D + SS2 + w1[i]
|
||||
TT2 := sm3.gg1(E, F, G) + H + SS1 + w[i]
|
||||
D = C
|
||||
C = sm3.leftRotate(B, 9)
|
||||
B = A
|
||||
A = TT1
|
||||
H = G
|
||||
G = sm3.leftRotate(F, 19)
|
||||
F = E
|
||||
E = sm3.p0(TT2)
|
||||
}
|
||||
a ^= A
|
||||
b ^= B
|
||||
c ^= C
|
||||
d ^= D
|
||||
e ^= E
|
||||
f ^= F
|
||||
g ^= G
|
||||
h ^= H
|
||||
msg = msg[64:]
|
||||
}
|
||||
sm3.digest[0], sm3.digest[1], sm3.digest[2], sm3.digest[3], sm3.digest[4], sm3.digest[5], sm3.digest[6], sm3.digest[7] = a, b, c, d, e, f, g, h
|
||||
}
|
||||
|
||||
func New() hash.Hash {
|
||||
var sm3 SM3
|
||||
|
||||
sm3.Reset()
|
||||
return &sm3
|
||||
}
|
||||
|
||||
// BlockSize, required by the hash.Hash interface.
|
||||
// BlockSize returns the hash's underlying block size.
|
||||
// The Write method must be able to accept any amount
|
||||
// of data, but it may operate more efficiently if all writes
|
||||
// are a multiple of the block size.
|
||||
func (sm3 *SM3) BlockSize() int { return 64 }
|
||||
|
||||
// Size, required by the hash.Hash interface.
|
||||
// Size returns the number of bytes Sum will return.
|
||||
func (sm3 *SM3) Size() int { return 32 }
|
||||
|
||||
// Reset clears the internal state by zeroing bytes in the state buffer.
|
||||
// This can be skipped for a newly-created hash state; the default zero-allocated state is correct.
|
||||
func (sm3 *SM3) Reset() {
|
||||
// Reset digest
|
||||
sm3.digest[0] = 0x7380166f
|
||||
sm3.digest[1] = 0x4914b2b9
|
||||
sm3.digest[2] = 0x172442d7
|
||||
sm3.digest[3] = 0xda8a0600
|
||||
sm3.digest[4] = 0xa96f30bc
|
||||
sm3.digest[5] = 0x163138aa
|
||||
sm3.digest[6] = 0xe38dee4d
|
||||
sm3.digest[7] = 0xb0fb0e4e
|
||||
|
||||
sm3.length = 0 // Reset numberic states
|
||||
sm3.unhandleMsg = []byte{}
|
||||
}
|
||||
|
||||
// Write, required by the hash.Hash interface.
|
||||
// Write (via the embedded io.Writer interface) adds more data to the running hash.
|
||||
// It never returns an error.
|
||||
func (sm3 *SM3) Write(p []byte) (int, error) {
|
||||
toWrite := len(p)
|
||||
sm3.length += uint64(len(p) * 8)
|
||||
|
||||
msg := append(sm3.unhandleMsg, p...)
|
||||
nblocks := len(msg) / sm3.BlockSize()
|
||||
sm3.update(msg, nblocks)
|
||||
|
||||
// Update unhandleMsg
|
||||
sm3.unhandleMsg = msg[nblocks*sm3.BlockSize():]
|
||||
|
||||
return toWrite, nil
|
||||
}
|
||||
|
||||
// Sum, required by the hash.Hash interface.
|
||||
// Sum appends the current hash to b and returns the resulting slice.
|
||||
// It does not change the underlying hash state.
|
||||
func (sm3 *SM3) Sum(in []byte) []byte {
|
||||
sm3.Write(in)
|
||||
msg := sm3.pad()
|
||||
|
||||
// Finialize
|
||||
sm3.update(msg, len(msg)/sm3.BlockSize())
|
||||
|
||||
// save hash to in
|
||||
needed := sm3.Size()
|
||||
if cap(in)-len(in) < needed {
|
||||
newIn := make([]byte, len(in), len(in)+needed)
|
||||
copy(newIn, in)
|
||||
in = newIn
|
||||
}
|
||||
out := in[len(in) : len(in)+needed]
|
||||
|
||||
for i := 0; i < 8; i++ {
|
||||
binary.BigEndian.PutUint32(out[i*4:], sm3.digest[i])
|
||||
}
|
||||
return out
|
||||
|
||||
}
|
||||
|
||||
func Sm3Sum(data []byte) []byte {
|
||||
var sm3 SM3
|
||||
|
||||
sm3.Reset()
|
||||
sm3.Write(data)
|
||||
return sm3.Sum(nil)
|
||||
}
|
63
vendor/github.com/tjfoc/gmsm/sm3/sm3_test.go
generated
vendored
Normal file
63
vendor/github.com/tjfoc/gmsm/sm3/sm3_test.go
generated
vendored
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func byteToString(b []byte) string {
|
||||
ret := ""
|
||||
for i := 0; i < len(b); i++ {
|
||||
ret += fmt.Sprintf("%02x", b[i])
|
||||
}
|
||||
return ret
|
||||
}
|
||||
func TestSm3(t *testing.T) {
|
||||
msg := []byte("test")
|
||||
err := ioutil.WriteFile("ifile", msg, os.FileMode(0644)) // 生成测试文件
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
msg, err = ioutil.ReadFile("ifile")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
hw := New()
|
||||
hw.Write(msg)
|
||||
hash := hw.Sum(nil)
|
||||
fmt.Println(hash)
|
||||
fmt.Printf("%s\n", byteToString(hash))
|
||||
hash1 := Sm3Sum(msg)
|
||||
fmt.Println(hash1)
|
||||
fmt.Printf("%s\n", byteToString(hash1))
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkSm3(t *testing.B) {
|
||||
t.ReportAllocs()
|
||||
msg := []byte("test")
|
||||
hw := New()
|
||||
for i := 0; i < t.N; i++ {
|
||||
|
||||
hw.Sum(nil)
|
||||
Sm3Sum(msg)
|
||||
}
|
||||
}
|
67
vendor/github.com/tjfoc/gmsm/sm4/sm4_test.go
generated
vendored
Normal file
67
vendor/github.com/tjfoc/gmsm/sm4/sm4_test.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package sm4
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSM4(t *testing.T) {
|
||||
key := []byte("1234567890abcdef")
|
||||
fmt.Printf("key = %v\n", key)
|
||||
data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
|
||||
WriteKeyToPem("key.pem", key, nil)
|
||||
key, err := ReadKeyFromPem("key.pem", nil)
|
||||
fmt.Printf("key = %v\n", key)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("data = %x\n", data)
|
||||
c, err := NewCipher(key)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
d0 := make([]byte, 16)
|
||||
c.Encrypt(d0, data)
|
||||
fmt.Printf("d0 = %x\n", d0)
|
||||
d1 := make([]byte, 16)
|
||||
c.Decrypt(d1, d0)
|
||||
fmt.Printf("d1 = %x\n", d1)
|
||||
}
|
||||
|
||||
func BenchmarkSM4(t *testing.B) {
|
||||
t.ReportAllocs()
|
||||
key := []byte("1234567890abcdef")
|
||||
data := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
|
||||
WriteKeyToPem("key.pem", key, nil)
|
||||
key, err := ReadKeyFromPem("key.pem", nil)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
c, err := NewCipher(key)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for i := 0; i < t.N; i++ {
|
||||
d0 := make([]byte, 16)
|
||||
c.Encrypt(d0, data)
|
||||
d1 := make([]byte, 16)
|
||||
c.Decrypt(d1, d0)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user