在简单的服务器端与客户端通信的应用中,这种做法比较常见
DES、blowfish扫盲:
1.des的常见模式分为四种 ECB / CBC / CFB / OFB 这里使用默认的ECB
ECB的缺陷:能从密文看出明文的规律
加
密算法是按块进行加密的, DES ,是 64Bit 一个块的进行加密,就是每次加密 8
个字节,因此每次输入八个字节的明文输出八个字节密文,如果是 16 个字节,那么分成两个块依次进行加密,问题就出现在这里,如果明文是
1234567812345678,分块分别进行加密,那么加密的结果类似“C4132737962C519C
C4132737962C519C”,可以看出明文的规律,这就是 ECB 加密模式,密文可以看出明文的规律
CBC/CFB/OFB:
为
了解决这个问题,有了其他的加密模式:CBC 加密模式(密码分组连接),CFB加密模式(密码反馈模式),OFB加密模式(输出反馈模式)CBC
是要求给一个初始化的向量,然后将每个输出与该向量作运算,并将运算的结果作为下一个加密块的初始化向量,CFB 和 OFB
则不需要提供初始化向量,直接将密码或者输出作为初始化向量进行运算;这样就避免了明文的规律出现在密文中;当然缺点是解密时需要保证密文的正确性,如果
网络传输时发生了一部分错误,则后面的解密结果就可能是错误的;(ECB模式仅影响传输错误的那个块);
2.上面提到des是以64bit作为单位块单位来进行加密的,如果加密的内容长度刚好不是64bit块的倍数,则需要做填充(padding)
常
用的填充算法是 PKCS#7,该填充方法是将每一个补充的字节内容填充为填充的字节个数;例如明文长度是 100 ,
分组的大小是32个字节,那么需要分为四组,补充28个字节,那么补充的字节全部补充为'\0x28',如果分组的大小是 8 个字节,那么
PKCS#7 的填充方式和 PKCS#5 是完全一致的;另外还有一个规定,就是如果明文刚刚好进行分组,那么需要补充一个独立的分组出来,例如
DES ,如果明文为 8 个字节,那么需要补充为 16
个字节进行运算,这样的好处是进行解密后,将解密出来的最后一个字节取出来,并将解密结果的长度减去该值,就是原来明文的长度;
当然你也可以选择NoPadding模式,自己对加密内容的字节数做处理,确保它的长度是64bit的倍数
(以上规则blowfish也同样使用)
代码:
java
01 | <b> import java.security.Key; |
02 | import java.security.Security; |
03 | import javax.crypto.Cipher; |
07 | static String strDefaultKey = "initkey" ; |
08 | static Cipher encryptCipher = null ; |
09 | static Cipher decryptCipher = null ; |
12 | Security.addProvider( new com.sun.crypto.provider.SunJCE()); |
15 | key = getKey(strDefaultKey.getBytes()); |
16 | encryptCipher = Cipher.getInstance( "DES" ); |
17 | encryptCipher.init(Cipher.ENCRYPT_MODE, key); |
19 | decryptCipher = Cipher.getInstance( "DES" ); |
20 | decryptCipher.init(Cipher.DECRYPT_MODE, key); |
29 | public static byte [] encrypt( byte [] arrB) throws Exception { |
30 | return encryptCipher.doFinal(arrB); |
33 | public static byte [] decrypt( byte [] arrB) throws Exception { |
34 | return decryptCipher.doFinal(arrB); |
37 | private static Key getKey( byte [] arrBTmp) throws Exception { |
38 | byte [] arrB = new byte [ 8 ]; |
39 | for ( int i = 0 ; i < arrBTmp.length && i < arrB.length; i++) { |
42 | Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES" ); |
c++01 | int Encrypt( unsigned char * inbuf , unsigned char * * outbuf , int inlen , unsigned char * key, unsigned char * iv ) |
03 | BIO *bio, *mbio, *cbio; |
07 | mbio = BIO_new( BIO_s_mem( ) ); |
08 | cbio = BIO_new( BIO_f_cipher( ) ); |
09 | BIO_set_cipher( cbio , EVP_des_cbc( ) , key , iv , 1 ); |
11 | bio = BIO_push( cbio , mbio ); |
12 | BIO_write( bio , inbuf , inlen ); |
15 | outlen = BIO_get_mem_data( mbio , (unsigned char **) & dst ); |
16 | * outbuf = ( unsigned char * ) malloc ( outlen ); |
17 | memcpy ( * outbuf , dst , outlen ); |