证书 一些证书类型:
所谓的用户证书,就是用户用自己的私钥对对自身信息内容进行签名,然后发给CA证书签发机构,CA验证后用CA的私钥签发的数字证书
此外还要知道的文件类型
使用openssl生成p12格式的RSA和ECC证书
使用gmssl生成p12格式的SM2证书 安装gmssl,参考https://github.com/guanzhi/GmSSL/tree/master
为了加深理解,在用gmssl生成SM2证书的同时,模拟下证书是如何签发的
首先要关注下gmssl的配置文件/usr/local/gmssl/openssl.cnf
(在安装gmssl的目录,因为要符合配置文件,所以要保持文件名相同或者根据需求进行修改,添加相应的默认文件,即mkdir newcerts private certs crl && touch index.txt && vi serial
,并在serial中输入初始化序列号,比如02
其中
dir:CA所在的目录
certificate:CA的证书
private_key:CA的密钥
CA生成密钥
1 $ gmssl sm2 -genkey -out private/cakey.pem
CA自签名证书
1 $ gmssl req -new -x509 -key private/cakey.pem -out cacert.pem
客户端生成密钥
1 $ gmssl sm2 -genkey -out 4xwi11.key
客户生成csr(好像公司等信息要和CA自签时一致
1 $ gmssl req -new -key 4xwi11.key -out 4xwi11.csr
CA签发crt证书
1 $ gmssl ca -in 4xwi11.csr -out 4xwi11.crt -cert demoCA/cacert.pem -keyfile demoCA/private/cakey.pem
验证签名
1 $ gmssl verify -verbose -x509_strict -CAfile demoCA/cacert.pem 4xwi11.crt
将crt转为p12
1 $ gmssl pkcs12 -export -in 4xwi11.crt -inkey 4xwi11.key -out 4xwi11.p12
将导入usbkey的容器里,接着就是很迷的地方,如下图,上面那个是老师帮我用在线网站生成证书然后导出公钥和私钥的,下面那个是我自己的, 我是没找到有什么办法可以把公私钥像上面那样导出来,反正我的无法正常使用(只能对称加密。其中应该有版本的问题,我看别人的都是V2.2.19,直接导入就是上面那样,而且还有创建容器的按钮,WTF
不过这个问题是可以通过调用API来解决的,后面还会提到
运行demo 总之折腾到这里本型号demo提供的功能都能够使用了
调用智能密码钥匙实现以下功能 在所有的操作之前,先实例化mTokenPlugin
对象
1 var token = new mTokenPlugin();
获取随机数 函数原型如下
1 2 3 4 p = token.SOF_GenerateRandom(100 ) console .log(p);console .log(_Base64decode(p));
获取的随机数base64解码出来是字节码,如下图所示。和预想的不一样。。。所以硬件是产生的随机值是字节形式的
经过验证uLength是随机数的字节长度,怎么验证的呢。。有点啰嗦
对这些字节码进行转10进制数字操作,代码如下,结果如下图二所示:20个字节(256进制)转10进制bit位在160左右
进一步分析随机函数参数uLength
与bit位的关系,代码如下,结果如下图三所示,可以说是SOF_GenerateRandom
函数接口会生成uLength*8
bit长度的随机数,即uLength
表示随机数的字节长度,并且可以传浮点数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from base64 import b64decodea = ['TFqASTnk/wbgnJdrsrhTm/f3TOM=' , '48mhqXP2TVvDEobwtrnu0ygRETI=' , 'Ic1j/mrYsVf1nrHJYU5pvjk8T2A=' , 'JhYXyMjulyA2S4bW147VhnnRzy8=' , 'DtyF8fKEmxdHAZnMj0/ySy/DNqI=' , 'w3+204ZtTNg+0bwjJx2raPBKMds=' , '6pv9XIWX1FOHrMb1pArMZEHGltI=' , 'fadDSTrjvzx31ZyObwgMmOCz4mw=' , 'rGS3q41jnt7NiOjymaMAOkcd89U=' ] for i in a: val = 0 src = b64decode(i) assert len (src) == 20 for j in range (len (src)): val += src[j] * 256 ** (len (src) - j - 1 ) print (f"256进制 ====> {val} && {val.bit_length()} nbits" ) print (f"l2b ====> {int (src.hex (), 16 )} && {int (src.hex (), 16 ).bit_length()} nbits" ) print ()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 from base64 import b64decodea = '' 'ag== hI8= 0Sm+ CZkaAQ== D0Dx6mY= 068tI/hc ncwlaByQDA== 75LErcGq05M= wjZVgpFGfT9T L+WBOYEtterUrA== jbhw/b4YoYpR+Ec= Nk/dDpr8EOx9iSeS r0hXkHskSHLQ+UMQ7A== eeK12gh+wg+Xhk9eVLU= UJ1xtQt/BjO7h8mn7z67 HUAO119KLqthbpX1zgvZcA== quI3zQp4rc0WOSnXZpfTV74= MPWaDcS1IRBpzwvX8hZGvQI/ TS16Gp6tsPKvebTacsQS6ZmYsQ== 1GKgYDJKoW8IJ9HaW/ORecc3xQc= f4BigtV4opSqbABIwMUfMTBYMI96 UOaNdWFj8imAu67qu/iRSIcRIuGS1g== lcfCepOg/mve2G08xRYKOOTTL+6zkFo= MRcKTt8yjdqkCHbX9+4O+6O3xzSEjQDj ES3f7/RSfO0aolrMPAzt+MIQhaNH7CkbFA== lA897tf2Gs9mPLHIWZ+w6w6r0T4W4fMHfLQ= NRTOxPqLWCfiXju8C+Dx5f3xTZSmgYSbGd7B DLHWBO289HTYHvyK+Bm1tcrqtP008zL5QsJsBg== 1R0MRh31HJDnM0XQqKgidxiLflRnrpLme9b1tRE= FCgYN14B2ZMrl0Msi6gJe87BuZRRpeqhu0d4y2T3 qN9sPcdG2b0Lt99t1NYwmXpLc6WLe9GpPO8XsMr82Q== sWIr4C+6HqFo5CEiMvnk5Mqqr3Pmx35beLTSAveS/UU= r6xdBYpVZexlUgqDh1FsDi+DDhqyrDksLFr9ilLVjtjf 5ps8iGmx3shHAPefTU/5AhIGMuu7njIakNFywcJIULZZ1A== 3BopWTfTO4N+x5v+yHjscolXWkwOqBdI4yPeMGefRhmp3wI= Ip2cZ5A1UTFrFsxIakG9DUPATXqbS0KSMu+aqW+sBhqeTpPe M5PxkVw1NPK9OyfIScu4JbSA0xfjxuwqjl0+TTgG7c7ohLZFcw== VdSryos9SkzYDp/9FJ9CrgiCSGDO82Yk70mIKIVGOx84e43FVrQ= 2I+cngj0i8R8De++1saob3CEzOA4QYwC2efYXrKNheiaBGmXdsit RGrDRgwEjpyLbywpW8hddYRpAsVxTcthPOTYxxOtNPOnwG3kcbQwsA== xkqdiU0j/sxqHZS/1pzps5hdPjcO7qIkC8HjBIJGd5DT140lulD0u6A= bBz9giAeit7NNaIC6+miB4H+kRCm2cV4p02Uxgp/BdqH5XkNKEEXvSjK fe2MPtPIk9uBwOEA0tjrtfF2cDJbqrXZ8TMLu7rXva1+LwTNwn7S80Qtbw== DqLOCXrkhiKm698fYJ2hjQ2U+U2cMzZM8zJbldvE5U/31/OK+00KhXuAvDw= NZSASmxK054Vkepw3RHDzN1ktv8ws/6ygdgNrjesqN5Dvcy0htCajU3MavMu cCO05rf7qSyJYqKtwW0hfezE/3uvJdXZcpJoLqkL2WCWevLz0gPkaQ9FkLFtMQ== sFfqBBsD50+GHzkDYM26NAkXWclJbrpdsvYvxVZobhnGXVO71XOvZPDJBzt9cxw= e7ZNpcp8absdDM1Rr6w9HE1mJ6HiucrrGaEsWGRl0TvQkXXrv+i2BiWB6Am/PfB2 czOPxtLV7/x0n4Qckbs3jzlFWaQGw7S+Oi/v5e7QEPLFpml2hTmf+/UvgyZFMosxxQ== j2kjfvLVbHyNwcys3QuLDNGRwpFRiQvJy++1qUkhVvAwUUTib/zhP1JuqRfhYbH1muo= xMdZnrCht3I2Ly9QtpmEC+FxSPgYj7PrVF3sC9oYleNXaYITAWzgYvtaNpFIb+CJaz7u lpbl2niIqCKRN+BcJ++AEtUkyYo5oUsTisLLQYGIXaRyT2mv+4ld8W5eloD6J/RuUE/o1A== HwJCb2T1dOIQlJp5Jy1dTrrKk8hqf+fgCqYyEOk0GhtA6lZUMa1bYCu/yzJl/cz2ppt/wyk= lhut0vBBSSEVC1wxvwTzCTzwcWVOiwoovdafUuG8UKOMWjTjEqQot92o2V01HCWGlwZyb0cG 21hBqIC4GdIL+Hs80pu7FYmefeQ1bBiSb9DpAUljYn7EtJAxFIxWwhP65OIsImc2+h6WimEgsg== PDH4YNMJ7SZ3UkXljr2kKTH8VvJ8HyOCK3Na92c2KVbnOJKQmMMfymBjCmbRlX3CrIUSHFZ+8Ao= 75T5YhJ6iPRN+EGcq/IEv1sIkgM0uj0MFHaN4xsKFRWOkA9lgDSM8HHDhZe0QxgYrARWcLuzhFHP QC8zKJ4x6hXExqGD1aJgxZwzMefaKzw7GnWz4VG5HabW41XcLDdCy/BGRhdIEgezhu3I9LYdqnOziA== zMwi+jrILWmp761Kqu5I+sSbjI6a7Aq0ZTINN8M2YZTrxrlBdkOoqhMNeZRyOnHHXcTX0ApJYi9GPfw= c+kVJ8Jkl2R23E7nz/nhVrpN88UFcOGcrVShCa9KZUbIb8B5Vp55gS03zGjFnJ2pdwWiZI8hOnMDgeYQ gF5V7dY/gjknFnampP2sgS2OGPtzxbOmhD/gA/CUWIBTARS5aZIOH1ucL9TTw9cy7pASDp5c+OrGxt5/0A== rgpYBo/iU7y0eekZ9P+V5hpw/niSO/ZiFNSBpbmnRmG3zDV54dK/94QSiG93/iiWrPf1wHwAK+xgSnCh3Gw= lFo+c8sAML/iUfOtdr2m/2pYr3bAqXfHVjbct1kps8sjGUNzpizxo380sv5vGbWe6wcN61ve4g6QYkETQdKs WsIoM7O0o0Y/q7gVY9kzfg1jpwGXugmvMKdZFBfgrUawDoo9Gj6n2uxmiiGzSfBgdUv9mB0vDB2HnWNdnox6Vw== kuThcoRn1SaOa8WtygLWEBaEcJWpy965qonIkAAYc3RFkwv02OXKdLR3r177GL7hbRmBf/e1JoMV7BwkVU5QM+g= p1xkYFnMzfdc82rl7+ap3Hcg/JPaBgQWBfsxxVNHC8O0LhULZRy4R9Mchcayz34P9kZXGC1wJA2A98F+5NJI7bS2 c45NRpfx7wwFwupCnNNBsGJFdDHT+rp2mNJPbKxwIjs+j4oVIxlcVYLLOZEllvhUxCziafDspDGbyoPmgkntE5qo4g== zhH2LRT0/IqIVjbCssBSna84TvHfFCbUpih5ONYFBl06hCbvmgd8jE6aaHu+/1ahGFgSji7uHcaO8XIOKtlYk9HnRpA= //5V/ePt5Ryc7RK/k6Y7VE0IcufLav+UNeUvaEMZixhGGnvndeL+mfMfBy7xi4gAgjwtDS4LMakEleOamZhGplKCCqa2 YNVJ6yNFMKku+4e6CtibSn8yvFIV8TCzpXt6xdgdXypSlXbcZwzKa6Yp+vMKGDwcLAmimXCvc5RbzpRTK7ycMja4Xy1WzA== eTnppoAMfCwcDKI5Y5bMaWYIXPTliPVInt5eAzbXOyGA/1ilR5VzMyFs0RDdk35TxIV6gOqp+kI0y7f9VjhofmZ3xW9iS14= 7fzG82S4iFkTF67rTIZXnq1OzcurS1E3BLiHNQ6OpZX6cBHwQ3pyRh8+4NxX/Fan55rRu4T3sueNYkkyALbL+ocsY2WqzCCN +FgoYx5RKEVC56nIlonC2KakkJNDKZC+JXlMIzYg/J1JQoqZhzSzw9qtxfOoqH35+VvyHtBYqn85tgDxQ4H3/C30TLOA9TGx2Q== E1wah2OhOC4Ci69pSfC8xgHKQ2xsKPrOAcSqqW2iHrU2U4U41YftwKmP9ecaV1ppckzJTNWgPUnMXWT9qW36aJfLXr8HldeQMkk= M7tJwW8Uy7ZTnwTsMUghgUAZf/8s7zO7WlJvfRdb6TyMhgQ/DQXUNYE2f5kxs5K2GOjMBpY0l9eTG2fsvqx0GyYZUh0vmwBXRtfl sT7xNdQA5a8E4CknveaEaes2nqIAWGFVEO59Eqsuj9mn+ORTQPK7bviPNDnuVLw1WGPGLUbDodXRO4aR+CTNykf48SFqE30Q76iF4w== /y/Vhv9MLDoU7I/OUNPe3owl6NqIDn+WsOh+y9brBybBX3AiIKXafTu+A/ldZzTGur2UFmBxHKGnfc16e0D9gSwxchRCbEP83krbYu8= kLm+qmyPUVIDC6meodWE0HJdp0EjiwZVFRlRic6SUT+6aOOetWS3ssyp+wyh8XNp7gmUUrwUhWyDCVPMwATLm0V995SOCcO3cu0UXigK Cgms7yCoIzF1GduQBzFojjOh0KW/nbb5Y96PRYjn9DlbPbAA85XRUMMhfnZMQjaCQvCN3BTpI1g0yPQR/spd87e30DhYm1tZv1Q47ipMOw== 5e25+gtBAiEFsS0/79Ng04moXbV1ZCUhgTtuXrV1pbDyzjRZrqiNTYOrv0mh1lJa1dEtfWuU8z584yz2JwF8y8oRA60oIWpZuq7hjCa8PHQ= wUWEuc+rWRpto1IuUXX78V+dVnUcXyPRwQ9+rZkcolY5GsDD+qIIVOLeZniKIW2YCrDcFYeurhgnZ0i8hoODpDb4072Gt27jnksutrU8hSD/ 9yOJv/swvwBq/4elnXW5TqtENuB5P7jnp0RsIGeO3kzXutM7ogjnLOUbFJNSv1a3RFxHK1GejNahxZzSgmK6gFbdXsiYliuC7bQUMDDzZ36TdA== +vA3YDDLZKObVe9sMpdypWBGtrVNNCOiS7uH/sFDFzmjaUD+kcfnDnVizt1GQiZAi3qZgxw/yZPCgzOHLkb1XXRUD/3KZxR/kyaYyHC0f2cS570= dirYz92a6Ti1eVo4jbR/xEUz3iABhvx3SpnXQy4c8JyzSiNNGclQvM7WAXbSzuKP11hBfqmOsa5AfGvscWtyKwRMTUyNeJ9Wd2lrOMi49EeEzrE2 yNh0XNDVZMvvt43WzxZpVEfoOdcdctknN6DH+mdtg0jnKgflDAy42T1YC/CtEflFt3DyrI+60r7eYpkfX7dCkWBDH85U+lbvbCikd0k8dBoH87H5Qg== 2ZGzjSQ8qJPQRPpus+LXLhpWbAmEpW/XfZykfggniKemx7C1Gp58r1sBS3e6RZ6wSrGjp5/6NaoHt2RxE/J6cpvGwO8w9tx1CTi5RT9QyZ7tMAWAxBk= A08n0IuKVA55LnnkTIrSrWow59V3WekpgOXusIt396Da3cz6/OQl9y5tcEV+CqyBVH72gD67S5QqoXTxMX1ianCydJ5Pcchfu5Y6Omr5Th9Tp9zqylIr tW2QfvKUpQ1wb7mSEi79G+uaUNNlgKOBOofyINQb3+/HRMTYf+zfFT6AXVH1BJlMnb2Hf3xt0EhLZl0K3ltRrU1IodMDMG+lb/RDngWgyvUBbk9oCi3Z2w== bcoUQq2gKiWEXrjOyEGNCIRXLIJ0eXsy5TONrlQjrCZxjud3cMKwcT7ltFXBOY0eo+ngUUr5gacoZD1wg1xj+c170X39orN8eDZzEBAVien8gjglaiAzmXc= fOAEFAYLifb3sRiqxN8UMjMRXX9APRTcJEW9tdQqo+xDvPh6a9632h/3pDtKz+o76iYDgnUp6yyMtlwnNNxmaQncLhwXOylq88zG/RJCGeX065ggogwSr7ZA uAjjXRMggTBEGpt0pee7oj3iqh1HdncUEG3rxTqU/WV8Etv11MEgpz5D3p8KCERvzlfxDWRl886xzHejK0bRth6EaYn63M9YdwXO7KqFOQIOM40DbMGR1HAOGw== KaH6UZTvVJ1R5bdRTciIclz8M4t7mAo+IXVT9n0DrbbWqKp15evyK9Z2RnokDkWKuly8gsmqKq5TYcJbW2y0iO94lVuPT7c+wJPn7ruWc9E4euLdU/eflktebww= MXRDmE60qUYHuXqXqFV2nThyQJaCcMkmT2MeBgEK08wZzSo14UXU7WZmwv5gV0A72bxj1NeVIIPP60Id2JnjuCwfSg5g1EbX4xGdBeQOHwbjFWqoQ7MB93r6McRA RvExfm8ab0wqM9/p3oIwPglkkZvKxtgh68tkj49pRCRos8G1gGbt/9bBCwv1nqvTRi9y4IGw5g/RtcnGGzm7xiWWThVbFs4tVWnpMai6tas6rWLkTt9PJKyKfkvq/w== U3iCt1dI95gxG8zDjEA1H/BasP/Wxvos31UKGN932SoDXQXhLZM5qzhoUqlbk/9wYAfmxubzAC2iDR6oReYk3v1V0dmjzhs60XJzphP9C14a8Ciju6W2LDktoaZbvEA= trVvSeN1Ki4F905FEQnOZXamKQGY0J6hVw4Ut6WyCJzR4Jkw8fLHh5JdBR5KIXLvo+swOuYDavSDWQnKdkRQYJaxkmWPwBPUGcgREOWuWBbxY+QvKrHQYkOPZzFPXNLe aQXkWomVggiirRDHTDxoeqmRJ34HrwqD/b02XuDiZiOHr0VrAjs3416nKMAD8BbjcxOdd8f0vspdraEUNzgp7qlqY1bDnUZj8044RMpGzkVUNqGI424OxBzfX0EGEeGOUA== 075bh4Kd3zyYJfvsEU4o0vJyqCRrbzFKiYFTeBuesCg1sNmCtDINOn8oftA/na2JtMl0PjBobFlXP/DSYmYbTIuBbLftbfIT9gcn2ITsNlOE1DdcK6d52VI1itD6JJm/WQs= M1Mb+GE81R1ddl/woj9ee4HzVXv587QLMIpTdvjtou1PpHfgRQDQodvVLPiwJ/d5WTTLK4jChdYT6VPSBxF0mjoVGwKzUBbsgVoy4oEo/OtXKKIri575BEAK6lN5IlEaqGT8' '' la = a.split('\n' ) for i in range(len(la)): src = b64decode(la[i]) print(f"uLength: {i + 1} ====> nbits: {int(src.hex(), 16).bit_length()}" )
不过这一切在老师后面给的另一份文档中得到证实。。。
最终在js里可以这么用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 const gen_rand_bits = $('#gen_rand_bits' );gen_rand_bits.click(function ( ) { const rand_bits = $('#rand_bits' ); const rand_num = $('#rand_num' ); rand_num.val('' ); let nbits = rand_bits.val(); if (nbits === '' ) { alert('请输入合法长度' ); return null ; } if (nbits > 6148 ) { alert('长度过长,须小于6148Bytes' ); return null ; } nbits = parseFloat (nbits); p = token.SOF_GenerateRandom(nbits); if (p === -3 ) { alert("与硬件交互失败,请检查是否插入USBKEY并是否登录" ); return null ; } else if (p === -2 ) { alert("生成随机数失败,错误码:" , token.SOF_GetLastError()); return null ; } else { p = _Base64decodeArray(p); let val = 0n ; let len = p.length; for (let i = 0 ; i < len; ++i) { val += BigInt (p[i]) * 256n ** (BigInt (len) - BigInt (i) - 1n ); } rand_num.val(val); } })
此外,经过测试(多次重装mPlugin_Setup
,该硬件生成的最大随机数位数在6148*8=49184 bits左右
计算HAMC HMAC 哈希运算消息认证码,简单来说就一句话
伪代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 function hmac (key, message) { if (length(key) > blocksize) { key = hash(key) } if (length(key) < blocksize) { key = key ∥ [0x00 * (blocksize - length(key))] } o_key_pad = [0x5c * blocksize] ⊕ key i_key_pad = [0x36 * blocksize] ⊕ key return hash(o_key_pad ∥ hash(i_key_pad ∥ message)) }
注意下面框框框起来
下面这张wiki的图就将用SHA-1做HMAC的流程解释得很清楚
blocksize参照下表
js实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 const gen_hmac = $('#gen_hmac' );gen_hmac.click(function ( ) { const hmac_val = $('#hmac_val' ); const hmac_key = $('#hmac_key' ); const hmac_msg = $('#hmac_msg' ); const hmac_digest = $('#hmac_digest' ); const container = $('#sele_contentList' ); let userID = '1234567812345678' ; let key = hmac_key.val(); let msg = hmac_msg.val(); let digest = hmac_digest.val(); let key_length = key.length; let msg_length = msg.length; let containerName = container.find("option:selected" ).text(); token.SOF_SetUserID(userID); token.SOF_SetDigestMethod(digest); let block_size = 64 ; if (digest == 130 || digest == 131 ) { block_size = 128 ; } let tmp_msg = stringToByte(msg); let tmp_key = stringToByte(key); if (key_length > block_size) { tmp_key = token.SOF_DigestData(containerName, _Base64encodeArray(tmp_key), key_length); tmp_key = _Base64decodeArray(tmp_key); } key_length = tmp_key.length; if (key_length < block_size) { for (let i = 0 ; i < block_size - key_length; ++i) { tmp_key.push(0x0 ); } } var o_key_pad = new Array (block_size).fill(0x5c ); var i_key_pad = new Array (block_size).fill(0x36 ); for (let i = 0 ; i < block_size; ++i) { o_key_pad[i] = tmp_key[i] ^ o_key_pad[i]; i_key_pad[i] = tmp_key[i] ^ i_key_pad[i]; } let tmp1 = i_key_pad.concat(tmp_msg); tmp1 = token.SOF_DigestData(containerName, _Base64encodeArray(tmp1), tmp1.length); tmp1 = _Base64decodeArray(tmp1); let tmp2 = o_key_pad.concat(tmp1); tmp2 = token.SOF_DigestData(containerName, _Base64encodeArray(tmp2), tmp2.length); if (tmp2 != null && tmp2 != "" ) { hmac_val.val('' ); hmac_val.val(tmp2); } else { alert("HMAC失败,错误码:" + token.SOF_GetLastError()); } })
验证一下好吧
生成公私钥对 函数原型如下所示
这个会根据参数,创建一个名为containerName的容器,返回0成功。然后可以用SOF_ExportPubKeyEx
将公钥导出,这个在demo里已经实现了,就不再赘述
导出公钥,制作数字证书,并将证书导入USBKey 文档里看到生成公私钥如上,还有生成公私钥并生成证书请求、还有将提前生成好的证书导入usbkey的API
要申请证书,还必须找一个CA
创建容器(有点鸡贼,调用SOF_GenerateP10Request
接口,借用申请证书请求时创建的容器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const create_con = $('#create_con' );create_con.click(function ( ) { let container_name = $('#container_name' ).val();let key_type = $('#key_type' ).val();let key_nbits = parseInt ($('#key_nbits' ).val());let enc_sign = parseInt ($('#enc_sign' ).val());let rtn = token.SOF_GenerateP10Request(container_name, '4xwi11' , key_type, enc_sign, key_nbits);if (rtn != null && rtn != '' ) {alert('容器创建成功' ); } else {alert('容器创建失败,错误代码:' , token.SOF_GetLastError()); } })
将openssl或者gmssl创建的证书导入刚才创建好的容器
其中证书的内容即自签名的证书内容,格式为base64编码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 const import_cert = $('#import_cert' );import_cert.click(function ( ) { let container_name = $('#container_name' ).val(); let import_cer_info = $('#import_cer_info' ).val(); let enc_sign = parseInt ($('#enc_sign' ).val()); let res = token.SOF_ImportCert(container_name, import_cer_info, enc_sign); if (res === 0 ) { alert('导入成功' ); } else { alert("导入失败:" , token.SOF_GetLastError()); } })
2022-04-18补充:
上面这个鸡贼的方法,当然会惨遭不测(现象是在数字签名的时候,除了老师导给我的SM2证书,我自己生成的其他证书验签都失败了)由于错得印象深刻,这里单独补充一下
原因是
这个来自《GMT0016-2012智能IC卡及智能密码钥匙密码应用接口规范》
所以上面这个操作是完全错误的,内部的私钥和导入的证书其实是对不上的
解决的方法是,将证书请求或公钥导出来,然后给外面的CA去做证书,然后再把证书导入(注意这里不能再自签名了,因为容器内部的私钥导不出来。然后暂时没找到合适的指定公钥的证书生成工具以及这个pkcs10的证书申请我也没怎么搞懂,先咕咕咕了
同样,也是因为上面这段话,是不能内部产生加密容器的
调用USBKey进行RSA或SM2数字签名 这个demo里,直接copy,注意RSA的摘要算法不能是SM3,而SM2的摘要算法只能有SM3
还有一点,注意userID并非鸡肋。这在最后补充SM2签名还会提到
一些坑 虽然坑很多,但主要的还是记录下
问题:key管理软件可以使用,但web端连不到
解决:重新安装mPlugin_Setup
补充 可以发现SM2签名,每次点签名按钮生成的签名都是不一样的,而RSA固定不变。因为前者在签名过程中使用了随机数
填下ECC和SM2签名的坑
ECDSA
SM2DSA 在ECDSA基础上,就非常好理解了
首先,要准备用户ID,这也是为什么上文这里有SOF_SetUserID
的API
具体的还是看文档吧
Reference
GMT0016-2012智能IC卡及智能密码钥匙密码应用接口规范
龙脉国密KEY 证书综合应用插件用户手册
openssl官方文档
gmssl模拟CA发布证书
外校实验课usbkey使用 (他们的key管理工具都是v2.2.19的
js-Bignt处理大数
wiki-HAMC
HMAC-blocksize
https://lazzzaro.github.io/2020/11/07/crypto-ECC/
SM2椭圆曲线公钥密码算法