<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          程序員必備基礎(chǔ):加簽驗簽

          共 2825字,需瀏覽 6分鐘

           ·

          2020-08-06 06:46

          我們在求職面試中,經(jīng)常會被問到,如何設(shè)計一個安全對外的接口呢? 其實可以回答這一點,加簽和驗簽,這將讓你的接口更加有安全。接下來,本文將和大家一起來學(xué)習(xí)加簽和驗簽。從理論到實戰(zhàn),加油哦~

          • 密碼學(xué)相關(guān)概念
          • 加簽驗簽概念
          • 為什么需要加簽、驗簽
          • 加密算法簡介
          • 加簽驗簽相關(guān)API
          • 加簽驗簽代碼實現(xiàn)
          • 公眾號:撿田螺的小男孩

          本文已經(jīng)收錄到個人github,文章有用的話,可以給個star呀:

          ?

          https://github.com/whx123/JavaHome

          ?

          密碼學(xué)相關(guān)概念

          明文、密文、密鑰、加密、解密

          • 明文:指沒有經(jīng)過加密的信息/數(shù)據(jù)。
          • 密文:明文被加密算法加密之后,會變成密文,以確保數(shù)據(jù)安全。
          • 密鑰:是一種參數(shù),它是在明文轉(zhuǎn)換為密文或?qū)⒚芪霓D(zhuǎn)換為明文的算法中輸入的參數(shù)。密鑰分為對稱密鑰與非對稱密鑰。
          • 加密:將明文變成密文的過程。
          • 解密:將密文還原為明文的過程。

          對稱加密、非對稱加密

          • 對稱加密:加密和解密使用相同密鑰的加密算法。

          • 非對稱加密:非對稱加密算法需要兩個密鑰(公開密鑰和私有密鑰)。公鑰與私鑰是成對存在的,如果用公鑰對數(shù)據(jù)進行加密,只有對應(yīng)的私鑰才能解密。

          什么是公鑰私鑰?

          • 公鑰與私鑰是成對存在的密鑰,如果用公鑰對數(shù)據(jù)進行加密,只有用對應(yīng)的私鑰才能解密。
          • 其實,公鑰就是公開的秘鑰,私鑰就是要你私自保存好的秘鑰。
          • 非對稱加密算法需要有一對公私鑰~
          ?

          假設(shè)你有一個文件,你用字母a加密,只有字母b才能解密;或者你用b加密,只有a才能解密,那么a和b就是一對公私鑰。如果密鑰a公開,密鑰b你就要私自保存好啦,這時候密鑰a就是公鑰,密鑰b就是私鑰。相反,如果b公開,a就要保存好,這時候呢,秘鑰b就是公鑰,秘鑰a就是私鑰。

          ?

          加簽驗簽概念

          • 「加簽」:用Hash函數(shù)把原始報文生成報文摘要,然后用私鑰對這個摘要進行加密,就得到這個報文對應(yīng)的數(shù)字簽名。通常來說呢,請求方會把「數(shù)字簽名和報文原文」一并發(fā)送給接收方。

          • 「驗簽」:接收方拿到原始報文和數(shù)字簽名后,用「同一個Hash函數(shù)」從報文中生成摘要A。另外,用對方提供的公鑰對數(shù)字簽名進行解密,得到摘要B,對比A和B是否相同,就可以得知報文有沒有被篡改過。

          為什么需要加簽驗簽

          上小節(jié)中,加簽和驗簽我們已經(jīng)知道概念啦,那么,為什么需要加簽和驗簽?zāi)兀坑行┡笥芽赡苡X得,我們不是用「公鑰加密,私鑰解密」就好了嘛?

          接下來呢,舉個demo吧。

          ?

          假設(shè)現(xiàn)在有A公司,要接入C公司的轉(zhuǎn)賬系統(tǒng)。在一開始呢,C公司把自己的公鑰寄給A公司,自己收藏好私鑰。A公司這邊的商戶,發(fā)起轉(zhuǎn)賬時,A公司先用C公司的公鑰,對請求報文加密,加密報文到達C公司的轉(zhuǎn)賬系統(tǒng)時,C公司就用自己的私鑰把報文揭開。假設(shè)在加密的報文在傳輸過程中,被中間人Actor獲取了,他也郁悶,因為他沒有私鑰,看著天鵝肉,又吃不了。本來想修改報文,給自己賬號轉(zhuǎn)一個億的,哈哈。這個實現(xiàn)方式看起來是天衣無縫,穩(wěn)得一匹的。

          ?

          但是呢,如果一開始,C公司把公鑰發(fā)給公司A的時候,就被中間人Actor獲取到呢,醬紫就出問題了。

          ?

          中間人Actor截取了C的公鑰,他把自己的公鑰發(fā)給了A公司,A誤以為這就是C公司的公鑰。A在發(fā)起轉(zhuǎn)賬時,用Actor的公鑰,對請求報文加密,加密報文到在傳輸過程,Actor又截取了,這時候,他用自己的私鑰解密,然后修改了報文(給自己轉(zhuǎn)一個億),再用C的公鑰加密,發(fā)給C公司,C公司收到報文后,繼續(xù)用自己的私鑰解密。最后是不是A公司的轉(zhuǎn)賬賬戶損失了一個億呢~

          ?

          C公司是怎么區(qū)分報文是不是來自A呢,還是被中間人修改過呢?為了表明身份和報文真實性,這就需要「加簽驗簽」啦!

          ?

          A公司把自己的公鑰也發(fā)送給C公司,私鑰自己保留著。在發(fā)起轉(zhuǎn)賬時,先用自己的私鑰對請求報文加簽,于是得到自己的數(shù)字簽名。再把數(shù)字簽名和請求報文一起發(fā)送給C公司。C公司收到報文后,拿A的公鑰進行驗簽,如果原始報文和數(shù)字簽名的摘要內(nèi)容不一致,那就是報文被篡改啦~

          ?

          有些朋友可能有疑問,假設(shè)A在發(fā)自己的公鑰給C公司的時候,也被中間人Actor截取了呢。嗯嗯,我們來模擬一波Actor又截取了公鑰,看看Actor能干出什么事情來~哈哈

          ?

          假設(shè)Actor截取到A的公鑰后,隨后也截取了到A發(fā)往C的報文。他截取到報文后,第一件想做的事肯定是修改報文內(nèi)容。但是如果單單修改原始報文是不可以的,因為發(fā)過去C公司肯定驗簽不過啦。但是呢,數(shù)字簽名似乎解不開,因為消息摘要算法(hash算法)無法逆向解開的,只起驗證的作用呢....

          ?

          所以呢,公鑰與私鑰是用來加密與加密的,「加簽與驗簽是用來證明身份」,以免被篡改的。

          常見加密相關(guān)算法簡介

          • 消息摘要算法
          • 對稱加密算法
          • 非對稱加密算法
          • 國密算法

          消息摘要算法:

          • 相同的明文數(shù)據(jù)經(jīng)過相同的消息摘要算法會得到相同的密文結(jié)果值。
          • 數(shù)據(jù)經(jīng)過消息摘要算法處理,得到的摘要結(jié)果值,是無法還原為處理前的數(shù)據(jù)的。
          • 數(shù)據(jù)摘要算法也被稱為哈希(Hash)算法或散列算法。
          • 消息摘要算法一般用于簽名驗簽。

          消息摘要算法主要分三類:MD(Message Digest,消息摘要算法)、SHA(Secure Hash Algorithm,安全散列算法)和MAC(Message Authentication Code,消息認證碼算法)。

          MD家族算法

          MD(Message Digest,消息摘要算法)家族,包括MD2,MD4,MD5。

          • MD2,MD4,MD5 計算的結(jié)果都是是一個128位(即16字節(jié))的散列值,用于確保信息傳輸完整一致。
          • MD2的算法較慢但相對安全,MD4速度很快,但安全性下降,MD5則比MD4更安全、速度更快。
          • MD5被廣泛應(yīng)用于數(shù)據(jù)完整性校驗、數(shù)據(jù)(消息)摘要、數(shù)據(jù)加密等。
          • MD5,可以被破解,對于需要高度安全性的數(shù)據(jù),專家一般建議改用其他算法,如SHA-2。2004年,證實MD5算法無法防止碰撞攻擊,因此不適用于安全性認證,如SSL公開密鑰認證或是數(shù)字簽名等用途。

          舉個例子,看看如何獲取字符串的MD5值吧:

          public?class?MD5Test?{

          ????public?static?void?main(String[]?args)?throws?UnsupportedEncodingException?{
          ????????String?s?=?"123";
          ????????byte[]?result?=?getMD5Bytes(s.getBytes());
          ????????StringBuilder?stringBuilder?=?new?StringBuilder();
          ????????for?(byte?temp?:?result)?{
          ????????????if?(temp?>=?0?&&?temp?????????????????stringBuilder.append("0");
          ????????????}
          ????????????stringBuilder.append(Integer.toHexString(temp?&?0xff));
          ????????}
          ????????System.out.println(s?+?",MD5加密后:"?+?stringBuilder.toString());
          ????}

          ????private?static?byte[]?getMD5Bytes(byte[]?content)?{
          ????????try?{
          ????????????MessageDigest?md5?=?MessageDigest.getInstance("MD5");
          ????????????return?md5.digest(content);
          ????????}?catch?(NoSuchAlgorithmException?e)?{
          ????????????throw?new?RuntimeException(e);
          ????????}
          ????}
          }


          運行結(jié)果:

          123,MD5加密后:202cb962ac59075b964b07152d234b70

          ShA家族算法

          SHA(Secure Hash Algorithm,安全散列算法),包括SHA-0、SHA-1、SHA-2(SHA-256,SHA-512,SHA-224,SHA-384等)、SHA-3。它是在MD算法基礎(chǔ)上實現(xiàn)的,與MD算法區(qū)別在于「摘要長度」,SHA 算法的摘要「長度更長,安全性更高」

          ?
          • SHA-0發(fā)布之后很快就被NSA撤回,因為含有會降低密碼安全性的錯誤,它是SHA-1的前身。
          • SHA-1在許多安全協(xié)議中廣為使用,包括TLS、GnuPG、SSH、S/MIME和IPsec,是MD5的后繼者。
          • SHA-2包括SHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256。它的算法跟SHA-1基本上相似,目前還沒有出現(xiàn)明顯弱點。
          • SHA-3是2015年正式發(fā)布,由于對「MD5出現(xiàn)成功的破解」,以及對SHA-0和SHA-1出現(xiàn)理論上破解的方法,SHA-3應(yīng)運而生。它與之前算法不同的是,它是可替換的加密散列算法。
          ?

          SHA-1、SHA-2(SHA-256,SHA-512,SHA-224,SHA-384)等算法是比較常用的,我們來看看跟MD5的對比吧

          算法類型摘要長度(bits)最大輸入消息長度(bits)碰撞攻擊(bits)性能示例(MiB/s)
          MD5128無限≤18(發(fā)現(xiàn)碰撞)335
          SHA-11602^64 ? 1<63(發(fā)現(xiàn)碰撞)192
          SHA-2242242^64 ? 1112139
          SHA-2562562^64 ? 1128139
          SHA-3843842^128 ? 1192154
          SHA-5125122^128 ? 1256154

          MAC算法家族

          MAC算法 MAC(Message Authentication Code,消息認證碼算法),是帶密鑰的Hash函數(shù)。輸入密鑰和消息,輸出一個消息摘要。它集合了MD和SHA兩大系列消息摘要算法。

          • MD 系列算法: HmacMD2、HmacMD4 和 HmacMD5 ;
          • SHA 系列算法:HmacSHA1、HmacSHA224、HmacSHA256、HmacSHA384 和 HmacSHA512 。

          對稱加密算法

          加密和解密使用「相同密鑰」的加密算法就是對稱加密算法。常見的對稱加密算法有AES、3DES、DES、RC5、RC6等。

          DES

          數(shù)據(jù)加密標準(英語:Data Encryption Standard,縮寫為 DES)是一種對稱密鑰加密塊密碼算法。DES算法的入口參數(shù)有三個:Key、Data、Mode。

          • Key: 7個字節(jié)共56位,是DES算法的工作密鑰;
          • Data: 8個字節(jié)64位,是要被加密或被解密的數(shù)據(jù);
          • Mode: 加密或解密。

          3DES

          三重數(shù)據(jù)加密算法(英語:Triple Data Encryption Algorithm,又稱3DES(Triple DES),是一種對稱密鑰加密塊密碼,相當(dāng)于是對每個數(shù)據(jù)塊應(yīng)用三次數(shù)據(jù)加密標準(DES)算法。

          AES

          AES,高級加密標準(英語:Advanced Encryption Standard),在密碼學(xué)中又稱Rijndael加密法,是美國聯(lián)邦政府采用的一種區(qū)塊加密標準。

          • 采用對稱分組密碼體制,密鑰長度為 128 位、 192 位、256 位,分組長度128位
          • 相對于DES ,AES具有更好的 安全性、效率 和 靈活性。

          非對稱加密算法

          非對稱加密算法需要兩個密鑰:公鑰和私鑰。公鑰與私鑰是成對存在的,如果用公鑰對數(shù)據(jù)進行加密,只有用對應(yīng)的私鑰才能解密。主要的非對稱加密算法有:RSA、Elgamal、DSA、D-H、ECC。

          RSA算法

          • RSA加密算法是一種非對稱加密算法,廣泛應(yīng)用于加密和數(shù)字簽名
          • RSA算法原理:兩個大素數(shù)的乘積進行因式分解卻極其困難,因此可以將乘積公開作為加密密鑰。
          • RSA是被研究得最廣泛的公鑰算法,從提出到現(xiàn)在,經(jīng)歷了各種攻擊的考驗,普遍認為是目前最優(yōu)秀的公鑰方案之一。

          DSA

          • DSA(Digital Signature Algorithm,數(shù)字簽名算法),也是一種非對稱加密算法。
          • DSA和RSA區(qū)別在,DSA僅用于數(shù)字簽名,不能用于數(shù)據(jù)加密解密。其安全性和RSA相當(dāng),但其性能要比RSA好。

          ECC 算法

          • ECC(Elliptic Curves Cryptography,橢圓曲線密碼編碼學(xué)),基于橢圓曲線加密。
          • Ecc主要優(yōu)勢是,在某些情況下,它比其他的方法使用更小的密鑰,比如RSA加密算法,提供相當(dāng)?shù)幕蚋叩燃壍陌踩墑e。
          • 它的一個缺點是,加密和解密操作的實現(xiàn)比其他機制時間長 (相比RSA算法,該算法對CPU 消耗嚴重)。

          國密算法

          國密即國家密碼局認定的國產(chǎn)密碼算法。為了保障商用密碼的安全性,國家商用密碼管理辦公室制定了一系列密碼標準,即SM1,SM2,SM3,SM4等國密算法。

          SM1

          • SM1,為對稱加密算法,加密強度為128位,基于硬件實現(xiàn)。
          • SM1的加密強度和性能,與AES相當(dāng)。

          SM2

          • SM2主要包括三部分:簽名算法、密鑰交換算法、加密算法
          • SM2用于替換RSA加密算法,基于ECC,效率較低。

          SM3

          • SM3,即國產(chǎn)消息摘要算法。
          • 適用于商用密碼應(yīng)用中的數(shù)字簽名和驗證,消息認證碼的生成與驗證以及隨機數(shù)的生成。

          SM4

          • SM4是一個分組算法,用于無線局域網(wǎng)產(chǎn)品。
          • 該算法的分組長度為128比特,密鑰長度為128比特。
          • 加密算法與密鑰擴展算法都采用32輪非線性迭代結(jié)構(gòu)。
          • 解密算法與加密算法的結(jié)構(gòu)相同,只是輪密鑰的使用順序相反,解密輪密鑰是加密輪密鑰的逆序。
          • 它的功能類似國際算法的DES。

          加簽驗簽相關(guān)Java的API

          這個小節(jié)先介紹一下加簽驗簽需要用到的API吧~

          加簽相關(guān)API

          -?java.security.Signature.getInstance(String?algorithm);?//根據(jù)對應(yīng)算法,初始化簽名對象
          -?KeyFactory.getInstance(String?algorithm);//?根據(jù)對應(yīng)算法,生成KeyFactory對象
          -?KeyFactory.generatePrivate(KeySpec?keySpec);?//生成私鑰
          -?java.security.Signature.initSign(PrivateKey?privateKey)?//由私鑰,初始化加簽對象
          -?java.security.Signature.update(byte[]?data)??//把原始報文更新到加簽對象
          -?java.security.Signature.sign();//加簽

          「Signature.getInstance(String algorithm);」

          • 根據(jù)對應(yīng)算法,初始化簽名對象
          • algorithm參數(shù)可以取SHA256WithRSA或者MD5WithRSA等參數(shù),SHA256WithRSA表示生成摘要用的是SHA256算法,簽名加簽用的是RSA算法

          「KeyFactory.getInstance(String algorithm);」

          • 根據(jù)對應(yīng)算法,生成KeyFactory對象,比如你的公私鑰用的是RSA算法,那么就傳入RSA

          「KeyFactory.generatePrivate(KeySpec keySpec)」

          • 生成私鑰,加簽用的是私鑰哈,所以需要通過KeyFactory先構(gòu)造一個私鑰對象。

          「Signature.initSign(PrivateKey privateKey)」

          • 加簽用的是私鑰,所以傳入私鑰,初始化加簽對象

          「Signature.update(byte[] data)」

          • 把原始報文更新到加簽對象

          「java.security.Signature.sign();」

          • 進行加簽操作

          驗簽相關(guān)API

          -?java.security.Signature.getInstance(String?algorithm);?//根據(jù)對應(yīng)算法,初始化簽名對象
          -?KeyFactory.getInstance(String?algorithm);//?根據(jù)對應(yīng)算法,生成KeyFactory對象
          -?KeyFactory.generatePublic(KeySpec?keySpec);?//生成公鑰
          -?java.security.Signature.initVerify(publicKey);?//由公鑰,初始化驗簽對象
          -?java.security.Signature.update(byte[]?data)??//把原始報文更新到驗簽對象
          -?java.security.Signature.verify(byte[]?signature);//驗簽

          「Signature.getInstance(String algorithm)」

          • 根據(jù)對應(yīng)算法,初始化簽名對象,注意驗簽和加簽是需要用相同的algorithm算法參數(shù)哦~

          「KeyFactory.getInstance(String algorithm);」

          • 根據(jù)對應(yīng)算法,生成KeyFactory對象

          「KeyFactory.generatePublic(KeySpec keySpec);」

          • 生成公鑰,驗簽用的是公鑰,通過KeyFactory先構(gòu)造一個公鑰對象
          「Signature.initVerify(publicKey);」
          • 公鑰驗簽,所以傳入公鑰對象參數(shù),初始化驗簽對象

          「Signature.update(byte[] data)」

          • 把原始報文更新到加簽對象

          「Signature.verify(byte[] signature);」

          • 進行驗簽操作

          加簽驗簽代碼實現(xiàn)

          前幾個小節(jié)討論完概念,是時候上代碼實戰(zhàn)了,我這邊用的是SHA-256作為摘要算法,RSA作為簽名驗簽算法,如下:

          package?pattern;

          import?sun.misc.BASE64Decoder;
          import?sun.misc.BASE64Encoder;

          import?java.io.IOException;
          import?java.io.UnsupportedEncodingException;
          import?java.security.*;
          import?java.security.spec.InvalidKeySpecException;
          import?java.security.spec.PKCS8EncodedKeySpec;

          /**
          ?*?加簽驗簽demo
          ?*??@Author?撿田螺的小男孩
          ?*/
          public?class?SignatureTest?{
          ????//公鑰字符串
          ????private?static?final?String?PUBLIC_KEY_STR?=?"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDaJzVjC5K6kbS2YE2fiDs6H8pB\n"?+
          ????????????"JFDGEYqqJJC9I3E0Ebr5FsofdImV5eWdBSeADwcR9ppNbpORdZmcX6SipogKx9PX\n"?+
          ????????????"5aAO4GPesroVeOs91xrLEGt/arteW8iSD+ZaGDUVV3+wcEdci/eCvFlc5PUuZJou\n"?+
          ????????????"M2XZaDK4Fg2IRTfDXQIDAQAB";
          ????//私鑰字符串
          ????private?static?final?String?PRIVATE_KEY_STR?=?"MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANonNWMLkrqRtLZg\n"?+
          ????????????"TZ+IOzofykEkUMYRiqokkL0jcTQRuvkWyh90iZXl5Z0FJ4APBxH2mk1uk5F1mZxf\n"?+
          ????????????"pKKmiArH09floA7gY96yuhV46z3XGssQa39qu15byJIP5loYNRVXf7BwR1yL94K8\n"?+
          ????????????"WVzk9S5kmi4zZdloMrgWDYhFN8NdAgMBAAECgYA9bz1Bn0i68b2KfqRdgOfs/nbe\n"?+
          ????????????"0XNN1DLQp2t7WDfRCg01iI1zPkZgyFVZWtI85f5/uIrLs5ArLosL1oNuqqc0nNne\n"?+
          ????????????"CvJK+ZxvA98Hx3ZqYTzDnleR054YhofL5awbhSciYVic204DOG1rhSsYWMqtX7J7\n"?+
          ????????????"3geoWL7TYdMfYXcCAQJBAPMMKsz6ZJh98EeQ1tDG5gpAGWFQkYNrxZDelP/LjeO0\n"?+
          ????????????"TP3XkQnIpcaZoCs7V/rRGRGMWwQ2BUdc/01in89ZZ5ECQQDlx2oBc1CtOAm2UAhN\n"?+
          ????????????"1xWrPkZWENQ53wTrwXO4qbTGDfBKon0AehLlGCSqxQ71aufLkNO7ZlX0IHTAlnk1\n"?+
          ????????????"TvENAkAGSEQ69CXxgx/Y2beTwfBkR2/gghKg0QJUUkyLqBlMz3ZGAXJwTE1sqr/n\n"?+
          ????????????"HiuSAiGhwH0ByNuuEotO1sPGukrhAkAMK26a2w+nzPL+u+hkrwKPykGRZ1zGH+Cz\n"?+
          ????????????"19AYNKzFXJGgclCqiMydY5T1knBDYUEbj/UW1Mmyn1FvrciHoUG1AkAEMEIuDauz\n"?+
          ????????????"JabEAU08YmZw6OoDGsukRWaPfjOEiVhH88p00veM1R37nwhoDMGyEGXVeVzNPvk7\n"?+
          ????????????"cELg28MSRzCK";


          ????public?static?void?main(String[]?args)?throws?SignatureException,?NoSuchAlgorithmException,?InvalidKeyException,?IOException,?InvalidKeySpecException?{
          ????????//原始報文
          ????????String?plain?=?"歡迎大家關(guān)注我的公眾號,撿田螺的小男孩";
          ????????//加簽
          ????????byte[]?signatureByte?=?sign(plain);
          ????????System.out.println("原始報文是:"?+?plain);
          ????????System.out.println("加簽結(jié)果:");
          ????????System.out.println(new?BASE64Encoder().encode(signatureByte));
          ????????//驗簽
          ????????boolean?verifyResult?=?verify(plain,?signatureByte);
          ????????System.out.println("驗簽結(jié)果:"?+?verifyResult);
          ????}

          ????/**
          ?????*?加簽方法
          ?????*?@param?plain
          ?????*?@return
          ?????*?@throws?NoSuchAlgorithmException
          ?????*?@throws?InvalidKeyException
          ?????*?@throws?UnsupportedEncodingException
          ?????*?@throws?SignatureException
          ?????*/
          ????private?static?byte[]?sign(String?plain)?throws?NoSuchAlgorithmException,?InvalidKeyException,?UnsupportedEncodingException,?SignatureException?{
          ????????//根據(jù)對應(yīng)算法,獲取簽名對象實例
          ????????Signature?signature?=?Signature.getInstance("SHA256WithRSA");
          ????????//獲取私鑰,加簽用的是私鑰,私鑰一般是在配置文件里面讀的,這里為了演示方便,根據(jù)私鑰字符串生成私鑰對象
          ????????PrivateKey?privateKey?=?getPriveteKey(PRIVATE_KEY_STR);
          ????????//初始化簽名對象
          ????????signature.initSign(privateKey);
          ????????//把原始報文更新到對象
          ????????signature.update(plain.getBytes("UTF-8"));
          ????????//加簽
          ????????return?signature.sign();
          ????}

          ????/**
          ?????*?驗簽方法
          ?????*?@param?plain
          ?????*?@param?signatureByte
          ?????*?@return
          ?????*?@throws?NoSuchAlgorithmException
          ?????*?@throws?InvalidKeyException
          ?????*?@throws?IOException
          ?????*?@throws?SignatureException
          ?????*?@throws?InvalidKeySpecException
          ?????*/
          ????private?static?boolean?verify(String?plain,?byte[]?signatureByte)?throws?NoSuchAlgorithmException,?InvalidKeyException,?IOException,?SignatureException,?InvalidKeySpecException?{
          ????????//獲取公鑰
          ????????PublicKey?publicKey?=?getPublicKey(PUBLIC_KEY_STR);
          ????????//根據(jù)對應(yīng)算法,獲取簽名對象實例
          ????????Signature?signature?=?Signature.getInstance("SHA256WithRSA");
          ????????//初始化簽名對象
          ????????signature.initVerify(publicKey);
          ????????//把原始報文更新到簽名對象
          ????????signature.update(plain.getBytes("UTF-8"));
          ????????//進行驗簽
          ????????return?signature.verify(signatureByte);
          ????}

          ????private?static?PublicKey?getPublicKey(String?publicKeyStr)?throws?InvalidKeySpecException,?IOException?{
          ????????PublicKey?publicKey?=?null;
          ????????try?{
          ????????????java.security.spec.X509EncodedKeySpec?bobPubKeySpec?=?new?java.security.spec.X509EncodedKeySpec(
          ????????????????????new?BASE64Decoder().decodeBuffer(publicKeyStr));
          ????????????//?RSA對稱加密算法
          ????????????java.security.KeyFactory?keyFactory;
          ????????????keyFactory?=?java.security.KeyFactory.getInstance("RSA");
          ????????????//?生成公鑰對象
          ????????????publicKey?=?keyFactory.generatePublic(bobPubKeySpec);
          ???????????}?catch?(NoSuchAlgorithmException?e)?{
          ?????????????e.printStackTrace();
          ????????????}
          ????????return?publicKey;
          ??????}

          ????private?static?PrivateKey?getPriveteKey(String?privateKeyStr)?{
          ????????PrivateKey?privateKey?=?null;
          ????????PKCS8EncodedKeySpec?priPKCS8;
          ????????try?{
          ????????????priPKCS8?=?new?PKCS8EncodedKeySpec(new?BASE64Decoder().decodeBuffer(privateKeyStr));
          ????????????KeyFactory?keyf?=?KeyFactory.getInstance("RSA");
          ????????????privateKey?=?keyf.generatePrivate(priPKCS8);
          ????????}?catch?(IOException?|?NoSuchAlgorithmException?|?InvalidKeySpecException?e)?{
          ????????????e.printStackTrace();
          ????????}
          ????????return?privateKey;
          ????}
          }

          「運行結(jié)果:」

          原始報文是:歡迎大家關(guān)注我的公眾號,撿田螺的小男孩
          加簽結(jié)果:
          Oz15/aybGe42eGHbc+iMoSYHSCc8tfRskTVjjGSTPD4HjadL0CC5JUWNUW0WxHjUb4MvxWo2oeWE
          Qw0+m61d+JgBMto/TWcVDcgwL/AbObsbWdQ6E/fVRqG13clkE8MyKsjt9Z7tcbwpycYTv0rUR4co
          rndAVfBdtv5KeV+OXqM=
          驗簽結(jié)果:true



          推薦閱讀:

          實戰(zhàn):一鍵生成前后端代碼,Mybatis-Plus代碼生成器讓我舒服了
          為什么要重寫 hashcode 和 equals 方法?
          SpringBoot @Value 解析集合配置

          瀏覽 121
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  成人女a在线免费 | 在线观看国内精品人 | 挨操成人免费视频 | 麻豆成人久久精品 | 麻豆亚洲AV成人无码久久精品 |