Java对称与非对称加密解密,AES与RSA

时间:2021-11-03 00:11:48

加密技术可以分为对称与非对称两种.

对称加密,解密,即加密与解密用的是同一把秘钥,常用的对称加密技术有DES,AES等

而非对称技术,加密与解密用的是不同的秘钥,常用的非对称加密技术有RSA等

为什么要有非对称加密,解密技术呢

假设这样一种场景A要发送一段消息给B,但是又不想以明文发送,所以就需要对消息进行加密.如果采用对称加密技术,那么加密与解密用的是同一把秘钥.除非B事先就知道A的秘钥,并且保存好.这样才可以解密A发来的消息.

由于对称技术只有一把秘钥,所以秘钥的管理是一个很麻烦的问题.而非对称技术的诞生就解决了这个问题.非对称加密与解密使用的是不同的秘钥,并且秘钥对是一一对应的,即用A的私钥加密的密文只有用A的公钥才能解密.

这样的话,每个人都有两把秘钥,私钥和公钥,私钥是只有自己才知道的,不能告诉别人,而公钥是公开的,大家都可以知道.这样,当A想要发送消息给B的时候,只需要用B的公钥对消息进行加密就可以了,由于B的私钥只有B才拥有,所以A用B的公钥加密的消息只有B才能解开.而B想更换自己的秘要时也很方便,只须把公钥告诉大家就可以了.

那么,既然非对称加密如此之好,对称加密就没有存在的必要了啊,其实不然,由于非对称加密算法的开销很大,所以如果直接以非对称技术来加密发送的消息效率会很差.那么怎么办呢?解决的办法也很简单,就是把对称加密技术与非对称加密技术结合起来使用.

还是这个例子:A要发送一个消息给B.

一,A先生成一个对称秘钥,这个秘钥可以是随机生成的,

二,A用B的公钥加密第一步生成的这个对称秘钥

三,A把加密过的对称秘钥发给B

四,A用第一步生成的这个对称秘钥加密实际要发的消息

五,A把用对称秘钥加密的消息发给B

对于B

他先收到A发来的对称秘钥,这个秘钥是用B的公钥加密过的,所以B需要用自己的私钥来解密这个秘钥

然后B又收到A发来的密文,这时候用刚才解密出来的秘钥来解密密文

这样子的整个过程既保证了安全,又保证了效率.

接下来是Java实现:

我这个Java实现使用的是AES的对称加密和RSA的非对称加密(DES的对称加密实现方法和AES的是一样的,但是由于DES算法本身有缺陷,容易被破解,所以现在多用其升级版AES对称加密)

