SM2 裸簽名

最近在處理一個(gè)需求试幽,使用國(guó)密SM2進(jìn)行簽名氏义,在實(shí)際需求中有這樣的一個(gè)場(chǎng)景:對(duì)PDF進(jìn)行簽名究西,其實(shí)是簽署PDF sm3處理后的摘要窗慎,所以后端給到我們的就是sm3 hash,標(biāo)準(zhǔn)的做法是簽署 signerinfo->AuthenticatedAttributeSet,而偏偏我們遇到的是直接對(duì)hash進(jìn)行簽名,所以不能用sm2sign_with_sm3遮斥,而BC庫(kù)又不支持sm2sign算法峦失。最后看源碼找到了SM2Signer,它的內(nèi)部實(shí)現(xiàn)其實(shí)還是sm2sign_with_sm3,所以我們可以進(jìn)行修改SM2Signer

看過源碼后發(fā)現(xiàn)只要修改generateSignature -> eHash就可以了,這樣就可以直接跳過內(nèi)部做過的sm3算法

public byte[] generateSignature(byte[] sm3Hash)
            throws CryptoException
{
    byte[] eHash = sm3Hash;

    BigInteger n = ecParams.getN();
    BigInteger e = calculateE(eHash);
    BigInteger d = ((ECPrivateKeyParameters)ecKey).getD();

    BigInteger r, s;

    ECMultiplier basePointMultiplier = createBasePointMultiplier();

    // 5.2.1 Draft RFC:  SM2 Public Key Algorithms
    do // generate s
    {
        BigInteger k;
        do // generate r
        {
            // A3
            k = kCalculator.nextK();

            // A4
            ECPoint p = basePointMultiplier.multiply(ecParams.getG(), k).normalize();

            // A5
            r = e.add(p.getAffineXCoord().toBigInteger()).mod(n);
        }
        while (r.equals(ZERO) || r.add(k).equals(n));

        // A6
        BigInteger dPlus1ModN = d.add(ONE).modInverse(n);

        s = k.subtract(r.multiply(d)).mod(n);
        s = dPlus1ModN.multiply(s).mod(n);
    }
    while (s.equals(ZERO));

    // A7
    try
    {
        return derEncode(r, s);
    }
    catch (IOException ex)
    {
        throw new CryptoException("unable to encode signature: " + ex.getMessage(), ex);
    }
}

在使用的時(shí)候只需要傳入sm3后的hash

/**
 * 簽名
 *
 * @param priKey  私鑰
 * @param srcData 原文
 * @return DER編碼后的簽名值
 * @throws CryptoException
 */
public static byte[] sign(BCECPrivateKey priKey, byte[] srcData) throws CryptoException {
    ECPrivateKeyParameters priKeyParameters = BCECUtil.convertPrivateKeyToParameters(priKey);
    BCSM2Signer signer = new BCSM2Signer();
    CipherParameters param = new ParametersWithRandom(priKeyParameters, new SecureRandom());
    signer.init(true, param);
    return signer.generateSignature(srcData);
}

簽名驗(yàn)簽同理

public boolean verifySignature(byte[] sm3Hash,byte[] signature)
{
    this.sm3Hash = sm3Hash;
    try
    {
        BigInteger[] rs = derDecode(signature);
        if (rs != null)
        {
            return verifySignature(rs[0], rs[1]);
        }
    }
    catch (IOException e)
    {
    }

    return false;
}


private boolean verifySignature(BigInteger r, BigInteger s)
{
    BigInteger n = ecParams.getN();

    // 5.3.1 Draft RFC:  SM2 Public Key Algorithms
    // B1
    if (r.compareTo(ONE) < 0 || r.compareTo(n) >= 0)
    {
        return false;
    }

    // B2
    if (s.compareTo(ONE) < 0 || s.compareTo(n) >= 0)
    {
        return false;
    }

    // B3
    byte[] eHash = sm3Hash;

    // B4
    BigInteger e = calculateE(eHash);

    // B5
    BigInteger t = r.add(s).mod(n);
    if (t.equals(ZERO))
    {
        return false;
    }

    // B6
    ECPoint q = ((ECPublicKeyParameters)ecKey).getQ();
    ECPoint x1y1 = ECAlgorithms.sumOfTwoMultiplies(ecParams.getG(), s, q, t).normalize();
    if (x1y1.isInfinity())
    {
        return false;
    }

    // B7
    BigInteger expectedR = e.add(x1y1.getAffineXCoord().toBigInteger()).mod(n);

    return expectedR.equals(r);
}   
/**
 * 驗(yàn)簽
 *
 * @param pubKey  公鑰
 * @param sm3Hash 原文sm3hash
 * @param sign    DER編碼的簽名值
 * @return
 */
public static boolean verify(BCECPublicKey pubKey, byte[] sm3Hash, byte[] sign) {
    ECPublicKeyParameters pubKeyParameters = BCECUtil.convertPublicKeyToParameters(pubKey);
    BCSM2Signer signer = new BCSM2Signer();
    signer.init(false, pubKeyParameters);
    return signer.verifySignature(sm3Hash,sign);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末术吗,一起剝皮案震驚了整個(gè)濱河市尉辑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌较屿,老刑警劉巖隧魄,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異隘蝎,居然都是意外死亡购啄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門嘱么,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狮含,“玉大人,你說我怎么就攤上這事曼振〖钙” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵冰评,是天一觀的道長(zhǎng)映胁。 經(jīng)常有香客問我,道長(zhǎng)甲雅,這世上最難降的妖魔是什么解孙? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮务荆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘穷遂。我一直安慰自己函匕,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布蚪黑。 她就那樣靜靜地躺著盅惜,像睡著了一般。 火紅的嫁衣襯著肌膚如雪忌穿。 梳的紋絲不亂的頭發(fā)上抒寂,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音掠剑,去河邊找鬼屈芜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的井佑。 我是一名探鬼主播属铁,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼躬翁!你這毒婦竟也來了焦蘑?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤盒发,失蹤者是張志新(化名)和其女友劉穎例嘱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宁舰,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拼卵,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了明吩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片间学。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖印荔,靈堂內(nèi)的尸體忽然破棺而出低葫,到底是詐尸還是另有隱情,我是刑警寧澤仍律,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布嘿悬,位于F島的核電站,受9級(jí)特大地震影響水泉,放射性物質(zhì)發(fā)生泄漏善涨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一草则、第九天 我趴在偏房一處隱蔽的房頂上張望钢拧。 院中可真熱鬧,春花似錦炕横、人聲如沸源内。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)膜钓。三九已至,卻和暖如春卿嘲,著一層夾襖步出監(jiān)牢的瞬間颂斜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工拾枣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留沃疮,地道東北人盒让。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像忿磅,于是被迫代替她去往敵國(guó)和親糯彬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

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