控制加密和解密过程的指令称为什么(Java开发中的加密、解密、签名、验签,密钥,证书(上篇))

Posted

篇首语:我会努力奋斗直到亮瞎你们的双眼。本文由小常识网(cha138.com)小编为大家整理,主要介绍了控制加密和解密过程的指令称为什么(Java开发中的加密、解密、签名、验签,密钥,证书(上篇))相关的知识,希望对你有一定的参考价值。

控制加密和解密过程的指令称为什么(Java开发中的加密、解密、签名、验签,密钥,证书(上篇))

OpenSSL和keytool

先说一下两个重要的工具

  • OpenSSL:OpenSSL整个软件包大概可以分成三个主要的功能部分:SSL协议库libssl、应用程序命令工具以及密码算法库libcrypto。它使用标准的文件格式(PEM/CER/CRT/PKCS等)存储密钥和证书信息。
  • keytool:是密钥和证书管理工具。它出自于Java体系,它使用KeyStore来管理密钥和证书。

两者都是可以用来生成加密密钥的工具,keytool出自Java体系,它可以直接操作KeyStore,而OpenSSL不支持直接操作KeyStore。实际情况有可能是这样的,使用OpenSSL生成了密钥或证书,然后使用keytool将其导入到KeyStore以便在Java环境中使用。

当然OpenSSL还具备其他功能比如作为SSL的客户端和服务器,这是keytool所不具备的。

对称加密

采用单钥密码系统的加密方法,同一个密钥可以同时用作信息的加密和解密,这种加密方法称为对称加密,也称为单密钥加密。——百度百科

对称加密算法的特点

  • 加密和解密使用同样的密钥
  • 计算速度快,适用于对大量数据加密处理
  • 安全性取决于算法,也取决于密钥的管理,一旦密钥泄漏,数据则暴露无遗

对称加密算法的使用场景

基于上述的特点,在一些需要高效实时传输的加密通讯场景中,比如使用VPN或者代理进行通讯时,可以使用对称加密。另外在同一个系统内部不同模块,比如前后端,从前端输入的敏感信息,可以使用对称加密算法进行加密后将密文传到后端,避免传输过程中明文被截获,因为同系统内部之间密钥管理相对容易,而对于共享密钥有泄漏风险的其他任何场景,则不适合使用对称加密算法进行加密。

常见的对称加密算法

算法 描述 DES(Data Encryption Standard) 数据加密标准,速度较快,适用于加密大量数据 3DES(Triple DES) 基于DES,对一块数据用三个不同的密钥进行三次加密,强度更高 AES(Advanced Encryption Standard) 高级加密标准,速度快,安全级别高,支持128、192、256、512位密钥的加密 Blowfish 速度快且安全,而且没有专利和商业限制。了解更多>>

OpenSSL实现对称加密

OpenSSL> enc --helpusage: enc -ciphername [-AadePp] [-base64] [-bufsize number] [-debug]    [-in file] [-iv IV] [-K key] [-k password]    [-kfile file] [-md digest] [-none] [-nopad] [-nosalt]    [-out file] [-pass arg] [-S salt] [-salt] -A                 Process base64 data on one line (requires -a) -a                 Perform base64 encoding/decoding (alias -base64) -bufsize size      Specify the buffer size to use for I/O -d                 Decrypt the input data -debug             Print debugging information -e                 Encrypt the input data (default) -in file           Input file to read from (default stdin) -iv IV             IV to use, specified as a hexadecimal string -K key             Key to use, specified as a hexadecimal string -md digest         Digest to use to create a key from the passphrase -none              Use NULL cipher (no encryption or decryption) -nopad             Disable standard block padding -out file          Output file to write to (default stdout) -P                 Print out the salt, key and IV used, then exit                      (no encryption or decryption is performed) -p                 Print out the salt, key and IV used -pass source       Password source -S salt            Salt to use, specified as a hexadecimal string -salt              Use a salt in the key derivation routines (default) -v                 Verbose

命令选项 描述 -in file 被加密文件的全路径 -out file 加密后内容输出的文件路径 -salt 自动插入一个随机数作为文件内容加密,默认选项 -e 加密模式,默认 -d 解密模式,需要与加密算法一致 -a 使用-base64位编码格式,也可使用-base64 -pass source 指定密码的输入方式,共有五种方式:命令行输入(stdin)、文件输入(file)、环境变量输入(var)、文件描述符输入(fd)、标准输入(stdin)。默认是标准输入即从键盘输入

只对文件进行base64编码,而不使用加解密

/*对文件进行base64编码*/openssl enc -base64 -in plain.txt -out base64.txt/*对base64格式文件进行解密操作*/openssl enc -base64 -d -in base64.txt -out plain2.txt/*使用diff命令查看可知解码前后明文一样*/diff plain.txt plain2.txt

