遇到有接口須要使用國密的SM2算法,對方使用的是JAVA,咱們使用的是go,原覺得都是標準算法不會有什麼大問題,結果巨坑沒法..java
對方使用的加密模塊,SM2.java和SM2KeyPairs.java,不知道最初是誰開發的,網上貌似不少都是這個版本的實現,可是和go的交互老是有問題,用這個java模塊加密的,go裏面怎麼也沒法正確解密。仔細覈對以後發現,這個java模塊有幾個地方並不符合GB/T32891的標準。算法
這裏只要獲得C4,便能進行解密,而C4 = kP = kdP = dkP = d(kC) = dC1。而C1是密文的一部分,因此有了私鑰d即可以進行解密。數組
這裏的P、G、C一、C4是橢圓曲線上的點,點的乘法只具備幾何意義上,並不是2X3=6的算術運算。編碼
加密後的密文,標準爲C1 || C3 || C2,C3位SM3哈系值,而這個庫中結果爲 C1 || C2 || C3。加密
Java中,BigInteger的最高位爲1時,toByteArray()獲得的字節數組會多一位,在前面多了一個爲0的字節,應該是要表示爲正數。致使運算結果和其餘語言的不一致。spa
計算T時,須要用點C4的X座標和Y座標組合進行,這個庫裏直接調用bouncycastle庫裏,ECPoint類的getEncoded()的方法,獲得的結果是在字節流里加了一個字節(0x4),實際是不須要的,致使計算的字節流T有差別code
java的bouncycastle庫裏,在橢圓曲線的計算中,使用了X/Y/Z三個座標,而其餘的實現多是沒有Z座標的,因此調用點的座標的時候,應該調用normalize()方法正則化後使用,這時Z座標是1。orm
而在這個庫中,並無進行正則化的操做,致使加密結果沒法與其餘程序進行交互,除非對方也使用的bouncycastle庫,可實現方式與其相似。接口