使用加密狗的國密算法實(shí)現(xiàn)B/S架構(gòu)數(shù)字信封

一舵鳞、程序邏輯

加密-上傳
  1. 瀏覽器發(fā)起A用戶的上傳請(qǐng)求
  2. 服務(wù)端生成會(huì)話密鑰Ks雇锡,用A用戶的公鑰Ka進(jìn)行SM2加密為密鑰Ks’,發(fā)給瀏覽器
  3. 瀏覽器收到加密后的會(huì)話 密鑰Ks’渠概,用A用戶的私鑰Ka’進(jìn)行SM2解密得到會(huì)話密鑰Ks
  4. 瀏覽器使用會(huì)話密鑰Ks锦亦,對(duì)上傳文件進(jìn)行SM4加密得到密文M’舶替,發(fā)給服務(wù)端
  5. 服務(wù)端保存密文M’以及會(huì)話密鑰Ks

二、技術(shù)實(shí)現(xiàn)

2.1 密鑰傳輸部分(步驟1-3)

  1. SM2證書解析
    首先測試瀏覽器端加密狗ocx插件杠园,可以使用ocx獲取證書顾瞪。


    加密狗ocx測試頁

    經(jīng)廠家確認(rèn),證書格式為X.509抛蚁。將證書直接寫在服務(wù)端代碼內(nèi)陈醒,嘗試解析證書并獲取公鑰Ka。代碼如下:

// 證書
String cert64 = "MIIBvzCCAWa…F2yvFQ==";
// base64解碼
byte[] certBytes = Base64.getDecoder().decode(cert64);
InputStream inStream = new ByteArrayInputStream(certBytes);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
// x509解析
X509Certificate cert = (X509Certificate)cf.generateCertificate(inStream);
// 打印證書到期時(shí)間
System.out.println(cert.getNotAfter());

運(yùn)行后報(bào)錯(cuò):

Caused by: java.io.IOException: Unknown named curve: 1.2.156.10197.1.301
    at sun.security.ec.ECParameters.engineInit(ECParameters.java:143)
    at java.security.AlgorithmParameters.init(AlgorithmParameters.java:293)
    at sun.security.x509.AlgorithmId.decodeParams(AlgorithmId.java:132)
    at sun.security.x509.AlgorithmId.<init>(AlgorithmId.java:114)
    at sun.security.x509.AlgorithmId.parse(AlgorithmId.java:372)
    at sun.security.x509.X509Key.parse(X509Key.java:168)
    at sun.security.x509.CertificateX509Key.<init>(CertificateX509Key.java:75)
    at sun.security.x509.X509CertInfo.parse(X509CertInfo.java:667)
    at sun.security.x509.X509CertInfo.<init>(X509CertInfo.java:167)