不同方式的密码输入方式

/*命令行输入,密码123456*/openssl enc -aes-128-cbc -in plain.txt -out out.txt -pass pass:123456/*文件输入,密码123456*/echo 123456 > passwd.txtopenssl enc -aes-128-cbc -in plain.txt -out out.txt -pass file:passwd.txt/*环境变量输入,密码123456*/passwd=123456export passwdopenssl enc -aes-128-cbc -in plain.txt -out out.txt -pass env:passwd/*从文件描述输入*/ openssl enc -aes-128-cbc -in plain.txt -out out.txt -pass fd:1  /*从标准输入输入*/ openssl enc -aes-128-cbc -in plain.txt -out out.txt -pass stdin 

Java实现对称加密

DES

/** * 生成 DES 算法密钥 * @return byte[] * @throws Exception */public static byte[] generateDESKey() throws Exception     KeyGenerator keyGenerator = KeyGenerator.getInstance("DES");    // must be equal to 56    keyGenerator.init(56);    SecretKey secretKey = keyGenerator.generateKey();    byte[] encodedKey = secretKey.getEncoded();    return encodedKey;/** * DES加密 * @param encodedKey generateDESKey生成的密钥 * @param dataBytes byte[]形式的待加密数据 * @return byte[] * @throws Exception */public static byte[] encryptByDES(byte[] encodedKey, byte[] dataBytes) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "DES");    Cipher cipher = Cipher.getInstance("DES");    cipher.init(Cipher.ENCRYPT_MODE, secretKey);    byte[] encryptedData = cipher.doFinal(dataBytes);    return encryptedData;/** * DES解密 * @param encodedKey generateDESKey生成的密钥 * @param encryptedData byte[]形式的待解密数据 * @return byte[] * @throws Exception */public static byte[] decryptByDES(byte[] encodedKey, byte[] encryptedData) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "DES");    Cipher cipher = Cipher.getInstance("DES");    cipher.init(Cipher.DECRYPT_MODE, secretKey);    byte[] decryptedData = cipher.doFinal(encryptedData);    return decryptedData;

基础版本使用方法如下:

@Testpublic void testDES_1() throws Exception     byte[] encodedKey = SecurityUtil.generateDESKey();    String data = "this is a good boy";    byte[] encryptedData = SecurityUtil.encryptByDES(encodedKey, data.getBytes());    byte[] decryptedData = SecurityUtil.decryptByDES(encodedKey, encryptedData);    Assert.assertEquals(data, new String(decryptedData));

可以看到,以上的方法使用起来并不友好,参数、返回等大量存在byte[],不便于理解,中间结果不便于查看和传输,比如如果需要将encryptedData返回给下游系统,那么还得使用Base64进行处理,基于此,我对在上述接口基础上进一步进行封装,使其使用起来更贴近日常使用场景。

优化版本:

/** * 生成 DES 算法密钥 * @return 经过Base64编码的字符串密钥 * @throws Exception */public static String generateDESKeyStr() throws Exception     return Base64.encodeBase64String(generateDESKey());/** * DES加密 * @param key 经过Base64编码的字符串密钥 * @param data String形式的待加密数据 * @return 经过Base64编码的加密数据 * @throws Exception */public static String encryptByDES(String key, String data) throws Exception     byte[] encodedKey = Base64.decodeBase64(key);    byte[] dataBytes = data.getBytes();    byte[] encryptedData = encryptByDES(encodedKey, dataBytes);    return Base64.encodeBase64String(encryptedData);/** * DES解密 * @param key 经过Base64编码的字符串密钥 * @param data String形式的待解密数据 * @return 原始数据 * @throws Exception */public static String decryptByDES(String key, String data) throws Exception     byte[] encodedKey = Base64.decodeBase64(key);    byte[] dataBytes = Base64.decodeBase64(data);    byte[] decryptedData = decryptByDES(encodedKey, dataBytes);    return new String(decryptedData);

优化版本使用方法如下:

@Testpublic void testDES_2() throws Exception     String key = SecurityUtil.generateDESKeyStr();    String data = "this is a good boy";    String encryptedData = SecurityUtil.encryptByDES(key, data);    String decryptedData = SecurityUtil.decryptByDES(key, encryptedData);    Assert.assertEquals(data, decryptedData);

这里补充一下,在实际项目开发过程中,还真遇见不少同学对Base64理解有误的情况,对于以上处理和转换过程理解有难度的同学,可以戳一下这里

3DES

