数据安全-身份验证
即使我們保證了數(shù)據(jù)的機(jī)密性和完整性,這里面仍然存在一些問(wèn)題:
-
接收方若要驗(yàn)證消息完整性,必須得到發(fā)送方對(duì)消息產(chǎn)生的摘要,若第三方得知摘要算法,那摘要也是可以被偽造的,因此摘要本身也需要被加密。
-
消息發(fā)送來(lái)源如何確定,怎么確定不是第三方偽造的?
發(fā)送方將消息原文使用摘要算法生成摘要,再用私鑰對(duì)摘要進(jìn)行加密,生成數(shù)字簽名,然后將內(nèi)容附上數(shù)字簽名一起傳輸。
? 接收方收到消息后,用發(fā)送方的公鑰對(duì)數(shù)字簽名進(jìn)行解密(能解密成功就完成了對(duì)發(fā)送方的身份驗(yàn)證),得到摘要A,然后再對(duì)原文使用摘要算法生成摘要B,比對(duì)摘要A和B是否相同,相同則說(shuō)明內(nèi)容沒(méi)有被篡改。
?下面例子演示了使用SHA1作為摘要算法,使用RSA作為簽名加密算法的簽名及驗(yàn)簽過(guò)程,在RSAEncrypt.java中增加以下代碼:
public static final String SIGN_ALGORITHMS = "SHA1WithRSA";/*** RSA簽名* @param content 待簽名數(shù)據(jù)* @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驗(yàn)簽名檢查* @param content 待簽名數(shù)據(jù)* @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; }測(cè)試方法如下:
/*** 測(cè)試SHA1WithRSA簽名、驗(yàn)證簽名*/ @Test public void test3() throws Exception {Map<Integer, String> akeyMap = RSAEncrypt.genKeyPair();//a方密鑰對(duì)System.out.println("隨機(jī)生成的a方公鑰為:" + akeyMap.get(0));System.out.println("隨機(jī)生成的a方私鑰為:" + akeyMap.get(1));String content = "你好世界";System.out.println("------------a向b發(fā)送數(shù)據(jù),使用a的私鑰生成簽名-----------");String signature = RSAEncrypt.sign(content, akeyMap.get(1), "utf-8");System.out.println("原文:'" +content+ "'生成簽名:" + signature);System.out.println("----------b接收到a發(fā)的數(shù)據(jù),使用a的公鑰驗(yàn)證簽名-----------");if (RSAEncrypt.verify(content, signature, akeyMap.get(0), "utf-8")) {System.out.println("驗(yàn)證簽名成功:" + signature);} else {System.out.println("驗(yàn)證簽名失敗!");} }總結(jié):
通過(guò)加密算法對(duì)數(shù)據(jù)原文的加密、解密,我們能保證數(shù)據(jù)傳輸過(guò)程中的機(jī)密性。
通過(guò)數(shù)字簽名機(jī)制,我們既可以保證數(shù)據(jù)完整性,也可以對(duì)數(shù)據(jù)來(lái)源進(jìn)行身份驗(yàn)證。
針對(duì)非對(duì)稱加密技術(shù)的應(yīng)用,我們通常使用兩種方式:
傳輸過(guò)程中的數(shù)據(jù)加密,我們使用接收方公鑰加密,接收方私鑰解密,保證數(shù)據(jù)在傳輸過(guò)程中是密文。
接收方對(duì)信息來(lái)源的確認(rèn),發(fā)送方會(huì)使用私鑰對(duì)數(shù)據(jù)簽名,接收方使用發(fā)送方公鑰進(jìn)行驗(yàn)簽。
總結(jié)