加密算法初步学习

   最近由于工作需要接触了一些加解密应用,此过程中学习了des3、aes加解密算法和消息摘要算法MD5。


3des 百科介绍 http://baike.baidu.com/view/350958.htm

3DES加密过程为:C=Ek3(Dk2(Ek1(P)))
3DES解密过程为:P=Dk1(EK2(Dk3(C)))

区别于进行与简单的3次des加密和解密。


aes iteye介绍  http://zhaosong.iteye.com/blog/353967 ;http://docstore.mik.ua/orelly/java-ent/security/ch13_05.htm


md5百科介绍 http://baike.baidu.com.cn/view/7636.htm 就是把一个任意长度的字节串变换成一定长的十六进制数字串(16字节)


这里有一篇介绍cipher,mode和padding比较好的文章 http://docstore.mik.ua/orelly/java-ent/security/ch13_05.htm


加密算法常见的有ECB模式和CBC模式:

常见加密模式介绍:

ECB(Electronic Code Book:电码本)

 ECB是最简单的模式,同样的明文分组总是加密成相同的密文分组。这对于发送单一的块数据来说是非常好的,如密钥。但对执行一个加密的信息流来说不是很好,因为如果相同的明文多次发送以后,同样的密文也会被多次发送。
ECB最大的弱点是对每一个块用相同的方式进行加密。如果我们的密钥或者数据不断发生变化,ECB是完全安全的。但是如果类似的块经过同样的密钥加密发出以后,攻击者可能获得一些我们并不想让别人知道的信息。

CBC(Cipher Block Chaining:密码分组链接)  
CBC模式改变了加密方式,同样的明文分组不一定加密或解密同样的密文块,因此解决了ECB存在的主要问题。CBC使用前一分组的信息加密当前分组。因此和ECB模式大不相同。这个方法依然存在问题,那就是相同的信息仍然加密成相同的密文,因为所有的分组是同时变成密文分组的。为了解决这个问题,我们引入一个Initialization Vector(初始化向量),也就是前不久有人问到的IV问题。IV仅仅是一个初始化加密程序的随机数。它无需秘密保存,但队每一个信息来说它都是不同的,通过这个方式,即使有两条相同的信息,只要他们有不同的IV,那么他们加密后的密文也是不同的。从这个意义上来说,初始化向量无疑就和口令加密过程中使用的盐值是一样的。
CBC很适合文本传输,但它每一次都需要传送一个完整的数据块,一般选8个字符。

CFB(Cipher FeedBack:密码反馈)  
CFB的工作方式与CBC类似,但它可以执行更小的数据块,典型的有8位,这非常适合加密像聊天对话这样的信息,因为每次可以发送单一的字节数据块。
和CBC一样,CFB也需要一个IV,且相同及钥发送的每条信息的IV都必须是唯一的。

OFB(Output FeedBack:输出反馈)

 OFB除了在传输中能给数据提供更好的保护,防止数据丢失外,其他和CFB类似。密文中一位出错,也只造成明文中的一位出错,其他的方式会造成整个块丢失。

数据补位一般有NoPadding和PKCS7Padding(JAVA中是PKCS5Padding)填充方式,PKCS7Padding和PKCS5Padding实际只是协议不一样,根据相关资料说明:PKCS5Padding明确定义了加密块是8字节,PKCS7Padding加密快可以是1-255之间。但是封装的DES算法默认都是8字节,所以可以认为他们一样。数据补位实际是在数据不满8字节的倍数,才补充到8字节的倍数的填充过程。

NoPadding填充方式:算法本身不填充,比如.NET的padding提供了有None,Zeros方式,分别为不填充和填充0的方式。

PKCS7Padding(PKCS5Padding)填充方式:为.NET和JAVA的默认填充方式,对加密数据字节长度对8取余为r,如r大于0,则补8-r个字节,字节为8-r的值;如果r等于0,则补8个字节8。比如:

加密字符串为为AAA,则补位为AAA55555;加密字符串为BBBBBB,则补位为BBBBBB22;加密字符串为CCCCCCCC,则补位为CCCCCCCC88888888。



自己写的小demo学习学习:

package demo;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.SecretKeySpec;




public class Main {
    
    private static String DES3_Cipher_Algorithm = "DESede/ECB/PKCS5Padding";
    
    private static String DES3_Key_Algorithm = "DESede";
    
    private static String AES_Cipher_Algorithm = "AES/ECB/PKCS5Padding";

    private static String AES_Key_Algorithm = "AES";
    
    private static String DES3_Key = "112233445566112233445566";
    