/** * 生成 3DES 算法密钥 * @return byte[] * @throws Exception */public static byte[] generate3DESKey() throws Exception     KeyGenerator keyGenerator = KeyGenerator.getInstance("DESede");    // must be equal to 112 or 168    keyGenerator.init(168);    SecretKey secretKey = keyGenerator.generateKey();    byte[] encodedKey = secretKey.getEncoded();    return encodedKey;/** * 3DES加密 * @param encodedKey generate3DESKey生成的密钥 * @param dataBytes byte[]形式的待加密数据 * @return byte[] * @throws Exception */public static byte[] encryptBy3DES(byte[] encodedKey, byte[] dataBytes) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "DESede");    Cipher cipher = Cipher.getInstance("DESede");    cipher.init(Cipher.ENCRYPT_MODE, secretKey);    byte[] encryptedData = cipher.doFinal(dataBytes);    return encryptedData;/** * 3DES解密 * @param encodedKey generate3DESKey生成的密钥 * @param encryptedData byte[]形式的待解密数据 * @return byte[] * @throws Exception */public static byte[] decryptBy3DES(byte[] encodedKey, byte[] encryptedData) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "DESede");    Cipher cipher = Cipher.getInstance("DESede");    cipher.init(Cipher.DECRYPT_MODE, secretKey);    byte[] decryptedData = cipher.doFinal(encryptedData);    return decryptedData;

使用方法如下:

@Testpublic void test3DES() throws Exception     byte[] encodedKey = SecurityUtil.generate3DESKey();    String data = "this is a good boy";    byte[] encryptedData = SecurityUtil.encryptBy3DES(encodedKey, data.getBytes());    byte[] decryptedData = SecurityUtil.decryptBy3DES(encodedKey, encryptedData);    Assert.assertEquals(data, new String(decryptedData));

AES

/** * 生成 AES 算法密钥 * @return byte[] * @throws Exception */public static byte[] generateAESKey() throws Exception     KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");    // must be equal to 128, 192 or 256    // 但是当你使用 192/256 时,会收到:    // java.security.InvalidKeyException: Illegal key size or default parameters    keyGenerator.init(128);    SecretKey secretKey = keyGenerator.generateKey();    byte[] encodedKey = secretKey.getEncoded();    return encodedKey;/** * AES加密 * @param encodedKey generateAESKey生成的密钥 * @param dataBytes byte[]形式的待加密数据 * @return byte[] * @throws Exception */public static byte[] encryptByAES(byte[] encodedKey, byte[] dataBytes) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "AES");    Cipher cipher = Cipher.getInstance("AES");    cipher.init(Cipher.ENCRYPT_MODE, secretKey);    byte[] encryptedData = cipher.doFinal(dataBytes);    return encryptedData;/** * AES密 * @param encodedKey generateAESSKey生成的密钥 * @param encryptedData byte[]形式的待解密数据 * @return byte[] * @throws Exception */public static byte[] decryptByAES(byte[] encodedKey, byte[] encryptedData) throws Exception     SecretKey secretKey = new SecretKeySpec(encodedKey, "AES");    Cipher cipher = Cipher.getInstance("AES");    cipher.init(Cipher.DECRYPT_MODE, secretKey);    byte[] decryptedData = cipher.doFinal(encryptedData);    return decryptedData;

使用方法如下:

@Testpublic void testAES() throws Exception     byte[] encodedKey = SecurityUtil.generateAESKey();    String data = "this is a good boy";    byte[] encryptedData = SecurityUtil.encryptByAES(encodedKey, data.getBytes());    byte[] decryptedData = SecurityUtil.decryptByAES(encodedKey, encryptedData);    Assert.assertEquals(data, new String(decryptedData));

虽然AES支持128、192或 256的密钥长度,但是当我们使用192或256位长度的密钥时,会收到这个异常:java.security.InvalidKeyException: Illegal key size or default parameters

java.security.InvalidKeyException: Illegal key size or default parameters at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026) at javax.crypto.Cipher.implInit(Cipher.java:801) at javax.crypto.Cipher.chooseProvider(Cipher.java:864) at javax.crypto.Cipher.init(Cipher.java:1249) at javax.crypto.Cipher.init(Cipher.java:1186) at com.example.architecture.util.SecurityUtil.encryptByAES(SecurityUtil.java:161) at com.example.architecture.util.SecurityUtilTest.testAES(SecurityUtilTest.java:97) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)

原因是JRE中自带的local_policy.jarUS_export_policy.jar是支持128位密钥的加密算法,而当我们要使用192或256位密钥算法的时候,已经超出它支持的范围。

解决方案:去官方下载JCE无限制权限策略文件。

JDK5 | JDK6 | JDK7| JDK8

