Git Product home page Git Product logo

gmsm's Introduction

gmsm

GM SM2/3/4 library based on Golang

Build Status

Feature

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)

Communication

tjfoc国密交流

Join the chat at https://gitter.im/tjfoc/gmsm

  • 如果你对国密算法开源技术及应用感兴趣,欢迎添加“苏州同济区块链研究院·小助手“微信,回复“国密算法进群”,加入“同济区块链国密算法交流群”。微信二维码如下:
    微信二维码

  • 发送邮件到[email protected]

License

版权所有 苏州同济区块链研究院有限公司(http://www.wutongchain.com/)

Copyright 2017- Suzhou Tongji Fintech Research Institute. 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's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gmsm's Issues

MarshalSm2PrivateKey打包后ParseSm2PrivateKey不能解包的问题

package main

import (
	"fmt"

	"github.com/tjfoc/gmsm/sm2"
)

func main() {
	priv, err := sm2.GenerateKey()
	if err != nil {
		fmt.Println(err)
		return
	}

	vk, err := sm2.MarshalSm2PrivateKey(priv, nil)
	if err != nil {
		fmt.Println(err)
		return
	}

	priv2, err := sm2.ParseSm2PrivateKey(vk)
	if err != nil {
		fmt.Println(err)
		return
	}
	fmt.Println(priv2)
}

x509: failed to parse SM2 private key: asn1: structure error: tags don't match (4 vs {class:0 tag:16 length:19 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue: tag: stringType:0 timeType:0 set:false omitEmpty:false} @5

go version go1.14 linux/amd64

SigtoPub

国密签名和ECDSA签名都需要临时公钥,ecdsa 签名是r=x1mod/n,国密的r=(h+x1)modn,ecdsa可以恢复公钥,国密理论上是不是也可以推导啊

在gmsm/sm2/x509.go main分支func checkSignature的问题

如题 x509.go 998 行,switch pub := publicKey.(type) 中为什么没有sm2.PulicKey的case?
但是在其他地方,如func signingParamsForPublicKey中switch pub := publicKey.(type),却有
sm2.PulicKey的case。

请问这个是基于什么特殊原因考虑的吗?

sm2 PrivateKey.Sign 传入的随机源无效

在 PrivateKey.Sign中调用了Sm2Sign 此过程中传入随机源被丢弃。此处应考虑把随机源传递到运算中。因为在工程中有可能不用go语言默认的随机源。(代码 sm2.go 80行)

sigtoPub

国密能根据签名和哈希推算出公钥吗

sm2 encryption and decryption instability

msgstr := "**"
msg := []byte(msgstr)
for i := 1; i <= 1000; i++ {
privKey, err := sm2.ReadPrivateKeyFromMem([]byte(-----BEGIN PRIVATE KEY----- MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgUhKrlwICnCHri8+a XO8Esc1fUizoelJ3J6qd6NqCru2gCgYIKoEcz1UBgi2hRANCAATk2/Kd3pwAFVYP Fqf7KvJmgJZYx1wZE7jgchIzBElYeMv+H0rQXKshnHCXTbM/55Yy+oAJq8QjJHKB ricYci06 -----END PRIVATE KEY-----), nil) // 读取密钥
if err != nil {
log.Fatal(err)
}

	pubKey, err := sm2.ReadPublicKeyFromMem([]byte(`-----BEGIN PUBLIC KEY-----

MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE5Nvynd6cABVWDxan+yryZoCWWMdc
GRO44HISMwRJWHjL/h9K0FyrIZxwl02zP+eWMvqACavEIyRyga4nGHItOg==
-----END PUBLIC KEY-----`), nil)
if err != nil {
log.Fatal(err)
}
d0, err := pubKey.Encrypt(msg)
if err != nil {
fmt.Printf("Error: failed to encrypt %s: %v\n", msg, err)
return
}

	_, err = privKey.Decrypt(d0)
	if err != nil {
		fmt.Printf("Error: failed to decrypt: %v\n", err)
	}

}

1000 executions may have 3 to 5 decryption failures

Sm2Sign bugs

package sm2,Sm2Sign function returns two bigInt(r,s),while combine the bytes of r and s,the total length of bytes array is 63 randomly,leading to signature verify failed,wish this problem to be solved。

注释

神兽压阵。。。
// 这代码真是丑比了,我也是对自己醉了。。。
// 你最好别改这个代码,不然你会死的很惨。。

这个程序哥哥也太可爱了吧

sm4加密问题

你好,我看到sm4的加密函数(func cryptBlock)代码中有这么一段,感觉有点不懂,请指教。

if decrypt {
		for i := 0; i < 8; i++ {
			x = b[1] ^ b[2] ^ b[3] ^ subkeys[31-4*i]
			b[0] = b[0] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[0] ^ b[2] ^ b[3] ^ subkeys[31-4*i-1]
			b[1] = b[1] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[0] ^ b[1] ^ b[3] ^ subkeys[31-4*i-2]
			b[2] = b[2] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[1] ^ b[2] ^ b[0] ^ subkeys[31-4*i-3]
			b[3] = b[3] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
		}
	} else {
		for i := 0; i < 8; i++ {
			x = b[1] ^ b[2] ^ b[3] ^ subkeys[4*i]
			b[0] = b[0] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[0] ^ b[2] ^ b[3] ^ subkeys[4*i+1]
			b[1] = b[1] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[0] ^ b[1] ^ b[3] ^ subkeys[4*i+2]
			b[2] = b[2] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
			x = b[1] ^ b[2] ^ b[0] ^ subkeys[4*i+3]
			b[3] = b[3] ^ sbox0[x&0xff] ^ sbox1[(x>>8)&0xff] ^ sbox2[(x>>16)&0xff] ^ sbox3[(x>>24)&0xff]
		}
	}

这一段对应的应该是
image
,请问代码里的sbox0,1,2,3是怎么计算的,什么原理呢。

怎么与Java的代码对接?

Java端我用的bouncycastle库的实现,Golang用的事gmsm的1.1.1版本,测试后发现SM3的结果是一致的,但用SM2签名后的信息无法互通,也就是说对某个信息用公钥加密后,在另一端无法验证。另外我发现gosm用公钥对同个信息签名,每次签名的结果是一样的;而在bouncycastle库的实现中,每次签名的结果是不一样的,好像加入了随机数。

是不是算法的实现细节有差异?有否给个解决思路?

not satisfied with the benchmark result

$ go test -run=^$ -bench  .
beginning tests, encryption:salsa20, fec:10/3
goos: darwin
goarch: amd64
pkg: github.com/xtaci/kcp-go
BenchmarkSM4-4             	   20000	     92234 ns/op	  32.53 MB/s	    6016 B/op	     376 allocs/op
BenchmarkAES128-4          	  200000	      7268 ns/op	 412.74 MB/s	       0 B/op	       0 allocs/op
BenchmarkAES192-4          	  200000	      8190 ns/op	 366.28 MB/s	       0 B/op	       0 allocs/op
BenchmarkAES256-4          	  200000	      9055 ns/op	 331.30 MB/s	       0 B/op	       0 allocs/op
BenchmarkTEA-4             	  100000	     19463 ns/op	 154.13 MB/s	       0 B/op	       0 allocs/op
BenchmarkXOR-4             	20000000	       108 ns/op	27679.97 MB/s	       0 B/op	       0 allocs/op
BenchmarkBlowfish-4        	   50000	     34005 ns/op	  88.22 MB/s	       0 B/op	       0 allocs/op
BenchmarkNone-4            	30000000	        56.5 ns/op	53066.58 MB/s	       0 B/op	       0 allocs/op
BenchmarkCast5-4           	   30000	     41978 ns/op	  71.47 MB/s	       0 B/op	       0 allocs/op
Benchmark3DES-4            	   10000	    149801 ns/op	  20.03 MB/s	       0 B/op	       0 allocs/op
BenchmarkTwofish-4         	   30000	     48963 ns/op	  61.27 MB/s	       0 B/op	       0 allocs/op
BenchmarkXTEA-4            	   30000	     59826 ns/op	  50.15 MB/s	       0 B/op	       0 allocs/op
BenchmarkSalsa20-4         	  500000	      4010 ns/op	 748.07 MB/s	       0 B/op	       0 allocs/op

SM4 is slow compared to other block ciphers, and it has many memory allocations when crypting.

am I misused this library or may be any improvements can be taken?

SM2 Signature Algorithm in x509 certificate should not be the same as ECDSA

I found the sm2 use the signature algorithm oid of ecdsa, which is
oidSignatureECDSAWithSHA256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 4, 3, 2}.
When i use gmssl to parse the certificate created by sm2/x509.go, I got something like

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
             (Negative)01
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: O = TEST, CN = test.example.com, GN = Gopher, C = NL
        Validity
            Not Before: Jan  1 00:16:40 1970 GMT
            Not After : Jan  2 03:46:40 1970 GMT
        Subject: O = TEST, CN = test.example.com, GN = Gopher, C = NL

