aes 相关

AES算法又称Rijndael,用于替换DES

数据分组长度 必须是 128 bits (单个AES模块明文输入和密文输出长度固定为128)

AES-128/192/256指密钥长度(Rijndael设计还可以处理其它分组/密钥长度,但 AES没采用)

对称加密如DES ,AES等,理论上都可暴力破解密钥(brute-force key search)来攻击

通过CBC, OFB等方式,把多个AES模块互联,同时使用padding时,才可以用AES加密任意长度的信息

确定所使用的AES”种类”(AES-128/192/256),及AES模块之间连接模式(CBC,OFB等),这个组合的理论安全性就是一个确定的值,即使是空字符串作为pass phrase

密码块工作模式(Block cipher mode of operation)

对按块处理密码的加密方式一种扩充,不仅仅适用于AES,包括DES, RSA等加密方法同样适用

名称英文全名方法优点缺点
ECBElectronic codebook电子密码本每块独立加密1.分块可以并行处理1.同样的原文得到相同的密文,容易被攻击
CBCCipher-block chaining密码分组链接每块加密依赖于前一块的密文1.同样的原文得到不同的密文2.原文微小改动影响后面全部密文1.加密需要串行处理2.误差传递
PCBCPropagating cipher-block chaining填充密码块链接CBC的扩种,较少使用1.同样的原文得到不同的密文2.互换两个邻接的密文块不会对后续块的解密造成影响1.加密需要串行处理
CFBCipher feedback密文反馈
OFBOutput feedback输出反馈模式加密后密文与原文异或XOR1.能够对密文进行校验
CTRCounter mode计数器模式增加一个序列函数对所有密文快做XOR

填充(Padding)

对需要按块处理的数据,当数据长度不符合块处理需求时,按照一定方法填充满块长的一种规则

名称方法示例
Zero padding最常见的方式,全填充0x00AA AA AA AA 00 00 00 00
ANSI X.923Zero的改进,最后一个字节为填充字节个数AA AA AA AA 00 00 00 04
ISO 10126随机填充AA AA AA AA 81 A6 23 04
PKCS7ANSI X.923的变体
填充1个字符就全0x01
填充2个字符就全0x02
不需要填充就增加一个块,填充块长度,块长为8就填充0x08,块长为16就填充0x10
AA AA AA AA AA AA AA 01
AA AA AA AA 04 04 04 04
AA AA AA AA AA AA AA AA 08 08 08 08 08 08 08 08
ISO/IEC 7816-4以0x80开始作为填充开始标记,后续全填充0x00AA AA AA AA AA AA AA 80
AA AA AA AA 80 00 00 00
算法/模式/填充16字节加密后数据长度不满16字节加密后长度
AES/CBC/NoPadding16不支持
AES/CBC/PKCS5Padding3216
AES/CBC/ISO10126Padding3216
AES/CFB/NoPadding16原始数据长度
AES/CFB/PKCS5Padding3216
AES/CFB/ISO10126Padding3216
AES/ECB/NoPadding16不支持
AES/ECB/PKCS5Padding3216
AES/ECB/ISO10126Padding3216
AES/OFB/NoPadding16原始数据长度
AES/OFB/PKCS5Padding3216
AES/OFB/ISO10126Padding3216
AES/PCBC/NoPadding16不支持
AES/PCBC/PKCS5Padding3216
AES/PCBC/ISO10126Padding3216

JDK AES实现

AES理论上支持128,192,256三种长度的密钥,几乎全部密码块工作模式和填充方法,但JDK 7只实现四种

  1. AES/CBC/NoPadding
  2. AES/CBC/PKCS5Padding
  3. AES/ECB/NoPadding
  4. AES/ECB/PKCS5Padding

缺省模式

Cipher.getInstance("AES")=Cipher.getInstance("AES/ECB/PKCS5Padding")

JDK的PKCS5Padding是PKCS7的实现

AES按16Byte对块处理,对NoPadding,加密原文长度不是16Byte倍数,抛异常

PKCS5Padding加密,NoPadding解密也能解密成功,内容为原文加上PKCS5Padding之后的结果

原文最后一个字符>=0x00&&<=0x10,PKCS5Padding解密异常,要么符合PKCS5Padding,最后内容被删除,要么不符合,解密失败抛异常

两种思路

  1. 原文Base64为可见字符
  2. 原文自带长度使用NoPadding解密

oracle jdk aes 256密钥需要覆盖java policy

