Java加密与安全 (4)

  PBE(Passwoord Based Encrytion)算法:由用户输入口令,采用随机数杂凑计算出密钥再进行加密,password:用户口令,例如"hello123",Salt:随机生成的byte[],密钥Key:generate(byte[] salt, String password)。如果把随机Salt存储在U盘,就得到了一个“口令”+USB Key加密软件,这样做的好处是即时用户使用非常弱的口令,没有USB Key仍然无法解密。

Java加密与安全

总结:PBE算法通过用户口令和随机数Salt计算Key然后加密,Key通过用户口令和随机数Salt计算得出,提高了安全性,PBE算法内部仍然使用的是标准对称加密算法(例如AES)。

密钥交换算法

  我们在使用对称加密算法的时候,我们的加密和解密使用的是同一个密钥Key。我们以AES加密为例,当我们要加密明文,我们需要使用一个随机生成的Key作为密钥进行加解密,最后我们的问题就是如何传递密钥?因为不给对方密钥,对方就无法解密,而直接传递密钥,会被黑客监听,所以问题就变成了:如何在不安全的信道上安全地传输密钥?密钥交换算法也就是Diff-Hellman算法,即DH算法。

Java加密与安全

甲首先选择一个素数P=509,然后在选择一个底数g和一个随机数a,然后计算 A=\(g^a\) mod p => 215

甲发送P=509,g=5,A=215,乙收到以后,也选择一个随机数b=456,然后计算 B=\(g^b\) mod p => 181,然后接着计算 s = \(A^b\) mod p => 121

乙把计算的B=181发送给甲,甲通过 s=\(B^a\) mod p 可以计算出也等于121。所以双方协商出的密钥就是121。

  要注意这个密钥并没有在网络上进行传输,通过网络传输的是p=509,g=5, A=215, B=181,但是通过这四个数,黑客是无法推算出密钥s的。更确切的说,DH算法它是一个密钥协商算法,双发最终协商出一个共同的密钥。我们把a看成是甲的私钥,A看成是甲的公钥,b看成是乙的私钥,B看成是乙的公钥,DH算法的本质就是:双方各自生成自己的私钥和公钥,然后交换公钥,并且根据自己的私钥和对方的公钥生成最终的密钥。DH算法根据数学定律保证了双方各自计算出来的key是相同的。

import javax.crypto.Cipher; import javax.crypto.KeyAgreement; import javax.crypto.SecretKey; import java.io.IOException; import java.math.BigInteger; import java.security.*; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; class Person { public final String name; // 表示人的名字 public PublicKey publicKey; // 表示这个人的公钥 public PrivateKey privateKey; // 表示这个人的私钥 public SecretKey secretKey; //表示最终的密钥 public Person(String name) { this.name = name; } //生成本地的KeyPair public void generateKeyPair() { try { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH"); keyGen.initialize(512); //创建一个512位的keyPair KeyPair keyPair = keyGen.generateKeyPair(); this.privateKey = keyPair.getPrivate(); this.publicKey = keyPair.getPublic(); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } } public void generateSecreteKey(byte[] recivedPUblickeyBytes) { //从byte[]恢复PublcKey try { X509EncodedKeySpec keySpec = new X509EncodedKeySpec(recivedPUblickeyBytes); KeyFactory kf = KeyFactory.getInstance("DH"); PublicKey recivedPublicKey = kf.generatePublic(keySpec); //生成本地密钥 KeyAgreement keyAgreement = KeyAgreement.getInstance("DH"); keyAgreement.init(this.privateKey); // 自己的私钥 keyAgreement.doPhase(recivedPublicKey,true); // 对方的公钥 //生成AES密钥 this.secretKey = keyAgreement.generateSecret("AES"); } catch (GeneralSecurityException e) { throw new RuntimeException(e); } } public void printKeys(){ System.out.printf("Name: %s\n", this.name); System.out.printf("private key: %x\n",new BigInteger(1,this.privateKey.getEncoded())); System.out.printf("public key: %x\n",new BigInteger(1,this.publicKey.getEncoded())); System.out.printf("secrete key: %x\n",new BigInteger(1,this.secretKey.getEncoded())); } //发送加密信息 public String sendMessage(String message){ try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE,this.secretKey); byte[] data = cipher.doFinal(message.getBytes("UTF-8")); return Base64.getEncoder().encodeToString(data); } catch (GeneralSecurityException |IOException e) { throw new RuntimeException(e); } } //接收加密信息并解密 public String reciveMessage(String message){ try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE,this.secretKey); byte[] data = cipher.doFinal(Base64.getDecoder().decode(message)); return new String(data,"UTF-8"); } catch (GeneralSecurityException |IOException e) { throw new RuntimeException(e); } } } public class DH { public static void main(String[] args) { //Bob和Alice Person bob = new Person("Bob"); Person alice = new Person("Alice"); //生成各自的keyPair bob.generateKeyPair(); alice.generateKeyPair(); //双方交换各自的public Key //Bob根据Alice的public Key生成自己的本地密钥 bob.generateSecreteKey(alice.publicKey.getEncoded()); //Alice根据Bob的public Key生成自己的本地密钥 alice.generateSecreteKey(bob.publicKey.getEncoded()); //检查双方的本地密钥是否相同 bob.printKeys(); alice.printKeys(); //双方的SecretKey相同,后续通信将使用SecretKey作为密钥进行AES加解密 String msgBobToAlice = bob.sendMessage("Hello, Alice!"); System.out.println("Bob -> Alice: " + msgBobToAlice); String aliceDecrypted = alice.reciveMessage(msgBobToAlice); System.out.println("Alice decrypted: " + aliceDecrypted); } }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpypfg.html