下载后解压,可以看到local_policy.jar和US_export_policy.jar以及readme.txt

  • 如果安装了JRE,将两个jar文件放到%JRE_HOME%\\lib\\security目录下覆盖原来的文件。
  • 如果安装了JDK,还要将两个jar文件也放到%JDK_HOME%\\jre\\lib\\security目录下覆盖原来文件。

AES128和AES256主要区别是密钥长度不同(分别是128bits,256bits)、加密处理轮数不同(分别是10轮,14轮),后者强度高于前者,当前AES是公认的较为安全的对称加密算法。

至此,上篇结束,更多精彩内容,欢迎继续阅读下篇。

参考资料:

https://baike.baidu.com/item/Blowfish/1677776

https://baike.baidu.com/item/对称加密/2152944

https://www.cnblogs.com/gordon0918/p/5317701.html

https://blog.csdn.net/u011414629/article/details/102645600

https://baike.baidu.com/item/非对称加密算法/1208652

https://www.jianshu.com/p/78886e480bef

https://blog.csdn.net/makenothing/article/details/88429511

https://blog.csdn.net/zlfing/article/details/77648444

https://blog.csdn.net/w47_csdn/article/details/87564029

相关参考

数据加密和解密的过程(了解加密与解密的初学者指南)

尽管加密和解密属于密码学的一个保护伞,但两者彼此不同。在这篇博客中,我们将讨论什么是什么。计算机系统在传输敏感或个人数据时必须承诺或至少保证隐私和机密性。一个简单的系统,除非配备适当的技术,否则无法阻...

数据加密解决方案(什么是数据加密技术?)

...中,数据加密技术可以帮助用户实现数据加密存储、访问控制增强等功能,可满足数据规模大、密文数据存在复杂查询和统计分析、性能要求高等应用场景需求。什么是数据加密技术?所谓数据加密(DataEncryption)技术,是指将...

日立中央空调面板怎么解锁(变频器解密,变频器被加密了怎么办?)

...员接手。一旦工厂的工艺条件改变了,需要修改变频器的控制参数,这时候密码就成了拦路虎,把着门不让你进去修改,怎么办呢?西门子品牌6SE70书本型变频器:设定密码打不开时,将P358和P359中数据改为相同即可。ABB品牌ACS60...

怎么给加密的文档解密(原来PDF解密这么简单用这3个方法1秒立即解密)

最近很多小伙伴都在私信问我,怎么解密加密的PDF文件?今天就专门给大家介绍一下PDF解密的3个方法,记得收藏起来以备不时之需哦!一、借助“微软浏览器”来解密微软浏览器除了用来浏览网页信息外,还可以解开加密的PDF...

文件夹加密码怎么解密(文件夹加密最简单的方法有哪些?)

电脑存放这么多的文件,多少有些是需要加密保护的,特别是涉及到商业机密的文件。那么怎么给文件夹加密呢?大家在使用电脑的时候是如何给隐私文件设置密码的呢?可以多多分享出来哈!除了重要的工作资料外,电脑上可...

怎么发加密(聊天可以加密吗?)

聊天可以加密吗?怎么加密聊天?哪个加密方式安全?随着大数据时代的到来,网络带来的便利性的同时,伴随着个人隐私泄露的问题也日渐凸显出来。大家也开始注重提高个人隐私信息保护意识了。聊天是可以加密的。现在的...

怎样加密wifi密码(如何为数据库选择最佳加密方法)

译者|李睿加密是对消息或信息进行安全编码的过程,只有授权方才能看到加密数据。加密的历史距今长达几个世纪。比如在第二次世界大战中,美军使用纳瓦霍语发送加密指令,使日军无法有效解码。如今,加密更加重要,因...

怎么把文件加密(电脑文件怎么加密?第一种方法最简单)

电脑文件加密一直令很多人十分头疼,究竟要怎么做才能既简单又安全呢?本文就将为您解开疑惑。方法一:文件夹加密超级大师1、右键需要加密的文件,选择“加密”;打开软件,点击“文件加密”,选择需要加密的文件。2...

常见的加密软件(国内即时聊天软件有哪些?隐蔽、保密、安全的加密app推荐)

...用的聊天软件?今天就给大家推荐一个我觉得比较好用的加密聊天软件。思语app有端对端的加密技术保护,我们的信息、图片、语音、视频都是安全加密的。在思语上聊天的所有消息,都经过端对端加密,任何聊天记录不进行本...

有什么好用的dll加密软件(加密狗怎么使用?软件开发者如何加密软件产品)

CodeMeter硬件加密狗是应用比较广泛,适合不同领域使用,无论是敏感的医疗设备应用场景还是严苛的半导体工厂,CodeMeter加密狗都能大显身手,完美实现加密功能要求,软件开发商和生产设备商都可以选择适合自己软件的加密锁...