Note: the certificate is created by go test in gmsm/sm2
In fact, sm2 has its own signature algorithm.

对象标识符 名称 OID

  • rsaEncryption RSA算法标识 1.2.840.113549.1.1.1
  • sha1withRSAEncryption SHA1的RSA签名 1.2.840.113549.1.1.5
  • ECC ECC算法标识 1.2.840.10045.2.1
  • SM2 SM2算法标识 1.2.156.10197.1.301
  • SM3WithSM2 SM3的SM2签名 1.2.156.10197.1.501
  • sha1withSM2 SHA1的SM2签名 1.2.156.10197.1.502
  • sha256withSM2 SHA256的SM2签名 1.2.156.10197.1.503
  • sm3withRSAEncryption SM3的RSA签名 1.2.156.10197.1.504
  • commonName 主体名 2.5.4.3
  • emailAddress 邮箱 1.2.840.113549.1.9.1
  • cRLDistributionPoints CRL分发点 2.5.29.31
  • extKeyUsage 扩展密钥用法 2.5.29.37
  • subjectAltName 使用者备用名称 2.5.29.17
  • CP 证书策略 2.5.29.32
  • clientAuth 客户端认证 1.3.6.1.5.5.7.3.2

I have a pull/request to fix it. And parsing the certificate created by the new code, I can get

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
             (Negative)01
    Signature Algorithm: sm2sign-with-sha256
        Issuer: O = TEST, CN = test.example.com, GN = Gopher, C = NL
        Validity
            Not Before: Jan  1 00:16:40 1970 GMT
            Not After : Jan  2 03:46:40 1970 GMT
        Subject: O = TEST, CN = test.example.com, GN = Gopher, C = NL

