3DES 的加密算法

import java.security.Key;
import java.security.spec.KeySpec;
 
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
 
public class BcTest {
 
    // 3DES key = 00 01 02 03 04 05 06 07 01 02 03 04 05 06 07 08 02 03 04 05 06 07 08 09
    // data ("01234567") = 30 31 32 33 34 35 36 37
    // 3des cipher = 5a b3 fd 7b 2a ca b2 95
    // cipher mode = DESede/ECB/NoPadding
    public static void main(String[] args) throws Exception {
 
        byte[] key1 = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7 };
        byte[] key2 = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        byte[] key3 = new byte[] { 2, 3, 4, 5, 6, 7, 8, 9 };
        byte[] data = "01234567".getBytes();  // 由于未采用填充模式,因此原文长度必须为 8 的倍数
 
        // 3DES ciphertext = EK3(DK2(EK1(plaintext)))
        byte[] crypt = encrypt(decrypt(encrypt(data, key1), key2), key3);
 
        // 3DES plaintext = DK1(EK2(DK3(ciphertext)))
        byte[] plain = decrypt(encrypt(decrypt(crypt, key3), key2), key1);
 
        System.out.println("  key: " + ByteUtil.bytes2HexSpace(key1) + " "
                + ByteUtil.bytes2HexSpace(key2) + " "
                + ByteUtil.bytes2HexSpace(key3));
        System.out.println(" data: " + ByteUtil.bytes2HexSpace(data));
        System.out.println("crypt: " + ByteUtil.bytes2HexSpace(crypt));
        System.out.println("plain: " + ByteUtil.bytes2HexSpace(plain));
    }
 
    public static byte[] decrypt(byte[] crypt, byte[] key) throws Exception {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.DECRYPT_MODE, k);
        return cipher.doFinal(crypt);
    }
 
    public static byte[] encrypt(byte[] data, byte[] key) throws Exception {
        Key k = toKey(key);
        Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
        cipher.init(Cipher.ENCRYPT_MODE, k);
        return cipher.doFinal(data);
    }
 
    public static SecretKey toKey(byte[] key) throws Exception {
        KeySpec dks = new DESKeySpec(key);
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
        return keyFactory.generateSecret(dks);
    }
}
 
class ByteUtil {
 
    private static final char HEX[] = "0123456789abcdef".toCharArray();
 
    public static String bytes2HexSpace(byte bys[]) {
        char chs[] = new char[(bys.length * 2 + bys.length) - 1];
        int i = 0;
        int offset = 0;
        for (; i < bys.length; i++) {
            if (i > 0)
                chs[offset++] = ' ';
            chs[offset++] = HEX[bys[i] >> 4 & 15];
            chs[offset++] = HEX[bys[i] & 15];
        }
        return new String(chs);
    }
}
上面DES的加密模式采用ECB,填充方式为不进行填充。

实际上JCE提供了3DES的加密算法,算法名为DESede,并不需要自己通过DES去实现3DES。只要把上面加密算法中有关DES改为DESede,toKey方法那个KeySpec的引用类由DESKeySpec改为DESedeKeySpec就可以了。

使用cipher可以很容易的实现3des加密,但是跟其他平台开发的3des加密对接来说,通常会有一些问题。基本的程序如下:

publicstaticbyte[]desEncrypt(Stringmessage,Stringkey)throwsException{
Ciphercipher
=Cipher.getInstance("DESede");

DESKeySpecdesKeySpec
=newDESKeySpec(key.getBytes("UTF-8"));
SecretKeyFactorykeyFactory
=SecretKeyFactory.getInstance("DESede");
SecretKeysecretKey
=keyFactory.generateSecret(desKeySpec);
cipher.init(Cipher.ENCRYPT_MODE,secretKey);

returncipher.doFinal(message.getBytes("UTF-8"));

我们跟其他平台对接发现对同样输入加密以后结果不同,看看jdk的文档,有如下描述:

A transformation is a string that describes the operation (or set of operations) to be performed on the given input, to produce some output.

A transformation is of the form:

  • "algorithm/mode/padding" or

  • "algorithm"

(in the latter case, provider-specific default values for the mode and padding scheme are used).

根据前面的代码,我们已经选择了正确的算法,那么加密不同的原因应该就是mode和padding了。

he SunJCE provider uses ECB as the default mode, and PKCS5Padding as the default padding scheme for DES, DES-EDE and Blowfish ciphers. This means that in the case of the SunJCE provider,
Cipher c1 = Cipher.getInstance("DES/ECB/PKCS5Padding");
and
Cipher c1 = Cipher.getInstance("DES");
are equivalent statements.

对于其他语言开发的3des,一定要采用相同的mode和padding才能保证通信。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值