通过反射修改代码,绕过限制

  public static void removeCryptographyRestrictions() {
        if (!isRestrictedCryptography()) {

            return;
        }
        try {
            final Class<?> jceSecurity = Class.forName("javax.crypto.JceSecurity");
            final Class<?> cryptoPermissions = Class.forName("javax.crypto.CryptoPermissions");
            final Class<?> cryptoAllPermission = Class.forName("javax.crypto.CryptoAllPermission");
    
            final Field isRestrictedField = jceSecurity.getDeclaredField("isRestricted");
            isRestrictedField.setAccessible(true);
            isRestrictedField.set(null, false);
    
            final Field defaultPolicyField = jceSecurity.getDeclaredField("defaultPolicy");
            defaultPolicyField.setAccessible(true);
            final PermissionCollection defaultPolicy = (PermissionCollection) defaultPolicyField.get(null);
    
            final Field perms = cryptoPermissions.getDeclaredField("perms");
            perms.setAccessible(true);
            ((Map<?, ?>) perms.get(defaultPolicy)).clear();
    
            final Field instance = cryptoAllPermission.getDeclaredField("INSTANCE");
            instance.setAccessible(true);
            defaultPolicy.add((Permission) instance.get(null));


        } catch (Exception e) {

        }
    }
    
    private static boolean isRestrictedCryptography() {
        // This simply matches the Oracle JRE, but not OpenJDK.
        return "Java(TM) SE Runtime Environment".equals(System.getProperty("java.runtime.name"));
    }

如何在不安全的环境中实现安全的数据通信?结合使用公钥,私钥加密算法

私钥算法(对称加密算法)

同一密钥既用于加密又用于解密,所以密钥不能公开。常见算法:DES/AES

公钥算法(非对称加密算法)

加密和解密的密码不一样,一个是公钥,另一个是私钥

  • 公钥和私钥成对出现
  • 公开的密钥叫公钥,只有自己知道的叫私钥
  • 用公钥加密的数据只有对应的私钥可以解密
  • 用私钥加密的数据只有对应的公钥可以解密
  • 如果可以用公钥解密,则必然是对应的私钥加的密
  • 如果可以用私钥解密,则必然是对应的公钥加的密

公钥和私钥是相对的,两者本身并没有规定哪一个必须是公钥或私钥

1.首先 接收方 生成一对密钥,即私钥和公钥 2.然后,接收方 将公钥发送给 发送方 3.发送方用收到的公钥对数据加密,再发送给接收方 4.接收方收到数据后,使用自己的私钥解密

公钥加密的数据必须用对应的私钥才能解密,而私钥又只有接收方自己知道,这样就保证了数据传输的安全性

数字签名

公钥体系另一用途。验证发送方身份并保护数据完整性

发送方用私钥对信息进行摘要算法生成签名(sign) 接收者可用发送者公钥验证(verify),便可确认资料是由发送方发出(私钥签名后只有匹配公钥才能解),可以确认两点:

1.保证信息是由签名者自己签名发送的,签名者不能否认或难以否认(不可抵赖性) 2.保证信息自签发后到收到为止未曾作过任何修改(数据完整性)

公钥算法非常慢,一般需要同时结合公钥算法与私钥算法

1.首先,发送方使用对称算法对原始信息进行加密 2.接收方通过公钥机制生成一对密钥,一个公钥,一个私钥 3.接收方 将公钥发送给 发送方 4.发送方用公钥对对称算法的密钥进行加密,并发送给接收方 5.接收方用私钥进行解密得到对称算法的密钥 6.发送方再把已加密的原始信息发送给接收方 7.接收方使用对称算法的密钥进行解密

总结:

1.每个用户都有一对私钥和公钥 私钥用来进行解密和签名,是给自己用的 公钥由本人公开,用于加密和验证签名,是给别人用的 2.当该用户发送文件时,用私钥签名,别人用他给的公钥解密,可以保证该信息是由他发送的。即数字签名。 3.当该用户接受文件时,别人用他的公钥加密,他用私钥解密,可以保证该信息只能由他看到。即安全传输。

DES缺点

  • 作为分组密码,DES的加密单位仅有64位二进制,这对于数据传输来说太小,因为每个分组仅含8个字符,而且其中某些位还要用于奇偶校验或其他通讯开销

  • DES的密钥的位数太短,只有56比特,而且各次迭代中使用的密钥是递推产生的,这种相关必然降低密码体制的安全性, 在现有技术下用穷举法寻找密钥已趋于可行

  • DES不能对抗差分和线性密码分析。迄今为止, DES算法中的S盒8个选择函数矩阵的设计原理因美国政府方面的干预, 不予公布。从这一方面严格地讲DES算法并不是一个真正的公开加密算法

  • DES用户实际使用的密钥长度为56bit, 理论上最大加密强度为256

DES算法要提高加密强度(例如增加密钥长度), 则系统开销呈指数增长。除采用提高硬件功能和增加并行处理功能外,从算法本身和软件技术方面无法提高DES算法的加密强度。

AES

总之汇聚了安全性、效率高、易实现性和灵活性等优点,是一种较DES更好的算法

http://www.baike.com/wiki/AES%E5%8A%A0%E5%AF%86%E7%AE%97%E6%B3%95

https://wustrive2008.github.io/2015/08/21/%E5%BC%80%E6%94%BE%E6%8E%A5%E5%8F%A3%E7%9A%84%E5%AE%89%E5%85%A8%E9%AA%8C%E8%AF%81%E6%96%B9%E6%A1%88(AES+RSA)/

https://xiaoyao9184.wordpress.com/2015/12/15/java-special-jce-3-solution-4-aes-256bits-keysize/

http://www.cnblogs.com/arix04/archive/2009/06/26/1511839.html

http://www.cnblogs.com/fullsail/archive/2013/04/29/3051456.html