对称加密与数字摘要--加密算法DES/AES的使用以及数字摘要的基本介绍与使用

一、基本介绍

  1、加密类型(对称加密/非对称加密)

    对称加密:简单来说就是加密与解密用的是同一把秘钥。

    非对称加密:加密用的是一把秘钥,解密的时候用的是另一把秘钥(例如一把私钥,一把公钥)。

  2、加密方式(流加密,分组加密)

    流加密:就是将加密的内容每个元素都用秘钥一个一个去处理。

    分组加密:将加密的内容分组,用秘钥按组去区分。所以如果按分组去处理的话,就需要进行填充,因为可能最后的一组位数不够分一块。

  3、常见的对称加密算法

    DES:Data Encryption Standard (数据加密标准),分组加密,秘钥是8位

    AES:Advanced Encryption Standard(高级加密标准),是DES的升级版本(所以一般是用这个),不过其的秘钥需要16位。

  4、常见的加密模式

    ECB:Electronic codebook, 电子密码本. 将加密的消息按照块划分,对每个块进行独立加密。

    CBC:Cipher-block chaining, 密码块链接. 每个明文块先与前一个密文块进行异或后,再进行加密。这种方法,每个密文块都依赖于它前面的所有明文块。(所以加密第一块的实时就需要给其一个自己定义的初始向量参数)。

    所以EBC能并行处理,CBC不能,但CBC更安全。

  5、常见的块加密的填充方式

    NoPadding:不填充,就是说不进行填充,所以待加密的内容刚好需要为划分的块的大小的倍数。例如DES就需要为8 byte的倍数,AES就需要为16 byte的位数。

    PKCS7Padding、PKCS5Padding、ZeroPadding:可以看下这篇文章,这里需要注意的是如果是ZeroPadding,因为其是用0去填充的,所以当分的最后一块的最后元素也有0的话就可能产生问题,所以直接根据密文的话就区分不了。

  6、base64

    介绍:我们知道加密的密文byte可能会对应到ascii表的任何映射,有些都不是可读的,可能有些都是具有特殊含义的(传输过程可能产生问题),所以我们需要将其转换为可读的、可打印的。所以base64的操作就是将byte都映射到用A-Z、a-z、0-9、+、/去标识,然后到需要使用的时候再将其转换为原来的内容。

    转换原理:三个byte为一组,就是3*8=24。然后base64再将这个24以4*6的方式组合,划分为四组,每组6bit最高的两位用0填充形成一个byte(00111111=63 -- 0-63总共64种组合),也就是将3个byte转换为4个byte。不足形成一个组的剩下的用'='去填充。

   案例代码:

// 3*8=24 为3个字符   3*n不需要填充
String content1 = "ABC";
String encode1 = Base64.encode(content1.getBytes());
// 4*8 = 32 所以对打印4个字符
System.out.println(encode1);
//2*8 = 16 为两个字符
String content2 = "AB";
String encode2 = Base64.encode(content2.getBytes());
//所以会填充一个=
System.out.println(encode2);

 

二、AES/DES案例代码

1、DES算法(加密模式为ECB)

    1、main方法

public static void main(String[] args) throws NoSuchPaddingException,
        NoSuchAlgorithmException, InvalidKeyException, BadPaddingException,
        IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException {
    //对称加密的算法
    String algorithm = "DES";
    //秘钥
    String key = "12345678";
    //对称加密的类型信息
    String algorithmType = "DES";
    //原文
    String content = "明文";
    //EBC模式
    String encryptionContent = encryptionECB(algorithm, key, algorithmType, content);
    System.out.println("ECB Encryption Code : " + encryptionContent);
    byte[] decryptionBytes = decryptionECB(algorithm,key,algorithmType,encryptionContent);
    System.out.println("ECB Decryption Code : " + new String(decryptionBytes).toString());
}

    2、encryptionECB方法

/**
 * 加密操作
 * @param algorithm     对称加密的算法 DES/AES
 * @param key   秘钥   8位
 * @param algorithmType     对称加密的类型信息
 *                          设置规则:算法/模式/填充 如果只写算法如DES或者AES,则默认是 (DES/AES)/ECB/PKCS5Padding
 * @param content       原文
 * ............
 */
public static String encryptionECB(String algorithm,String key,String algorithmType,String content)
        throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException,
        BadPaddingException, IllegalBlockSizeException {
    //加密操作的对象
    Cipher cipher = Cipher.getInstance(algorithmType);
    //加密规则
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
    // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则
    cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec);
    //加密操作
    byte[] bytes = cipher.doFinal(content.getBytes());

    System.out.print("doFinalChars:");
    for (int i = 0; i < bytes.length; i++) {
        System.out.print((char)bytes[i]);
    }
    System.out.println();
    //进行Base64的操作:让密文具有可读性,在解密的时候也需要进行Base64的解密
    // (Base64不是一种加密操作,只是增加可读写)
    // (也可以不进行base64操作,同样在解密的时候也不需要解析base64的操作)
    String encodeContent = Base64.encode(bytes);
    return encodeContent;
}

    3、decryptionECB

public static byte[] decryptionECB(String algorithm,String key,String algorithmType,String encryptContent)
        throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException,
        BadPaddingException, IllegalBlockSizeException, Base64DecodingException {
    //Base64的解密
    byte[] decryptionCode = Base64.decode(encryptContent.getBytes());
    //加密操作的对象
    Cipher cipher = Cipher.getInstance(algorithmType);
    //加密规则
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
    // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则
    cipher.init(Cipher.DECRYPT_MODE,secretKeySpec);
    //加密操作
    byte[] bytes = cipher.doFinal(decryptionCode);
    return bytes;
}