AES对称加密,解密

  1. import java.io.IOException;
  2. import java.io.InputStream;
  3. import java.io.OutputStream;
  4. import java.security.InvalidKeyException;
  5. import java.security.Key;
  6. import java.security.NoSuchAlgorithmException;
  7. import java.security.SecureRandom;
  8. import javax.crypto.BadPaddingException;
  9. import javax.crypto.Cipher;
  10. import javax.crypto.IllegalBlockSizeException;
  11. import javax.crypto.KeyGenerator;
  12. import javax.crypto.NoSuchPaddingException;
  13. import javax.crypto.ShortBufferException;
  14. public class AES {
  15. private Key key;
  16. /**
  17. * 生成AES对称秘钥
  18. * @throws NoSuchAlgorithmException
  19. */
  20. public void generateKey() throws NoSuchAlgorithmException {
  21. KeyGenerator keygen = KeyGenerator.getInstance("AES");
  22. SecureRandom random = new SecureRandom();
  23. keygen.init(random);
  24. this.key = keygen.generateKey();
  25. }
  26. /**
  27. * 加密
  28. * @param in
  29. * @param out
  30. * @throws InvalidKeyException
  31. * @throws ShortBufferException
  32. * @throws IllegalBlockSizeException
  33. * @throws BadPaddingException
  34. * @throws NoSuchAlgorithmException
  35. * @throws NoSuchPaddingException
  36. * @throws IOException
  37. */
  38. public void encrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
  39. this.crypt(in, out, Cipher.ENCRYPT_MODE);
  40. }
  41. /**
  42. * 解密
  43. * @param in
  44. * @param out
  45. * @throws InvalidKeyException
  46. * @throws ShortBufferException
  47. * @throws IllegalBlockSizeException
  48. * @throws BadPaddingException
  49. * @throws NoSuchAlgorithmException
  50. * @throws NoSuchPaddingException
  51. * @throws IOException
  52. */
  53. public void decrypt(InputStream in, OutputStream out) throws InvalidKeyException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, IOException {
  54. this.crypt(in, out, Cipher.DECRYPT_MODE);
  55. }
  56. /**
  57. * 实际的加密解密过程
  58. * @param in
  59. * @param out
  60. * @param mode
  61. * @throws IOException
  62. * @throws ShortBufferException
  63. * @throws IllegalBlockSizeException
  64. * @throws BadPaddingException
  65. * @throws NoSuchAlgorithmException
  66. * @throws NoSuchPaddingException
  67. * @throws InvalidKeyException
  68. */
  69. public void crypt(InputStream in, OutputStream out, int mode) throws IOException, ShortBufferException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
  70. Cipher cipher = Cipher.getInstance("AES");
  71. cipher.init(mode, this.key);
  72. int blockSize = cipher.getBlockSize();
  73. int outputSize = cipher.getOutputSize(blockSize);
  74. byte[] inBytes = new byte[blockSize];
  75. byte[] outBytes = new byte[outputSize];
  76. int inLength = 0;
  77. boolean more = true;
  78. while (more) {
  79. inLength = in.read(inBytes);
  80. if (inLength == blockSize) {
  81. int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
  82. out.write(outBytes, 0, outLength);
  83. } else {
  84. more = false;
  85. }
  86. }
  87. if (inLength > 0)
  88. outBytes = cipher.doFinal(inBytes, 0, inLength);
  89. else
  90. outBytes = cipher.doFinal();
  91. out.write(outBytes);
  92. out.flush();
  93. }
  94. public void setKey(Key key) {
  95. this.key = key;
  96. }
  97. public Key getKey() {
  98. return key;
  99. }
  100. }

RSA非对称加密,解密对称秘钥

  1. public class RSA {
  2. public static final int KEYSIZE = 512;
  3. private KeyPair keyPair;
  4. private Key publicKey;
  5. private Key privateKey;
  6. /**
  7. * 生成秘钥对
  8. * @return
  9. * @throws NoSuchAlgorithmException
  10. */
  11. public KeyPair generateKeyPair() throws NoSuchAlgorithmException {
  12. KeyPairGenerator pairgen = KeyPairGenerator.getInstance("RSA");
  13. SecureRandom random = new SecureRandom();
  14. pairgen.initialize(RSA.KEYSIZE, random);
  15. this.keyPair = pairgen.generateKeyPair();
  16. return this.keyPair;
  17. }
  18. /**
  19. * 加密秘钥
  20. * @param key
  21. * @return
  22. * @throws NoSuchAlgorithmException
  23. * @throws NoSuchPaddingException
  24. * @throws InvalidKeyException
  25. * @throws IllegalBlockSizeException
  26. */
  27. public byte[] wrapKey(Key key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException {
  28. Cipher cipher = Cipher.getInstance("RSA");
  29. cipher.init(Cipher.WRAP_MODE, this.privateKey);
  30. byte[] wrappedKey = cipher.wrap(key);
  31. return wrappedKey;
  32. }
  33. /**
  34. * 解密秘钥
  35. * @param wrapedKeyBytes
  36. * @return
  37. * @throws NoSuchAlgorithmException
  38. * @throws NoSuchPaddingException
  39. * @throws InvalidKeyException
  40. */
  41. public Key unwrapKey(byte[] wrapedKeyBytes) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
  42. Cipher cipher = Cipher.getInstance("RSA");
  43. cipher.init(Cipher.UNWRAP_MODE, this.publicKey);
  44. Key key = cipher.unwrap(wrapedKeyBytes, "AES", Cipher.SECRET_KEY);
  45. return key;
  46. }
  47. public Key getPublicKey() {
  48. return publicKey;
  49. }
  50. public void setPublicKey(Key publicKey) {
  51. this.publicKey = publicKey;
  52. }
  53. public Key getPrivateKey() {
  54. return privateKey;
  55. }
  56. public void setPrivateKey(Key privateKey) {
  57. this.privateKey = privateKey;
  58. }
  59. }