加入收藏 | 设为首页 | 会员中心 | 我要投稿 核心网 (https://www.hxwgxz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

循序渐进学加密

发布时间:2019-06-25 19:06:39 所属栏目:建站 来源:张京
导读:还记得上初二的那年夏天,班里来了一个新同学,他就住在我家对面的楼里,于是我们一起上学放学,很快便成了最要好的朋友。我们决定发明一套神秘的沟通方式,任何人看到都不可能猜到它的真实含义。我们第一个想到的就是汉语拼音,但很显然光把一个句子变成

接下来我们看看Java端的解密代码该如何写:

  1. try { 
  2.     Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); 
  3.     cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec("这里是16字节密钥".getBytes(), "AES")); 
  4.     String plaintext = new String(cipher.doFinal(Base64.getDecoder().decode("这里是明文".getBytes())), "UTF-8"); 
  5.     System.out.println(plaintext); 
  6. } catch (Exception e) { 
  7.     System.out.println("解密出错:" + e.toString()); 

注意这里我们用到的是PKCS5Padding,上面加密的时候不是用的是pkcs7padding吗?怎么这里变成5了呢?

我们先来了解一下什么是pkcs。pkcs的全称是Public Key Cryptography Standards(公钥加密标准),这是RSA实验室制定的一系列的公钥密码编译标准,比较著名的有pkcs1, pkcs5, pkcs7, pkcs8这四个,它们分别管理的是不同的内容。在这里我们只是用它来填充,所以我们只关注pkcs5和pkcs7就够了。那么pkcs5和pkcs7有什么区别呢?其实在填充方面它们两个的算法是一样的,pkcs5是pkcs7的一个子集,区别在于pkcs5是8字节固定的,而pkcs7可以是1到255之间的任意字节。但用在AES算法上,因为AES标准规定块大小必须是16字节或者24字节或者32字节,不可能用pkcs5的8字节,所以AES算法只能用pkcs7填充。但是由于java早期工程师犯的一个命名上的错误,他们把AES填充算法的名称设定为pkcs5,而实际实现中实现的是pkcs7,所以我们在java端开发解密的时候需要使用pkcs5。

AES-CBC

谈完了不安全的AES-ECB,我们来做一下相对安全一些的AES-CBC模式。

1. AES-CBC的Javascript加密

直接上代码:

  1. const cipher = forge.cipher.createCipher('AES-CBC', '这里是16字节密钥'); 
  2. cipher.start({ iv: '这里是16字节偏移量' }); 
  3. cipher.update(forge.util.createBuffer('这里是明文')); 
  4. cipher.finish(); 
  5. const result = forge.util.encode64(cipher.output.getBytes()); 

跟上面的AES-ECB差不多,唯一区别只是在start函数里定义了一个iv。

2. AES-CBC的Java解密

下面是Java代码:

  1. try { 
  2.     Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); 
  3.     cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec("这里是16字节密钥".getBytes(), "AES"), new IvParameterSpec("这里是16字节偏移量".getBytes())); 
  4.     String plaintext = new String(cipher.doFinal(Base64.getDecoder().decode("这里是明文".getBytes())), "UTF-8"); 
  5.     System.out.println(plaintext); 
  6. } catch (Exception e) { 
  7.     System.out.println("解密出错:" + e.toString()); 

也是同样,跟上面用AES-ECB时的模式几乎一模一样,只是增加了一个IvParameterSpec,用来生成iv,在cipher.init里面增加了一个iv参数,除此之外完全相同,就这样我们就已经实现了一个简单的CBC模式。

RSA

但是以上两种做法都明显是非常不安全的,因为我们把加密用的密钥和iv参数都直接暴露在了前端,为此我们需要一种更加安全的加密方法——RSA。因为RSA是非对称加密,即使我们把加密用的公钥完全暴露在前端也不必担心,别人即使截获了我们的密文,但因为他们没有解密密钥,是无法解出我们的明文的。

1. 生成密钥对

要用RSA加密,首先我们需要生成一个公钥和一个私钥,我们可以直接执行命令ssh-keygen。它会问我们密钥文件保存的文件夹,注意一定要单独找一个文件夹存放,不要放在缺省文件夹下,否则你日常使用的ssh公钥和私钥就都被覆盖了。

得到公钥文件之后,由于这个公钥文件是rfc4716格式的,而我们的forge库要求一个pkcs1格式的公钥,所以这里我们需要把它转换成pem格式(也就是pkcs1格式):

  1. ssh-keygen -f 公钥文件名 -m pem -e 

2. RSA的Javascript加密

得到pem格式的公钥之后,我们来看一下js的代码:

  1. forge.util.encode64(forge.pki.publicKeyFromPem('-----BEGIN RSA PUBLIC KEY-----MIIBCfdsafasfasfafsdaafdsaAB-----END RSA PUBLIC KEY-----').encrypt('这里是明文', 'RSA-OAEP', { md: forge.md.sha256.create(), mgf1: { md: forge.md.sha1.create() } }); 

一句话就完成整个加密过程了,这就是forge的强大之处。

3. RSA的Java解密

接下来我们看解密。

(编辑:核心网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读