tjfoc / gmsm Goto Github PK
View Code? Open in Web Editor NEWGM SM2/3/4 library based on Golang (基于Go语言的国密SM2/SM3/SM4算法库)
Home Page: http://www.wutongchain.com
License: Apache License 2.0
GM SM2/3/4 library based on Golang (基于Go语言的国密SM2/SM3/SM4算法库)
Home Page: http://www.wutongchain.com
License: Apache License 2.0
在sm2目录的x509.go文件中在Sm2的校验分支没有对RawTBSCertificate内容先按照设定hash函数进行hash,造成校验失败。需要在验证之前对RawTBSCertificate调用闭包fnHash进行hash。
https://github.com/tjfoc/gmsm/blob/master/sm2/x509.go/#L1036
已提交pull request请合入
Java端我用的bouncycastle库的实现,Golang用的事gmsm的1.1.1版本,测试后发现SM3的结果是一致的,但用SM2签名后的信息无法互通,也就是说对某个信息用公钥加密后,在另一端无法验证。另外我发现gosm用公钥对同个信息签名,每次签名的结果是一样的;而在bouncycastle库的实现中,每次签名的结果是不一样的,好像加入了随机数。
是不是算法的实现细节有差异?有否给个解决思路?
参考sm4_test.go中代码
Line 25 in 867dc48
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
Line 186 in 71e9164
目前 sm4_test.go
里面加解密都是成对出现的,我把加密后的结果拿出来单独做解密无法得到原文,怀疑是因为在每次执行 cryptBlock
这个方法时,会修改 c.block1和c.block2,这个副作用应该被禁止
根据压缩公钥的格式标准,应该是:
若y坐标最后一位是0,则压缩公钥前缀为:0x02,否则为0x03
如题 x509.go 998 行,switch pub := publicKey.(type) 中为什么没有sm2.PulicKey的case?
但是在其他地方,如func signingParamsForPublicKey中switch pub := publicKey.(type),却有sm2.PulicKey的case。
请问这个是基于什么特殊原因考虑的吗?
下面的测试用例不通过
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
As fabric will do toLowS
after signature generated to avoid signature malleability attack, ecdsa lib could sucessfully verify the modified signature which sm2 can't .
https://github.com/hyperledger/fabric/blob/master/bccsp/sw/ecdsa.go#L33
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
如题,谢谢!
参考:pull request
你好,我看到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]
}
}
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/cer/sm4$ cat dst.sm4
bufsize=8192
key=1D5C66C44102C7B87A466C30313BE4EE
iv =1D5C66C44102C7B87A466C30313BE4EE
bytes read : 95
bytes written: 130
rom@rom-cd:
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加密内容
go get github.com/tjfoc/[email protected]: no matching versions for query "v1.2"
go get github.com/tjfoc/[email protected]: github.com/tjfoc/[email protected]: invalid version: unknown revision v1.2.0
go mod 需要识别类似 v1.2.0 的tag
ZA函数中,如果uid不出现,使用的default_uid,这个好像不是标准方式吧?能否改为uid不出现,拼接一个空的uid呢?提了一个pull request,请参考,谢谢!
Why is SM2 treated as one of the ECDSA?
There is no difference between sm.PublicKey and ecdsa.PublicKey in memory structure.
is there any resource for fabric-go-sdk to use fabric-gm ? thanks
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.
i notice there is a sha512 function used in SM2 Signature Algorithm implementation.Does it satisfy the standard ?
$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.
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字节长度的整数。这个用意是什么?我看国密标准里没有此项表述。
$ 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?
asn1: structure error: integer not minimally-encoded
我解析sm2签名证书出现这个错误 是什么原因?调用rest, err := asn1.Unmarshal(asn1Data, &cert)
在 PrivateKey.Sign中调用了Sm2Sign 此过程中传入随机源被丢弃。此处应考虑把随机源传递到运算中。因为在工程中有可能不用go语言默认的随机源。(代码 sm2.go 80行)
sm4
小白。
按我的理解,data
是原始数据,d0
是加密data
的结果,d1
是解密d0
的结果。那么d1
跟data
是不是应该一样?
$ 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
Line 66 in 71e9164
在整个方法中找不到用到的地方
大佬你好,
我这边改造 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
中做了下测试, 发现:
所以提取 证书读取后的校验代码, 希望大佬能给帮帮忙看一下:
// 添加依赖 "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")
}
上面这两个在我这边测试的时候 都会失败。
希望大佬给指点指点。
根据国密标准GB/T 32918.1-2016中的第4.2.9的描述:
公钥压缩字节串格式首字节应该是0x02或是0x03,具体取决于特殊比特位的值是0还是1。但是在我测试的时候却发现实现过程中首字节貌似是0x00和0x01,没有一个转换的过程。这一点与国密标准相悖。望请改正。
如果是我测试或者理解错误,请在issue下面回复一下,别直接就关闭issue,上次给你们提一个pr,你们直接关闭,我以为是自己理解错误,谁知道你们后来改了过来,我很郁闷。
感谢你们的开源项目,比原链项目中的国密算法部分采用了你们的代码,在此感谢!
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.
在p256.go文件中,sm2P256PointDouble函数和initP256Sm2函数使用曲线的a值(FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC)计算结果,导致性能下降。其实完全可以参照ecdsa的计算方法(如initP256Sm2完全可以使用ecdsa p256中的改函数,无需自己实现),将a值选用-3计算结果,性能会提升。因为-3和FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC的两条曲线等价。
sm2也属于ec算法,是不是可以复用go标准库中的ecdsa.PrivateKey等struct?同时Sign等标准库中的方法都不是正确实现,只有SM2Sign实现是正确的,容易误导使用者。
oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} 这是ecdsa的
你好, 我在尝试生成证书请求时, 发现无法通过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和摘要都没有问题, 于是怀疑签名函数有问题。
签名函数验证过程如下
-----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
31323334353637383132333435363738
验签失败。国密签名和ECDSA签名都需要临时公钥,ecdsa 签名是r=x1mod/n,国密的r=(h+x1)modn,ecdsa可以恢复公钥,国密理论上是不是也可以推导啊
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
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
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
国密能根据签名和哈希推算出公钥吗
在golang 1.12.1中通过go get的导入v1.2这个项目失败,能否支持golang mod的语义化版本号。
https://semver.org/lang/zh-CN/
pkcs5UnPadding 函数没处理好下标越界问题
IS the curve used in Go pkg (elliptic) which is y2 = x3 - 3x +b satisfied with National Standard ?
两个问题:
key
长度和BlockSize
一样?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证书的,都用了默认用户身份标识
9. 用户身份标识 ID 的默认值
无特殊约定的情况下,用户身份标识ID的长度为16字节,其默认值从左至右依次为:
0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38 0x31 0x32 0x33 0x34 0x35 0x36 0x37 0x38
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有点莫名其妙的。
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。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.