--------------------------------end line--------------------------
xyz:~/gopath/src/github.com/tjfoc/gmsm/sm2$ gmssl x509 -text -noout -in cert.pem

sm2代码设计问题

sm2也属于ec算法,是不是可以复用go标准库中的ecdsa.PrivateKey等struct?同时Sign等标准库中的方法都不是正确实现,只有SM2Sign实现是正确的,容易误导使用者。

私钥长度是32字节,为什么将b设置为40字节?

https://github.com/tjfoc/gmsm/blob/0b26aafa7604a3cd63d76facfb62dc7885c068fa/sm2/sm2.go#L137~L145

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
}

这样的话私钥k的值其实就是40字节长度的整数。这个用意是什么?我看国密标准里没有此项表述。

sm4加解密问题

参考sm4_test.go中代码

func TestSM4(t *testing.T) {

当变量data换个值后,就失败了

func TestSm4(t *testing.T) {
	key := []byte("1234567890abcdef")
	fmt.Printf("key = %x\n", key)
	data := []byte("hello, world,,asdjkfhaksldfhjalskdfjhalsdfhj")
	fmt.Printf("data = %x\n", data)
	c, err := sm4.NewCipher(key)
	if err != nil {
		log.Fatal(err)
	}
	d0 := make([]byte, len(data))
	c.Encrypt(d0, data)
	fmt.Printf("d0 = %x\n", d0)
	d1 := make([]byte, len(data))
	c.Decrypt(d1, d0)
	fmt.Printf("d1 = %x\n", d1)

	t.Errorf("\n%x\n%x\n%x\n", data, d0, d1)
}

加密后后半部分数据全成0了
data=68656c6c6f2c20776f726c642c2c6173646a6b6668616b736c6466686a616c736b64666a68616c736466686a
d0=bd444d3e066e932409213856ec7010ff00000000000000000000000000000000000000000000000000000000
d1=68656c6c6f2c20776f726c642c2c617300000000000000000000000000000000000000000000000000000000

SM2签名数据在gmssl中无法验证的问题

你好, 我在尝试生成证书请求时, 发现无法通过gmssl的验证。已排除uid的问题, 代码内所有函数已改为使用 default_uid 而不是nil

验证证书请求的如下

[zcw@localhost csr]$ /opt/gmssld/bin/gmssl  req  -text -verify -in  ./sm2_4.csr           
crypto/sm2/sm2_sign.c 504: sm2_do_verify
verify failure
139987016300352:error:0D0C5006:asn1 encoding routines:ASN1_item_verify:EVP lib:crypto/asn1/a_verify.c:188:
Certificate Request:
    Data:
        Version: 1 (0x0)
        Subject: C = US, ST = California, L = San Francisco, O = CloudFlare, OU = Systems Engineering, CN = cloudflare.com
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:93:f3:ba:62:70:27:39:6a:dd:89:66:5d:6b:b2:
                    bf:51:f6:ff:07:f4:3c:1a:97:17:18:c6:7c:14:08:
                    9f:7a:80:15:ad:c7:bb:d2:97:d3:7d:7d:2c:e8:b3:
                    9e:02:30:90:07:53:34:6c:0c:b8:98:83:0b:2a:4a:
                    b9:38:1b:be:92
                ASN1 OID: sm2p256v1
                NIST CURVE: SM2
        Attributes:
        Requested Extensions:
            X509v3 Subject Alternative Name: 
                DNS:cloudflare.com, DNS:www.cloudflare.com
    Signature Algorithm: sm2sign-with-sm3
         30:45:02:21:00:95:71:bb:73:61:7d:9d:04:20:0e:05:ed:07:
         7e:ef:96:e0:29:f5:35:32:02:39:93:62:e1:95:d1:e6:8b:a5:
         26:02:20:56:38:17:c1:70:49:ce:48:42:ad:d7:de:e9:89:c4:
         9e:57:25:77:1d:87:03:8a:26:21:cc:25:13:cb:44:11:60
-----BEGIN CERTIFICATE REQUEST-----
MIIBgzCCASkCAQAwgYYxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlh
MRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRMwEQYDVQQKEwpDbG91ZEZsYXJlMRww
GgYDVQQLExNTeXN0ZW1zIEVuZ2luZWVyaW5nMRcwFQYDVQQDEw5jbG91ZGZsYXJl
LmNvbTBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABJPzumJwJzlq3YlmXWuyv1H2
/wf0PBqXFxjGfBQIn3qAFa3Hu9KX0319LOizngIwkAdTNGwMuJiDCypKuTgbvpKg
QDA+BgkqhkiG9w0BCQ4xMTAvMC0GA1UdEQQmMCSCDmNsb3VkZmxhcmUuY29tghJ3
d3cuY2xvdWRmbGFyZS5jb20wCgYIKoEcz1UBg3UDSAAwRQIhAJVxu3NhfZ0EIA4F
7Qd+75bgKfU1MgI5k2LhldHmi6UmAiBWOBfBcEnOSEKt197picSeVyV3HYcDiiYh
zCUTy0QRYA==
-----END CERTIFICATE REQUEST-----

提示,签名验证失败, 经gdb调试gmssl, 生成的za和摘要都没有问题, 于是怀疑签名函数有问题。

签名函数验证过程如下

  1. 修改 Sm2Sign , 将 k, err = randFieldElement(c, rand.Reader) , k固定为大数1,方便固定签名结果。
  2. 运行一次 TestSm2 , 会生成 私钥priv.pem、公钥pub.pem 、签名结果ofile。
  3. 取出上述三个文件。
    公钥文件
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAELSX1rhfPtcWAqoNqk81/AMNWZ6HA
IGoepEZ4cJTeuxON3OT8Ff8Kit6nOIZ2OlEcr6fu1icISnIYP2jI/twioA==
-----END PUBLIC KEY-----

私钥文件

-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgitMiH4EY/aMoVr+g
JsRUp8+gIzB1rlnvpbsp5Pg9RaugCgYIKoEcz1UBgi2hRANCAAQtJfWuF8+1xYCq
g2qTzX8Aw1ZnocAgah6kRnhwlN67E43c5PwV/wqK3qc4hnY6URyvp+7WJwhKchg/
aMj+3CKg
-----END PRIVATE KEY-----

签名结果为二进制,数据为

30 45 02 20 14 7a a4 c7 ce 82 23 ae ae 35 50 52 
70 77 11 8f e8 fc f6 d2 5e cf 00 c8 1a be 43 cd 
1a 45 5c f3 02 21 00 8a 35 0e 3d d8 00 d0 08 35 
7f 0e 3a a0 92 20 1d 8d 46 2a 7a fb 2d 32 bd 76 
8d 55 d2 9d 7e c6 08
  1. 使用asn1view,取出裸公钥 , 裸私钥,裸签名结果 ,使用多种国密算法工具,随机数输入1,uid输入 31323334353637383132333435363738 验签失败。

The performance of SM2-sign is unacceptable.

 $go test -bench .                                                 
BenchmarkSM2SignParallel-2           500           2631264 ns/op         1160430 B/op      11332 allocs/op
BenchmarkECDSASignParallel-2       20000             61821 ns/op            4680 B/op         69 allocs/op
PASS
ok      github.com/xxx/performance        3.542s

Ecdsa is about 40x faster than sm2.

公钥压缩算法实现没有遵从国密标准

根据国密标准GB/T 32918.1-2016中的第4.2.9的描述:
image

公钥压缩字节串格式首字节应该是0x02或是0x03,具体取决于特殊比特位的值是0还是1。但是在我测试的时候却发现实现过程中首字节貌似是0x00和0x01,没有一个转换的过程。这一点与国密标准相悖。望请改正。

如果是我测试或者理解错误,请在issue下面回复一下,别直接就关闭issue,上次给你们提一个pr,你们直接关闭,我以为是自己理解错误,谁知道你们后来改了过来,我很郁闷。

感谢你们的开源项目,比原链项目中的国密算法部分采用了你们的代码,在此感谢!

ZA函数使用的default_uid问题

ZA函数中,如果uid不出现,使用的default_uid,这个好像不是标准方式吧?能否改为uid不出现,拼接一个空的uid呢?提了一个pull request,请参考,谢谢!

没有userId参数吗?

msg, _ := hex.DecodeString("39393939313131313132333431326464646461616132323232323232323232323232323232323232323232323231313131")
sign, _ := hex.DecodeString("B573007F61A773626A1229936B8ACAE29228E1A343D8156472194DBBD41AC450E178DC876BEAA75922CBFB1D92C102391A87B84AE83202C28B09EADBDB8E6C8A")
pubkeyByte, _ := hex.DecodeString("0B085AA0473B0AD429189263B52D7A05C998CC5E7523F9E6F17DCCC4F9BCD4EEDBAB204B8F8FE17A2D1E70D1B23FC1BB24B58768F77CF10E372AD930A9ACF3ED")
pubkey, _ := sm2.ParseSm2PublicKey(pubkeyByte)
ok := pubkey.Verify(msg, sign)
if ok {
fmt.Println("ok\n")
} else {
fmt.Print("fail\n")
}
是不是没有用上国密推荐的userId参数 1234567812345678 ?
公钥验签是上述代码这样做的吗?我用已经验证过的JAVA代码生成的数据用上述代码做验签,都不行(不管JAVA代码生成的数据有没有用上userId做哈希)

SM2加密结果数据结构问题

目前gmsm项目中使用的SM2公钥加密使用的 GB/T 32918.4-2016 中加密结果是 C1|C3|C2直接拼接到一起。

image

gmsm 实际上在加解密的时候也是 sm2/sm2.go使用了该结构。

然后在需要传输和交换密文的场景中,使用的是 GM/T GMT 0009-2012 SM2密码算法使用规范中

image

的ASN1数据结构

就好像签名值一般不使用 R|S的而是用 ASN1表达一样,是否考虑将SM2加解密接口改进为了ASN1结果的返还值。

sm4 test

sm4
小白。

按我的理解,data是原始数据,d0是加密data的结果,d1是解密d0的结果。那么d1data是不是应该一样?

$ go test
key = [49 50 51 52 53 54 55 56 57 48 97 98 99 100 101 102]
key = [49 50 51 52 53 54 55 56 57 48 97 98 99 100 101 102]
data = 0123456789abcdeffedcba9876543210
d0 = 17e653832de37333d216c6be7cf13e6e
d1 = fcc8ab0fb273e1775152840cbd533ebd
PASS
ok      /git/gmsm/sm4       0.007s

解析国密证书出错

asn1: structure error: integer not minimally-encoded
我解析sm2签名证书出现这个错误 是什么原因?调用rest, err := asn1.Unmarshal(asn1Data, &cert)

sm2中曲线中使用a值计算时,性能降低,应该选-3

在p256.go文件中,sm2P256PointDouble函数和initP256Sm2函数使用曲线的a值(FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC)计算结果,导致性能下降。其实完全可以参照ecdsa的计算方法(如initP256Sm2完全可以使用ecdsa p256中的改函数,无需自己实现),将a值选用-3计算结果,性能会提升。因为-3和FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC的两条曲线等价。

v1.3.0 on proxy.golang.org differs from v1.3.0 on github.com

The cached zip file and checksum of v1.3.0 at proxy.golang.org and sum.golang.org do not match the v1.3.0 tag at github.com. If you download the module with GOPROXY="direct" to disable proxy.golang.org, you get a checksum mismatch.

$ go version
go version go1.14.2 linux/amd64
$ go clean -modcache
$ go mod init example.com/example
go: creating new go.mod: module example.com/example
$ GOPROXY="direct" GOSUMDB="sum.golang.org" go get github.com/tjfoc/gmsm
go: downloading github.com/tjfoc/gmsm v1.3.0
go get github.com/tjfoc/gmsm: github.com/tjfoc/[email protected]: verifying module: checksum mismatch
        downloaded: h1:qhgkrZru95jFP9NbVPknJvc9vgkMXhOEzkOASKdc0oQ=
        sum.golang.org: h1:i7c6Za/IlgBvnGxYpfD7L3TGuaS+v6oGcgq+J9/ecEA=

SECURITY ERROR
This download does NOT match the one reported by the checksum server.
The bits may have been replaced on the origin server, or an attacker may
have intercepted the download attempt.

For more information, see 'go help module-auth'.

If you disable the checksum check with GOSUMDB="off", you can download the module zip file from github, and directly from proxy.golang.org, to see what differs. Besides a filename encoding issue, two source files are different.

$ GOPROXY="https://proxy.golang.org" GOSUMDB="sum.golang.org" go get github.com/tjfoc/gmsm
go: downloading github.com/tjfoc/gmsm v1.3.0
go: github.com/tjfoc/gmsm upgrade => v1.3.0
$ curl -o proxy.zip https://proxy.golang.org/github.com/tjfoc/gmsm/@v/v1.3.0.zip
$ unzip -d proxy proxy.zip
$ diff -ru "$GOPATH/pkg/mod/github.com/tjfoc/[email protected]" "proxy/github.com/tjfoc/[email protected]" | diffstat
 $GOPATH/pkg/mod/github.com/tjfoc/[email protected]/API使用说明.md |only
 proxy/github.com/tjfoc/[email protected]/API??+???޻???.md                   |only
 proxy/github.com/tjfoc/[email protected]/sm2/p256.go                         |  251 ++--------
 proxy/github.com/tjfoc/[email protected]/sm2/sm2.go                          |    3 
 4 files changed, 65 insertions(+), 189 deletions(-)

I suppose that at some point, v1.3.0 pointed to a different commit than it does now, and someone did a go get of it, which cached that version at proxy.golang.org. Later, v1.3.0 was changed to point to a different commit.

Because of its version number, go get still considers v1.3.0 to be the newest version, even though v1.2.2, v1.2.3, and v1.2.4 were released more recently. I don't think you can ever change what's stored at proxy.golang.org and sum.golang.org, but you could release a new v1.3.1 that doesn't have the problem.

sm2.MarshalSm2PrivateKey 或 sm2.ParseSm2PrivateKey 错误

下面的测试用例不通过

func TestKeyEncode(t *testing.T) {
	priv, err := GenerateKey()
	if err != nil {
		t.Error(err)
		return
	}
	keyb, err := MarshalSm2PrivateKey(priv, nil)
	if err != nil {
		t.Error(err)
		return
	}

	priv2, err := ParseSm2PrivateKey(keyb)
	if err != nil {
		t.Error(err)
		return
	}
	if priv2.D.Cmp(priv.D) != 0 {
		t.Error("parsed key differ with souce key")
	}
}

输出如下:

--- FAIL: TestKeyEncode (0.00s)
    cert_test.go:19: x509: failed to parse SM2 private key: asn1: structure error: tags don't match (4 vs {class:0 tag:16 length:19 isCompound:true}) {optional:false explicit:false application:false private:false defaultValue:<nil> tag:<nil> stringType:0 timeType:0 set:false omitEmpty:false}  @5
FAIL
exit status 1
FAIL    github.com/tjfoc/gmsm/sm2       0.010s

sm4

两个问题:

  1. 怎么设置盐(salt)?
  2. 为什么要求key长度和BlockSize一样?

the sm4-cbc is different from openssl

func Sm4Encryption(key, iv, plainText []byte) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData := PKCS5Padding(plainText, blockSize)
blockMode := cipher.NewCBCEncrypter(block, iv)
cryted := make([]byte, len(origData))
blockMode.CryptBlocks(cryted, origData)
return cryted, nil
}
func Sm4Decryption(key, iv, cipherText []byte) ([]byte, error) {
block, err := sm4.NewCipher(key)
if err != nil {
return nil, err
}
blockMode := cipher.NewCBCDecrypter(block, iv)
origData := make([]byte, len(cipherText))
blockMode.CryptBlocks(origData, cipherText)
origData = PKCS5UnPadding(origData)
return origData, nil
}
func PKCS5Padding(src []byte, blockSize int) []byte {
padding := blockSize - len(src)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
func PKCS5UnPadding(src []byte) []byte {
length := len(src)
unpadding := int(src[length-1])
return src[:(length - unpadding)]
}
func main() {
originalText := "sysys"
fmt.Println(originalText)
mytext := []byte(originalText)
key := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
iv := []byte{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10}
cryptoText, _ := Sm4Encryption(key, iv, mytext)
fmt.Println(string(cryptoText))
decryptedText, _ := Sm4Decryption(key, iv, cryptoText)
fmt.Println(string(decryptedText))
}

the result of this way is different from openssl enc sm4-cbc,why?
test:
openssl:rom@rom-cd:/cer/sm4$ openssl enc -sm4-cbc -K 1d5c66c44102c7b87a466c30313be4ee -iv 1d5c66c44102c7b87a466c30313be4ee -p -v -nosalt -base64 -in src-test -out dst.sm4
bufsize=8192
key=1D5C66C44102C7B87A466C30313BE4EE
iv =1D5C66C44102C7B87A466C30313BE4EE
bytes read : 95
bytes written: 130
rom@rom-cd:
/cer/sm4$ cat dst.sm4
aSAhgpGpRIxQemxbZJ/4e/nRDm/JIpxldx25ZXWU8VgfStRDaV2dH/ngNlDRfknk
EhXIXLM2AU88F/ww8+Z5YhjRZjQjPNjZyrkJ/ZH2nJg3x83J0GZwMxq1d492JQfb
//加密内容经过base64

gmsm:
TestSM4Encrypt hex keybts string ct base64 aSAhgpGpRIxQemxbZJ/4e/nRDm/JIpxldx25ZXWU8VgfStRDaV2dH/ngNlDRfknkEhXIXLM2AU88F/ww8+Z5YhjRZjQjPNjZyrkJ/ZH2nJiNUAPDMH1UZSQ572PUOJno

加密key:
key := []byte{29, 92, 102, 196, 65, 2, 199, 184, 122, 70, 108, 48, 49, 59, 228, 238}
// 128比特iv
iv := []byte{29, 92, 102, 196, 65, 2, 199, 184, 122, 70, 108, 48, 49, 59, 228, 238}
内容 data := []byte("Hello World itoy irajfja;fa; jfapjfpajfpbsgblsgslghsg;sjg;sjg;sjg;js;yofgfgajfjafgjhagjfgakfgk")

加密结果比较:两者最后22位不相同,无法用openssl解密gmsm加密内容

关于gmssl生成的sm2withsm3证书在gmsm中验证失败的问题

现在很多涉及到sm2证书的,都用了默认用户身份标识

9. 用户身份标识 ID 的默认值
无特殊约定的情况下,用户身份标识ID的长度为16字节,其默认值从左至右依次为:
0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38

https://github.com/guanzhi/GmSSL/blob/838f4effbefd150a8c64e251bbac1be224ab24dc/go/gmssltest/gmssltest.go#L199

https://github.com/guanzhi/GmSSL/blob/1c00e47681678afc16cb1bc04fe814adf732b4b3/include/openssl/sm2.h#L72

https://github.com/cryptape/libsm/blob/3f62eb92758df72eb8f5deec71c9702b82d22eaf/src/sm2/signature.rs#L152
https://github.com/cryptape/libsm/blob/3f62eb92758df72eb8f5deec71c9702b82d22eaf/src/sm2/signature.rs#L201

提示一下,如果用gmsm的代码去验证gmssl生成的sm2withsm3的证书,记得自己在 CheckSignature(algo SignatureAlgorithm, signed, signature []byte) 的时候在signed前面补上16字节的用户身份标识ID。

其实比较好奇为啥gmsm项目不直接按照那个规范去做。虽然我也觉得在前面加一串1234567812345678有点莫名其妙的。

自签名 CA证书 校验签名失败

大佬你好,
我这边改造 fabric-国密版本, 发现新版本的 自签名 CA 证书 总是验证失败:

panic: Failed putting our own identity into the identity mapper: failed classifying identity: Unable to extract msp.Identity from peer Identity: could not obtain certification chain: failed getting validation chain: the supplied identity is not valid: x509: certificate signed by unknown authority (possibly because of "x509: SM2 verification failure" while trying to verify candidate authority certificate "ca.org1.example.com")

然后我单独到 gmsm 这个项目里 的 sm2_test.go 中做了下测试, 发现:

  • TestSm2 这个测试可以整体通过 证书校验
  • 单独使用 证书读取 后, 验证 证书 即无法通过 证书校验

所以提取 证书读取后的校验代码, 希望大佬能给帮帮忙看一下:

// 添加依赖 	"github.com/stretchr/testify/assert"
func TestReadCertificateFromPem(t *testing.T) {
        // gm版本 cryptogen 工具 生成 的自签名 CA
	var certPem = `-----BEGIN CERTIFICATE-----
MIICUjCCAfegAwIBAgIQYYTprq/7P3K7xn2w6qhTkDAKBggqgRzPVQGDdTBzMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu
b3JnMS5leGFtcGxlLmNvbTAeFw0yMDA0MTMwMzMzNTFaFw0zMDA0MTEwMzMzNTFa
MHMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T
YW4gRnJhbmNpc2NvMRkwFwYDVQQKExBvcmcxLmV4YW1wbGUuY29tMRwwGgYDVQQD
ExNjYS5vcmcxLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAE
eq64uveK/KX8jnZZ/5IOoIPpdSIV+gGmD2N8abr2/EKz5KE2zbxNRXcCvTUnO1pN
360Bk2YEk+T/BW4FFDjX+aNtMGswDgYDVR0PAQH/BAQDAgGmMB0GA1UdJQQWMBQG
CCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MCkGA1UdDgQiBCBx
R+y7n5LEXeBKUxxXE/uhAEsC+ZWxpUdTkkVK0VAU1TAKBggqgRzPVQGDdQNJADBG
AiEAzIefgCfH8xEEOCVzMFwn3sBHlxT62qiVBAQa/RmfjuACIQDrDFELRK4UnDfp
Y2IzEADy1jvAgdSAJiU2EPCba5VpNg==
-----END CERTIFICATE-----`

        // TestSm2 生成的 CA 证书
	var selfTestGenerateCertPem = `-----BEGIN CERTIFICATE-----
MIIDMzCCAtqgAwIBAgIB/zAKBggqgRzPVQGDdTBIMQ0wCwYDVQQKEwRURVNUMRkw
FwYDVQQDExB0ZXN0LmV4YW1wbGUuY29tMQ8wDQYDVQQqEwZHb3BoZXIxCzAJBgNV
BAYTAk5MMB4XDTcwMDEwMTAwMTY0MFoXDTcwMDEwMjAzNDY0MFowSDENMAsGA1UE
ChMEVEVTVDEZMBcGA1UEAxMQdGVzdC5leGFtcGxlLmNvbTEPMA0GA1UEKhMGR29w
aGVyMQswCQYDVQQGEwJOTDBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABNK3zTaa
4T9a8w7LmIImcDLWl4Fqy7bk0LUlFlhU7ZAnP8CCIAP/ijlc5jvdRHFXkVY+GO6M
UdGasbNs/LMhnDijggGzMIIBrzAOBgNVHQ8BAf8EBAMCAgQwJgYDVR0lBB8wHQYI
KwYBBQUHAwIGCCsGAQUFBwMBBgIqAwYDgQsBMA8GA1UdEwEB/wQFMAMBAf8wXwYI
KwYBBQUHAQEEUzBRMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5leGFtcGxlLmNv
bTAqBggrBgEFBQcwAoYeaHR0cDovL2NydC5leGFtcGxlLmNvbS9jYTEuY3J0MEYG
A1UdEQQ/MD2CEHRlc3QuZXhhbXBsZS5jb22BEWdvcGhlckBnb2xhbmcub3JnhwR/
AAABhxAgAUhgAAAgAQAAAAAAAABoMA8GA1UdIAQIMAYwBAYCKgMwKgYDVR0eBCMw
IaAfMA6CDC5leGFtcGxlLmNvbTANggtleGFtcGxlLmNvbTBXBgNVHR8EUDBOMCWg
I6Ahhh9odHRwOi8vY3JsMS5leGFtcGxlLmNvbS9jYTEuY3JsMCWgI6Ahhh9odHRw
Oi8vY3JsMi5leGFtcGxlLmNvbS9jYTEuY3JsMBYGAyoDBAQPZXh0cmEgZXh0ZW5z
aW9uMA0GA1UdDgQGBAQEAwIBMAoGCCqBHM9VAYN1A0cAMEQCIAFl6HuA0qntdsGh
9SBSf6/JCtZmeSGuNbr1PgNRqDupAiA4UXAzrPBgAbIN3CWjQV28QCorLCvQ3Xct
fyXNzlRCtA==
-----END CERTIFICATE-----`
	cert, err := ReadCertificateFromMem([]byte(certPem))
	assert.NoError(t,err,"ReadCertificateFromMem Failed.")

	err = cert.CheckSignature(cert.SignatureAlgorithm, cert.RawTBSCertificate, cert.Signature)
	assert.NoError(t,err,"CheckSignature Failed")


	cert2,err := ReadCertificateFromMem([]byte(selfTestGenerateCertPem))
	assert.NoError(t,err,"ReadCertificateFromMem Failed.")

	err = cert.CheckSignature(cert2.SignatureAlgorithm, cert2.RawTBSCertificate, cert2.Signature)
	assert.NoError(t,err,"CheckSignature Failed")
}

上面这两个在我这边测试的时候 都会失败。

希望大佬给指点指点。

Test for SM4

I have noticed that the data used to encrypt in an4_test.go must be 16 or 16*n bytes long.And I have a try to use Encryption function here to encrypt some data like "Hello World",but it doesn't work with Decryption function here.So,does it work in GM module in bccsp for sm4 now? Thanks in advanced.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.