2、AES算法(加密模式为CBC)

  这里由于我们使用的是CBC模式,所以需要多一个初始向量参数。下面代码多了一个创建IvParameterSpec的过程

    1、main方法

public static void main(String[] args) throws NoSuchPaddingException,
        NoSuchAlgorithmException, InvalidKeyException, BadPaddingException,
        IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException {
    //原文
    String content = "明文";
    //CBC模式
    String algorithmCBC = "AES";
    String keyAES = "1234567812345678";
    String algorithmTypeCBC = "AES/CBC/PKCS5Padding";
    String ivParameter = "8765432187654321";
    String encryptionCBCContent = encryptionCBC(algorithmCBC, keyAES, ivParameter, algorithmTypeCBC, content);
    System.out.println("CBC Encryption Code : " + encryptionCBCContent);
    byte[] decryptionCBC = decryptionCBC(algorithmCBC, keyAES, ivParameter, algorithmTypeCBC, encryptionCBCContent);
    System.out.println("CBC Decryption Code : " + new String(decryptionCBC).toString());
}

    2、encryptionCBC

/**
 * @param algorithm     对称加密的算法 DES/AES
 * @param key   秘钥      16位
 * @param ivParameter       IV向量        16位
 * @param algorithmType     对称加密的类型信息
 * @param content       原文
 * .......
 */
public static String encryptionCBC(String algorithm,String key,String ivParameter,String algorithmType,String content)
        throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException,
        BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
    //加密操作的对象
    Cipher cipher = Cipher.getInstance(algorithmType);
    //加密规则
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
    //创建IV向量
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes());
    // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则
    cipher.init(Cipher.ENCRYPT_MODE,secretKeySpec,ivParameterSpec);
    //加密操作
    byte[] bytes = cipher.doFinal(content.getBytes());
    //进行Base64的操作:让密文具有可读性,在解密的时候也需要进行Base64的解密
    // (Base64不是一种加密操作,只是增加可读写)
    // (也可以不进行base64操作,同样在解密的时候也不需要解析base64的操作)
    String encodeContent = Base64.encode(bytes);
    return encodeContent;
}

    3、decryptionCBC

public static byte[] decryptionCBC(String algorithm,String key,String ivParameter,String algorithmType,String encryptContent)
        throws InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException,
        BadPaddingException, IllegalBlockSizeException, Base64DecodingException, InvalidAlgorithmParameterException {
    //Base64的解密
    byte[] decryptionCode = Base64.decode(encryptContent.getBytes());
    //加密操作的对象
    Cipher cipher = Cipher.getInstance(algorithmType);
    //加密规则
    SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(),algorithm);
    //创建IV向量
    IvParameterSpec ivParameterSpec = new IvParameterSpec(ivParameter.getBytes());
    // 参数1:进行init的类型:加密/解密=ENCRYPT/DECRYPT,参数2加密规则
    cipher.init(Cipher.DECRYPT_MODE,secretKeySpec,ivParameterSpec);
    //加密操作
    byte[] bytes = cipher.doFinal(decryptionCode);
    return bytes;
}

三:数字摘要

  1、数字摘要的介绍与意义

    1、介绍

        数字摘要就是将任意长度的消息变成固定长度的短消息,一般用散列算法去处理,例如:MD5、SHA-1、SHA-256、SHA-512,这些都是散列算法,对于它们产生的结果来说:主要的区别就是会产生不同bit长度的结果,还有就是安全性问题,例如SHA-512这个长度比较长所以相对来说要碰撞就更不容易。

    2、意义

        其作用主要来说就是用来看这个消息的内容有没有被修改,一个消息即使做了很少的改动,最终产生的结果也会很大。

  2、案例代码

public static void main(String[] args) throws NoSuchAlgorithmException {
    String content = "明文";
    String algorithm = "MD5";  //   MD5/SHA-1/SHA-256/SHA-512
    MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
    //数字摘要的byte
    byte[] digestContext = messageDigest.digest(content.getBytes());
    //一般是用16进制进行展示,所以需要进行转换16进制
    // 4 bit 表示一个16进制数 4*32 = 128 & 8*16 = 128
    String hexTo16 = hexTo16(digestContext);
    System.out.println(hexTo16);
}

public static String hexTo16(byte[] bytes){
    StringBuffer stringBuffer = new StringBuffer();
    for (byte byteCode : bytes) {
        //为两个长度
        String hexString = Integer.toHexString(byteCode & 0xff);
        //由于产生的hexString ,如果是05这种,hexString没有前面的0,所以需要加上
        if (hexString.length() == 1)
        {
            stringBuffer.append("0");
        }
        stringBuffer.append(hexString);
    }
    return stringBuffer.toString();
}

    其进行签名产生的结果总共16byte:

    然后转换为16进制后的最终结果是:,长度为32

  3、Integer.toHexString方法的简单介绍

    简单来说,这个方法就是将byte(1个byte :8bit,4bit表示一个16进制的数)写成两个16进制数字符,会省略前面的0

    案例代码: 

byte byte1 = (byte)12;
String toHexString1 = Integer.toHexString(byte1);
System.out.println("toHexString1: " + toHexString1);
byte byte2 = (byte)16;
String toHexString2 = Integer.toHexString(byte2);
System.out.println("toHexString2: " + toHexString2);

    产生的结果:

      

 

 

    

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值