• java 与 c# 3des 加解密


     

    主要差异如下:

    1、  对于待加密解密的数据,各自的填充模式不一样

          C#的模式有:ANSIX923、ISO10126、None、PKCS7、Zero,而Java有:NoPadding、PKCS5Padding、SSL3Padding

    2、  各自默认的3DES实现,模式和填充方式不一样

    C#的默认模式为CBC,默认填充方式为PKCS7; java的默认模式为ECB,默认填充方式为PKCS5Padding

    3、  各自的key的size不一样

    C#中key的size为16和24均可;java中要求key的size必须为24;对于CBC模式下的向量iv的size两者均要求必须为8

     

    翻看了3DES的原理:

    DES主要采用替换和移位的方法,用56位密钥对64位二进制数据块进行加密,每次加密可对64位的输入数据进行16轮编码,

    经一系列替换和移位后,输入的64位转换成安全不同的64的输出数据

    .   
    3DES:是在DES的基础上采用三重DES,即用两个56位的密钥K1,K2,发送方用K1加密,K2解密,再使用K1加密.接收方使用K1解密,K2加密,再使用K1解密,

    其效果相当于密钥长度加倍.

     

    于是尝试在java中,对key进行补位,即用前8个字节作为byte[24] 中的byte[16]~byte[23];发现与c#中加密的结果相同!于是大胆假设C#中可能是检查key的size为16的时候

    自动将前8个字节作为k3进行了补位,而java没有实现这一点(因为java的3DES算法中强制要求key的size必须为24)。这样的情况下,可能就是发送方用k1加密、k2解密、k3再加密;接受方k3解密、k2加密、再k1解密来实现。

     

    最终经过编码验证,确认key大小为24时,java和c#的加密解密结果相一致。

    Java中实现时,只要注意对大小不足24的key进行补位,和采用CBC模式,填充模式为PKCS5Padding即可。

    View Code
      1 public class CDES {
      2 
      3     public static byte[] encrypt(String sKey, byte[] bIV, byte[] bPlainText, int nOffset, int nSize)
      4             throws Exception {
      5         byte[] bKey = buildKey(sKey);
      6         byte[] bInput = buildInput(nSize, bPlainText, nOffset);
      7         byte[] bResult = encrypt(bIV, bKey, bInput);
      8         return bResult;
      9     }
     10 
     11     public static byte[] decrypt(String sKey, byte[] bIV, byte[] bCipherText)
     12             throws Exception {
     13         byte[] bKey = buildKey(sKey);
     14         SecretKey securekey = buildSecretKey(bKey);
     15         IvParameterSpec iv = new IvParameterSpec(bIV);
     16         Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
     17         SecureRandom sr = new SecureRandom();
     18         cipher.init(Cipher.DECRYPT_MODE, securekey, iv, sr);
     19         byte[] bOutput = cipher.doFinal(bCipherText);
     20         int nLen = 0;
     21         nLen = nLen | (int) bOutput[0];
     22         nLen = nLen | ((int) bOutput[1] << 8);
     23         if (nLen > bOutput.length - 4) {
     24             throw new Exception("非法的密文");
     25         }        
     26         byte[] bResult = new byte[bOutput.length  - 4];
     27         bResult = Arrays.copyOfRange(bOutput, 2, bOutput.length - 2);
     28         return bResult;
     29     }
     30 
     31     private static byte[] md5Digest(String sData) throws NoSuchAlgorithmException {
     32         MessageDigest md5 = MessageDigest.getInstance("MD5");
     33         byte[] bData = sData.getBytes();
     34         md5.update(bData, 0, bData.length);
     35         byte[] hash = md5.digest();
     36         return hash;
     37     }
     38 
     39     private static byte[] buildInput(int nSize, byte[] bPlainText, int nOffset) {
     40         byte[] bInput = new byte[nSize + 4];
     41         for (int i = 0; i < bPlainText.length; i++) {
     42             Arrays.fill(bInput, 2 + i, 2 + i + 1, bPlainText[i]);
     43         }
     44         int usCRC = CCRC16.CalcCrcCheckSum(bPlainText, nOffset, nSize);
     45         bInput[0] = (byte) (nSize & 0xFF);
     46         bInput[1] = (byte) (nSize >> 8 & 0xFF);
     47         bInput[nSize + 2] = (byte) (usCRC & 0xFF);
     48         bInput[nSize + 3] = (byte) (usCRC >> 8 & 0xFF);
     49         return bInput;
     50     }
     51 
     52     private static byte[] buildKey(String sKey) throws NoSuchAlgorithmException {
     53         byte[] bTmp = md5Digest(sKey);
     54         byte[] bKey = new byte[24];
     55         System.arraycopy(bTmp,0,bKey,0,bTmp.length);
     56         System.arraycopy(bTmp,0,bKey,16,8);
     57         return bKey;
     58     }
     59 
     60     private static SecretKey buildSecretKey(byte[] bkey) throws InvalidKeyException,
     61             InvalidKeySpecException, NoSuchAlgorithmException {
     62         DESedeKeySpec dks = new DESedeKeySpec(bkey);
     63         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
     64         SecretKey securekey = keyFactory.generateSecret(dks);
     65         return securekey;
     66     }
     67 
     68     private static byte[] encrypt(byte[] biv, byte[] bkey, byte[] input) throws Exception {
     69         SecretKey securekey = buildSecretKey(bkey);
     70         IvParameterSpec iv = new IvParameterSpec(biv);
     71         Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
     72         SecureRandom sr = new SecureRandom();
     73         cipher.init(Cipher.ENCRYPT_MODE, securekey, iv, sr);
     74         return cipher.doFinal(input);
     75     }
     76 }
     77 
     78 class CCRC16 {
     79     public static int CalcCrcCheckSum(byte[] pBuffer, int nOffset, int nSize) {
     80 
     81         int[] table = {
     82             0x00000xC0C10xC1810x01400xC3010x03C00x02800xC241,
     83             0xC6010x06C00x07800xC7410x05000xC5C10xC4810x0440,
     84             0xCC010x0CC00x0D800xCD410x0F000xCFC10xCE810x0E40,
     85             0x0A000xCAC10xCB810x0B400xC9010x09C00x08800xC841,
     86             0xD8010x18C00x19800xD9410x1B000xDBC10xDA810x1A40,
     87             0x1E000xDEC10xDF810x1F400xDD010x1DC00x1C800xDC41,
     88             0x14000xD4C10xD5810x15400xD7010x17C00x16800xD641,
     89             0xD2010x12C00x13800xD3410x11000xD1C10xD0810x1040,
     90             0xF0010x30C00x31800xF1410x33000xF3C10xF2810x3240,
     91             0x36000xF6C10xF7810x37400xF5010x35C00x34800xF441,
     92             0x3C000xFCC10xFD810x3D400xFF010x3FC00x3E800xFE41,
     93             0xFA010x3AC00x3B800xFB410x39000xF9C10xF8810x3840,
     94             0x28000xE8C10xE9810x29400xEB010x2BC00x2A800xEA41,
     95             0xEE010x2EC00x2F800xEF410x2D000xEDC10xEC810x2C40,
     96             0xE4010x24C00x25800xE5410x27000xE7C10xE6810x2640,
     97             0x22000xE2C10xE3810x23400xE1010x21C00x20800xE041,
     98             0xA0010x60C00x61800xA1410x63000xA3C10xA2810x6240,
     99             0x66000xA6C10xA7810x67400xA5010x65C00x64800xA441,
    100             0x6C000xACC10xAD810x6D400xAF010x6FC00x6E800xAE41,
    101             0xAA010x6AC00x6B800xAB410x69000xA9C10xA8810x6840,
    102             0x78000xB8C10xB9810x79400xBB010x7BC00x7A800xBA41,
    103             0xBE010x7EC00x7F800xBF410x7D000xBDC10xBC810x7C40,
    104             0xB4010x74C00x75800xB5410x77000xB7C10xB6810x7640,
    105             0x72000xB2C10xB3810x73400xB1010x71C00x70800xB041,
    106             0x50000x90C10x91810x51400x93010x53C00x52800x9241,
    107             0x96010x56C00x57800x97410x55000x95C10x94810x5440,
    108             0x9C010x5CC00x5D800x9D410x5F000x9FC10x9E810x5E40,
    109             0x5A000x9AC10x9B810x5B400x99010x59C00x58800x9841,
    110             0x88010x48C00x49800x89410x4B000x8BC10x8A810x4A40,
    111             0x4E000x8EC10x8F810x4F400x8D010x4DC00x4C800x8C41,
    112             0x44000x84C10x85810x45400x87010x47C00x46800x8641,
    113             0x82010x42C00x43800x83410x41000x81C10x80810x4040,};
    114 
    115         byte[] bytes = pBuffer;
    116         int crc = 0x0000;
    117         for (byte b : bytes) {
    118             crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
    119         }
    120 
    121         return crc;
    122     }

      

    还有一种让Java和.Net兼容的方式,在.Net中指定模式为ECB,填充为PKCS7,然后在Java中采用其默认的模式(DESede/ECB/PKCS5Padding)即可,注意双方约定key的size为24个字节。建议双方对key以base64编码字符串进行告知,因为java和.net中byte字节的范围不相同(前者-128~127,后者0~255),避免不必要的处理。

  • 相关阅读:
    创建maven项目
    有pom.xml文件但是无法用maven构建问题
    Linux关闭防火墙,开放端口
    Java SSH远程执行Shell命令、shell脚本实现(Ganymed SSH)
    linux系统切换用户
    Looksery Cup 2015 C. The Game Of Parity —— 博弈
    Codeforces Round #105 (Div. 2) E. Porcelain —— DP(背包问题)
    Codeforces Round #198 (Div. 2) E. Iahub and Permutations —— 容斥原理
    Educational Codeforces Round 9 C. The Smallest String Concatenation —— 贪心 + 字符串
    Technocup 2017
  • 原文地址:https://www.cnblogs.com/tearer/p/2284432.html
Copyright © 2020-2023  润新知