数据安全-身份验证
即使我們保證了數據的機密性和完整性,這里面仍然存在一些問題:
-
接收方若要驗證消息完整性,必須得到發送方對消息產生的摘要,若第三方得知摘要算法,那摘要也是可以被偽造的,因此摘要本身也需要被加密。
-
消息發送來源如何確定,怎么確定不是第三方偽造的?
發送方將消息原文使用摘要算法生成摘要,再用私鑰對摘要進行加密,生成數字簽名,然后將內容附上數字簽名一起傳輸。
? 接收方收到消息后,用發送方的公鑰對數字簽名進行解密(能解密成功就完成了對發送方的身份驗證),得到摘要A,然后再對原文使用摘要算法生成摘要B,比對摘要A和B是否相同,相同則說明內容沒有被篡改。
?下面例子演示了使用SHA1作為摘要算法,使用RSA作為簽名加密算法的簽名及驗簽過程,在RSAEncrypt.java中增加以下代碼:
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";/*** RSA簽名* @param content 待簽名數據* @param privateKey 私鑰* @param input_charset 編碼格式* @return 簽名值*/ public static String sign(String content, String privateKey, String input_charset) {try {PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decoder.decode(privateKey));KeyFactory keyf = KeyFactory.getInstance("RSA");PrivateKey priKey = keyf.generatePrivate(priPKCS8);Signature signature = Signature.getInstance(SIGN_ALGORITHMS);signature.initSign(priKey);signature.update(content.getBytes(input_charset));byte[] signed = signature.sign();return encoder.encodeToString(signed);} catch (Exception e) {e.printStackTrace();}return null; }/*** RSA驗簽名檢查* @param content 待簽名數據* @param sign 簽名值* @param public_key 公鑰* @param input_charset 編碼格式* @return 布爾值*/ public static boolean verify(String content, String sign, String public_key, String input_charset) {try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");byte[] encodedKey = decoder.decode(public_key);PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));Signature signature = Signature.getInstance(SIGN_ALGORITHMS);signature.initVerify(pubKey);signature.update(content.getBytes(input_charset));boolean bverify = signature.verify(decoder.decode(sign));return bverify;} catch (Exception e) {e.printStackTrace();}return false; }測試方法如下:
/*** 測試SHA1WithRSA簽名、驗證簽名*/ @Test public void test3() throws Exception {Map<Integer, String> akeyMap = RSAEncrypt.genKeyPair();//a方密鑰對System.out.println("隨機生成的a方公鑰為:" + akeyMap.get(0));System.out.println("隨機生成的a方私鑰為:" + akeyMap.get(1));String content = "你好世界";System.out.println("------------a向b發送數據,使用a的私鑰生成簽名-----------");String signature = RSAEncrypt.sign(content, akeyMap.get(1), "utf-8");System.out.println("原文:'" +content+ "'生成簽名:" + signature);System.out.println("----------b接收到a發的數據,使用a的公鑰驗證簽名-----------");if (RSAEncrypt.verify(content, signature, akeyMap.get(0), "utf-8")) {System.out.println("驗證簽名成功:" + signature);} else {System.out.println("驗證簽名失敗!");} }總結:
通過加密算法對數據原文的加密、解密,我們能保證數據傳輸過程中的機密性。
通過數字簽名機制,我們既可以保證數據完整性,也可以對數據來源進行身份驗證。
針對非對稱加密技術的應用,我們通常使用兩種方式:
傳輸過程中的數據加密,我們使用接收方公鑰加密,接收方私鑰解密,保證數據在傳輸過程中是密文。
接收方對信息來源的確認,發送方會使用私鑰對數據簽名,接收方使用發送方公鑰進行驗簽。
總結