上網(wǎng)搜索得知:國密證書使用了自有的橢圓曲線瞧甩,所以無法使用JDK自帶的java.security解析證書(http://www.jonllen.com/jonllen/work/162.aspx)钉跷。經(jīng)過調(diào)研,需要引入BouncyCastle亲配,BC庫支持國密算法尘应。參考這篇文章(https://blog.csdn.net/jinhill/article/details/9996117)修改代碼惶凝,在pom.xml增加BC庫依賴:

<!-- https://mvnrepository.com/artifact/org.bouncycastle/bcprov-jdk15on -->
<dependency>
   <groupId>org.bouncycastle</groupId>
   <artifactId>bcprov-jdk15on</artifactId>
   <version>1.61</version>
</dependency>

修改測試代碼為:

// 引入BC庫
Security.addProvider(new BouncyCastleProvider());
// 使用BC解析X.509證書
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");

經(jīng)測試吼虎,可以正常讀取證書內(nèi)容犬钢。

  1. SM2公鑰加密
    參考(https://blog.csdn.net/pridas/article/details/86118774)編寫加密代碼如下:
// 測試會(huì)話密鑰
String ks = "666666";
byte[] data = ks.getBytes();
// 獲取A的公鑰Ka
BCECPublicKey publicKey = (BCECPublicKey) cert.getPublicKey();
// 加密引擎
SM2Engine sm2Engine = new SM2Engine();
// 加密參數(shù)
X9ECParameters sm2p256v1 = GMNamedCurves.getByName("sm2p256v1");
ECDomainParameters parameters = new ECDomainParameters(sm2p256v1.getCurve(), sm2p256v1.getG(), sm2p256v1.getN());
// 引擎初始化
sm2Engine.init(true, new ParametersWithRandom(new ECPublicKeyParameters(publicKey.getQ(), parameters), new SecureRandom()));
// 加密
byte[] encrypt = sm2Engine.processBlock(data, 0, data.length);
// base64編碼
String encrypt64 = Base64.getEncoder().encodeToString(encrypt);
System.out.println(encrypt64);

可以生成加密后的密文,但嘗試使用ocx插件進(jìn)行解密時(shí)思灰,解密失敗玷犹。


解密失敗

參考這篇文章所述,考慮密文組織順序洒疚,舊標(biāo)準(zhǔn):C1+C2+C3歹颓,新標(biāo)準(zhǔn)C1+C3+C2。增加密文結(jié)果調(diào)整函數(shù)油湖,調(diào)整密文組織順序巍扛。

/**
 * 安全芯片SM2加密處理的密文順序是 C1+C3+C2  而BC庫加密出來的順序是C1+C2+C3
 * 此方法在加密后調(diào)用,將結(jié)果轉(zhuǎn)化為 C1+C3+C2
 */
static byte[] changeC123toC132(byte[] src) {
    //sm2p256v1的這個(gè)固定65乏德〕芳椋可看GMNamedCurves、ECCurve代碼喊括。
    final int c1len = (sm2p256v1.getCurve().getFieldSize() + 7) / 8 * 2 + 1;
    //new SM3Digest().getDigestSize();
    final int c3len = 32;
    byte[] dst = new byte[src.length];
    System.arraycopy(src, 0, dst, 0, c1len); //c1
    System.arraycopy(src, src.length - c3len, dst, c1len, c3len); //c3
    System.arraycopy(src, c1len, dst, c1len + c3len, src.length - c1len - c3len); //c2
    return dst;
}

再次嘗試使用ocx插件進(jìn)行解密胧瓜,仍失敗。比對(duì)ocx通過加密狗生成的密文與代碼生成的密文郑什,發(fā)現(xiàn)ocx的比代碼生成的密文短一個(gè)字節(jié)府喳。上網(wǎng)搜索問題原因,終于找到這篇(https://my.oschina.net/547217475/blog/2252583)蘑拯。通過debug钝满,發(fā)現(xiàn)加密后密文的第一個(gè)字節(jié)的確是04。

加密后數(shù)據(jù)

增加一個(gè)函數(shù)申窘,去除密文的第一個(gè)字節(jié)弯蚜。

/**
 * 安全芯片在C1數(shù)據(jù)最前面沒有04,而BC庫加密出來的數(shù)據(jù)前面有04
 * 去除BC加密后C1數(shù)據(jù)的第一個(gè)字節(jié)
 */
static byte[] removeFirstByte(byte[] src) {
    byte[] dst = new byte[src.length - 1];
    System.arraycopy(src, 1, dst, 0, dst.length);
    return dst;
}

經(jīng)測試偶洋,ocx可以正確解密獲得服務(wù)器端生成的會(huì)話密鑰ks熟吏。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市玄窝,隨后出現(xiàn)的幾起案子牵寺,更是在濱河造成了極大的恐慌,老刑警劉巖恩脂,帶你破解...
    沈念sama閱讀 206,311評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件帽氓,死亡現(xiàn)場離奇詭異,居然都是意外死亡俩块,警方通過查閱死者的電腦和手機(jī)黎休,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門浓领,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人势腮,你說我怎么就攤上這事联贩。” “怎么了捎拯?”我有些...
    開封第一講書人閱讀 152,671評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵泪幌,是天一觀的道長。 經(jīng)常有香客問我署照,道長祸泪,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,252評(píng)論 1 279
  • 正文 為了忘掉前任建芙,我火速辦了婚禮没隘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘禁荸。我一直安慰自己右蒲,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,253評(píng)論 5 371
  • 文/花漫 我一把揭開白布屡限。 她就那樣靜靜地躺著品嚣,像睡著了一般。 火紅的嫁衣襯著肌膚如雪钧大。 梳的紋絲不亂的頭發(fā)上翰撑,一...
    開封第一講書人閱讀 49,031評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音啊央,去河邊找鬼眶诈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瓜饥,可吹牛的內(nèi)容都是我干的逝撬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,340評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼乓土,長吁一口氣:“原來是場噩夢啊……” “哼宪潮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起趣苏,我...
    開封第一講書人閱讀 36,973評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤狡相,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后食磕,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體尽棕,經(jīng)...
    沈念sama閱讀 43,466評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,937評(píng)論 2 323
  • 正文 我和宋清朗相戀三年彬伦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了滔悉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伊诵。...
    茶點(diǎn)故事閱讀 38,039評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖回官,靈堂內(nèi)的尸體忽然破棺而出曹宴,到底是詐尸還是另有隱情,我是刑警寧澤孙乖,帶...
    沈念sama閱讀 33,701評(píng)論 4 323
  • 正文 年R本政府宣布浙炼,位于F島的核電站份氧,受9級(jí)特大地震影響唯袄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蜗帜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,254評(píng)論 3 307
  • 文/蒙蒙 一恋拷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧厅缺,春花似錦蔬顾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至窥妇,卻和暖如春舷胜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背活翩。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工烹骨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人材泄。 一個(gè)月前我還...
    沈念sama閱讀 45,497評(píng)論 2 354
  • 正文 我出身青樓沮焕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拉宗。 傳聞我的和親對(duì)象是個(gè)殘疾皇子峦树,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,786評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容