lpilp / phpsm2sm3sm4

php版本,支持国密SM2的签名算法,非对称加解密,SM3的hash, SM4的对称加解密
329 stars 76 forks source link

求助SM2解密问题 #65

Closed alexlipe closed 11 months ago

alexlipe commented 11 months ago

对接移动的接口,用的是SM2加解密,给了一套 base64的密钥公钥。套进来以后,都不好使了。。求助。在网上搜了在线加解密的工具,只有一个用java后端网站可以解的开。 同时对接的别家公司也是用java的可以解开。

加密的时候报 Uncaught Exception: publickey format error in /home/www/gm/vendor/wzhih/guomi/src/sm/RtSm2.php:314

解密的时候报 Uncaught Mdanter\Ecc\Exception\PointNotOnCurveException: Curve curve(115792089210356248756420345214020892766250353991924191454421193933289684991996, 18505919022281880113072981827955639221458448578012075254857346196103069175443, 115792089210356248756420345214020892766250353991924191454421193933289684991999) does not contain point (2073623091809835619484128975511634192252869500422850399165305844804933041599, 101651507866330411692959266458639688105383006869356102341330448629304075468432) in /home/www/gm/vendor/mdanter/ecc/src/Primitives/Point.php:102

公钥密钥 都已经用 bin2hex(base64_decode('xxxxxxxx')) 处理过了。

曲线:sm2p256v1

私钥:MIGTAg.......HSnVTAJ7

公钥:MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEZDUTeG9t+2y5vUITcracrWQo8eW7j/VX878FF5XjuqlHCoS/VFoVQ6xtaHXsjS4Kl5kCKm1MZfJ+oh0p1UwCew==

对方给的密文是 0495A10B4373C26595C0B919345539575852F3EFBB083D1EA0393109AB42BDBFE0BCB6EE0B6021E42AB2509C1A09C9A4D161E9AAD15C6068E8252358F947BE905A7823B6BF5DF16C98370DC4D379333423FE28E5EAA417705C7774DB051559EDC41D17FE287C0FFC6ECF8D9CE944317683C290BA59ED3797E3AAD31F781E6420A5DCC626F4A9F6723B9B1F7E9D430A42B6ED89EF3C6A49CA06511D5C52D1B835F665BE613E133E57EBFD42165E9E7A093706BB35581B87E308D5334B1FB16D87D95DB911F9F6F7EE5157FBC324CAF3FF7EFA9A9A68276680EB070785FDABDD7FBA31354248193D90E5BF9B06ECC15D6ABBB32D21C0F546F2D977AFE428462DA21CD88D55F28069F9C2859170F823D49C5BB92554DCFDEA556CD53FDE400C7D9A99E13EF76831895E99DF83A7EDF908664100E813AED4DCC4B67AF50C587D913CBD9155A89BA4D8ECEFAD3F40F251B84ADDAC45E805D1FB4CCE26191F236C777BA3CFB203FAB41B7373E3D5DC51779DE1BA607E2D9DAE0E0B2909179C4C869E521C195E526338D15511A7EC5E01F34FCAD38A2E0D4C8E5929F53D76066EA5D319F19B212AB9EB97E2FFE002688D8A0F257384A6B240DBDF51CAF332928429A563D5647B1376997B95D0B8BD34575DE1503012F0FFDF1F1B817563F37E543CBF13793C5C52521B436AA217F962F12894AC398E235924B56385F92957BCCED2D48A5F4299C061D029FFBC97821D3EB6CE9EB836A8E96771D79A1486C0F700884D4609CC140087CA0AE8FC17D23307090B8429FC54CF224D65A745AC02958884F3C0298B9905D77DEBB61EEB055A031D824E92F0B65AABF440973C148EFEAF352B5F0DD8DC97077D94D4532157DE9795662AB0

lpilp commented 11 months ago

首先把你这个私钥隐了 本项目目前支持的是明文hex公私钥, 你给的的这个私钥是pkcs8这种类似格式的,首先将这个私钥 asn1解开得到一个私钥的类pkcs1的,然后再将这个 asn1串解开就可以得到正式的私钥了, 为“147EC3--------”, 不想解的话,就把这个私钥hex后,找到这个147ec3这个连续64个字符就是私钥了

项目util下有个类可以使用来解开,解开一次后,就可以存下来了

$keys = MyAsn1::decode($key,'base64');
$privateKeys = MyAsn1::decode($keys[2],'hex');
$privateKey = $privateKeys[1];
var_dump($privateKeys[1]);
lpilp commented 11 months ago

很多项目像我这个一样,只支持明文的,所以就不好使,JAVA的一般使用的BC库,那个库是支持ASN1过的私钥格式的

alexlipe commented 11 months ago

项目util下有个类可以使用来解开,解开一次后,就可以存下来了

好的。我试试看, 怀疑是钥匙格式的问题,但是不知道怎么解。 谢谢大佬。我去再试下。

alexlipe commented 11 months ago

可以了,可以了。果然是这个问题,谢谢大佬

alexlipe commented 11 months ago

还有一个疑问,劳烦再解下惑。 $key = MyAsn1::decode($pub,'base64'); $pub = $key[1];

在解这个公钥的时候, 只需要这一步就行了,不存在keys[2], 不需要执行MyAsn1::decode($keys[2],'hex'); 在keys[1]中看到 公钥是04开头的, 是不是公钥解到04 就是解开了? 私钥解到14开头就可以了?

然后密文并不是04 开头的,我回传java那边的时候,还需要自己加一个04在前面?

lpilp commented 11 months ago

公钥与私钥的格式不一样,你的这个私钥要解asn1两次才能解出私钥,公钥只要一次就解开了,还是和封装格式有关,至于公钥有没有04就看各个代码自己的处理方式了

alexlipe commented 11 months ago

了解。 感谢大佬。