    private static String AES_Key = "1122334411223344";
    
    
    private static byte[] des3_encrypt(byte[] keyBytes, byte[] srcBytes){
        
        try {
            Cipher cipher = Cipher.getInstance(DES3_Cipher_Algorithm);
            Key secretKey = new SecretKeySpec(keyBytes,DES3_Key_Algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(srcBytes);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    
    private static  byte[] des3_decrypt(byte[] keyBytes, byte[] srcBytes){
        
        try {
            Cipher cipher = Cipher.getInstance(DES3_Cipher_Algorithm);
            Key secretKey = new SecretKeySpec(keyBytes,DES3_Key_Algorithm);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(srcBytes);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    
    private static byte[] aes_encrypt(byte[] keyBytes, byte[] srcBytes){
        
        try {
            Cipher cipher = Cipher.getInstance(AES_Cipher_Algorithm);
            Key secretKey = new SecretKeySpec(keyBytes,AES_Key_Algorithm);
            cipher.init(Cipher.ENCRYPT_MODE, secretKey);
            return cipher.doFinal(srcBytes);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    
    private static byte[] aes_decrypt(byte[] keyBytes, byte[] srcBytes){
        
        try {
            Cipher cipher = Cipher.getInstance(AES_Cipher_Algorithm);
            Key secretKey = new SecretKeySpec(keyBytes,AES_Key_Algorithm);
            cipher.init(Cipher.DECRYPT_MODE, secretKey);
            return cipher.doFinal(srcBytes);
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (BadPaddingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }
    
    private static void test_des3() throws UnsupportedEncodingException{
        String srcStr = "des3测试数据11";
        byte[] srcBytes = srcStr.getBytes("UTF-8");
        System.out.println("srcBytes len = " + srcBytes.length);
        byte[] des3_keyBytes = DES3_Key.getBytes("UTF-8");
        System.out.println("des3_keyBytes len = " + des3_keyBytes.length);
        byte[] encryptedBytes = des3_encrypt(des3_keyBytes, srcBytes) ;
        System.out.println("encryptedStr = " + new String(encryptedBytes, "UTF-8"));
        System.out.println("encryptedBytes len = " + encryptedBytes.length);
        byte[] decryptedBytes = des3_decrypt(des3_keyBytes, encryptedBytes) ;
        System.out.println("decryptedStr = " + new String(decryptedBytes, "UTF-8"));
    }
    
    private static void test_aes() throws UnsupportedEncodingException{
        String srcStr = "aes测试数据22";
        byte[] srcBytes = srcStr.getBytes("UTF-8");
        System.out.println("srcBytes len = " + srcBytes.length);
        byte[] aes_keyBytes = AES_Key.getBytes("UTF-8");
        System.out.println("aes_keyBytes len = " + aes_keyBytes.length);
        byte[] encryptedBytes = aes_encrypt(aes_keyBytes, srcBytes) ;
        System.out.println("encryptedStr = " + new String(encryptedBytes, "UTF-8"));
        System.out.println("encryptedBytes len = " + encryptedBytes.length);
        byte[] decryptedBytes = aes_decrypt(aes_keyBytes, encryptedBytes) ;
        System.out.println("decryptedStr = " + new String(decryptedBytes, "UTF-8"));
    }
    
    private static void test_md5() throws Exception{
        String srcStr = "md5测试数据33";
        MessageDigest digest = MessageDigest.getInstance("MD5");
        digest.update(srcStr.getBytes("UTF-8"));
        byte[] destBytes = digest.digest();
        String destHexString = bytes2hex(destBytes);
        System.out.println("destHexString + " + destHexString);
    }
    
    private static String bytes2hex(byte[] bytes) {
        int len = bytes.length;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < len; i++) {
            String temp = Integer.toHexString(bytes[i]);
            switch (temp.length()) {
            case 0:
            case 1:
                temp = "0" + temp;
                break;
            default:
                temp = temp.substring(temp.length() - 2);
                break;
            }
            sb.append(temp);
        }
        return sb.toString().toUpperCase();

    }
    
    public static void main(String[] args) throws Exception{
        test_aes();
        System.out.println("---------------------------------------------------");
        test_des3();
        System.out.println("---------------------------------------------------");
        test_md5();
    }
}


eclipse 控制台输出
srcBytes len = 17
aes_keyBytes len = 16
encryptedStr = nv?�#S�N�\����m����*K��6�HP�hy�
encryptedBytes len = 32
decryptedStr = aes测试数据22
---------------------------------------------------
srcBytes len = 18
des3_keyBytes len = 24
encryptedStr = L�*�a�X�v.�Mm�c֭��
encryptedBytes len = 24
decryptedStr = des3测试数据11
---------------------------------------------------
destHexString + 6256807840E17897A2321CC20769ED6D



这里,

3des的密钥要求是24字节,假如是用nopadding,源加密串的长度要求是8字节的倍数,可以用其它padding如PKCS5Padding对源加密串进行填充,这要就无须要求源加密串长度是8字节的倍数了。


des的密钥要求是8字节,假如是用nopadding,源加密串的长度要求是8字节的倍数,可以用其它padding如PKCS5Padding对源加密串进行填充,这要就无须要求源加密串长度是8字节的倍数了。

aes的密钥要求是16字节,假如用nopadding,源加密串的长度要求是16字节的倍数,可以用其它padding如PKCS5Padding对源加密串进行填充,这要就无须要求源加密串长度是16字节的倍数了。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值