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即可。

  1.  
  2.   1 public class CDES {
  3.   2 
  4.   3     public static byte[] encrypt(String sKey, byte[] bIV, byte[] bPlainText, int nOffset, int nSize)
  5.   4             throws Exception {
  6.   5         byte[] bKey = buildKey(sKey);
  7.   6         byte[] bInput = buildInput(nSize, bPlainText, nOffset);
  8.   7         byte[] bResult = encrypt(bIV, bKey, bInput);
  9.   8         return bResult;
  10.   9     }
  11.  10 
  12.  11     public static byte[] decrypt(String sKey, byte[] bIV, byte[] bCipherText)
  13.  12             throws Exception {
  14.  13         byte[] bKey = buildKey(sKey);
  15.  14         SecretKey securekey = buildSecretKey(bKey);
  16.  15         IvParameterSpec iv = new IvParameterSpec(bIV);
  17.  16         Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
  18.  17         SecureRandom sr = new SecureRandom();
  19.  18         cipher.init(Cipher.DECRYPT_MODE, securekey, iv, sr);
  20.  19         byte[] bOutput = cipher.doFinal(bCipherText);
  21.  20         int nLen = 0;
  22.  21         nLen = nLen | (int) bOutput[0];
  23.  22         nLen = nLen | ((int) bOutput[1] << 8);
  24.  23         if (nLen > bOutput.length - 4) {
  25.  24             throw new Exception("非法的密文");
  26.  25         }        
  27.  26         byte[] bResult = new byte[bOutput.length  - 4];
  28.  27         bResult = Arrays.copyOfRange(bOutput, 2, bOutput.length - 2);
  29.  28         return bResult;
  30.  29     }
  31.  30 
  32.  31     private static byte[] md5Digest(String sData) throws NoSuchAlgorithmException {
  33.  32         MessageDigest md5 = MessageDigest.getInstance("MD5");
  34.  33         byte[] bData = sData.getBytes();
  35.  34         md5.update(bData, 0, bData.length);
  36.  35         byte[] hash = md5.digest();
  37.  36         return hash;
  38.  37     }
  39.  38 
  40.  39     private static byte[] buildInput(int nSize, byte[] bPlainText, int nOffset) {
  41.  40         byte[] bInput = new byte[nSize + 4];
  42.  41         for (int i = 0; i < bPlainText.length; i++) {
  43.  42             Arrays.fill(bInput, 2 + i, 2 + i + 1, bPlainText[i]);
  44.  43         }
  45.  44         int usCRC = CCRC16.CalcCrcCheckSum(bPlainText, nOffset, nSize);
  46.  45         bInput[0] = (byte) (nSize & 0xFF);
  47.  46         bInput[1] = (byte) (nSize >> 8 & 0xFF);
  48.  47         bInput[nSize + 2] = (byte) (usCRC & 0xFF);
  49.  48         bInput[nSize + 3] = (byte) (usCRC >> 8 & 0xFF);
  50.  49         return bInput;
  51.  50     }
  52.  51 
  53.  52     private static byte[] buildKey(String sKey) throws NoSuchAlgorithmException {
  54.  53         byte[] bTmp = md5Digest(sKey);
  55.  54         byte[] bKey = new byte[24];
  56.  55         System.arraycopy(bTmp,0,bKey,0,bTmp.length);
  57.  56         System.arraycopy(bTmp,0,bKey,16,8);
  58.  57         return bKey;
  59.  58     }
  60.  59 
  61.  60     private static SecretKey buildSecretKey(byte[] bkey) throws InvalidKeyException,
  62.  61             InvalidKeySpecException, NoSuchAlgorithmException {
  63.  62         DESedeKeySpec dks = new DESedeKeySpec(bkey);
  64.  63         SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
  65.  64         SecretKey securekey = keyFactory.generateSecret(dks);
  66.  65         return securekey;
  67.  66     }
  68.  67 
  69.  68     private static byte[] encrypt(byte[] biv, byte[] bkey, byte[] input) throws Exception {
  70.  69         SecretKey securekey = buildSecretKey(bkey);
  71.  70         IvParameterSpec iv = new IvParameterSpec(biv);
  72.  71         Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
  73.  72         SecureRandom sr = new SecureRandom();
  74.  73         cipher.init(Cipher.ENCRYPT_MODE, securekey, iv, sr);
  75.  74         return cipher.doFinal(input);
  76.  75     }
  77.  76 }
  78.  77 
  79.  78 class CCRC16 {
  80.  79     public static int CalcCrcCheckSum(byte[] pBuffer, int nOffset, int nSize) {
  81.  80 
  82.  81         int[] table = {
  83.  82             0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
  84.  83             0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
  85.  84             0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
  86.  85             0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
  87.  86             0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
  88.  87             0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
  89.  88             0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
  90.  89             0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
  91.  90             0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
  92.  91             0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
  93.  92             0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
  94.  93             0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
  95.  94             0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
  96.  95             0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
  97.  96             0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
  98.  97             0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
  99.  98             0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
  100.  99             0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
  101. 100             0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
  102. 101             0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
  103. 102             0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
  104. 103             0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
  105. 104             0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
  106. 105             0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
  107. 106             0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
  108. 107             0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
  109. 108             0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
  110. 109             0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
  111. 110             0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
  112. 111             0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
  113. 112             0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
  114. 113             0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040,};
  115. 114 
  116. 115         byte[] bytes = pBuffer;
  117. 116         int crc = 0x0000;
  118. 117         for (byte b : bytes) {
  119. 118             crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
  120. 119         }
  121. 120 
  122. 121         return crc;
  123. 122     }

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

java 与 c# 3des 加解密的更多相关文章

  1. PHP版3DES加解密类

    <?php /** * * PHP版3DES加解密类 * * 可与java的3DES(DESede)加密方式兼容 * * @Author:蓝凤(ilanfeng.com) * * @versio ...

  2. 3DES加解密【示例】

    代码 /**  * 3DES加解密  */ public class DESedeUtils {     private static final String ALGORITHM_MD5 = &qu ...

  3. 3DES 加解密

    using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace Comm ...

  4. C# RSA加解密与验签,AES加解密,以及与JAVA平台的密文加解密

    前言: RSA算法是利用公钥与密钥对数据进行加密验证的一种算法.一般是拿私钥对数据进行签名,公钥发给友商,将数据及签名一同发给友商,友商利用公钥对签名进行验证.也可以使用公钥对数据加密,然后用私钥对数 ...

  5. 3DES加解密 C语言

    3DES(或称为Triple DES),它相当于是对每个数据块应用三次DES加密算法.3*8字节密钥. 设Ek()和Dk()代表DES算法的加密和解密过程,K代表DES算法使用的密钥,P代表明文,C代 ...

  6. Java中的AES加解密工具类:AESUtils

    本人手写已测试,大家可以参考使用 package com.mirana.frame.utils.encrypt; import com.mirana.frame.constants.SysConsta ...

  7. 最新版-Python和Java实现Aes相互加解密

    前情 需要使用Python和Java实现同一个AES加解密算法,使Python版本加密的密文能够由Java代码解密,反之亦然. Python实现 Python为3.6版本 # -*- coding: ...

  8. 3DES加解密类

    using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace GT.C ...

  9. 与非java语言使用RSA加解密遇到的问题:algid parse error, not a sequence

    遇到的问题 在一个与Ruby语言对接的项目中,决定使用RSA算法来作为数据传输的加密与签名算法.但是,在使用Ruby生成后给我的私钥时,却发生了异常:IOException: algid parse ...

随机推荐

  1. JavaScript(JS)入门篇

    <script type="text/javascript"> 表示在<script></script>之间的是文本类型(text),javas ...

  2. [转载]pytest学习笔记

    pytest学习笔记(三)   接着上一篇的内容,这里主要讲下参数化,pytest很好的支持了测试函数中变量的参数化 一.pytest的参数化 1.通过命令行来实现参数化 文档中给了一个简单的例子, ...

  3. kvm批量创建虚拟主机

    1.首先你的提前创建一个kvm虚拟机主机,才能批量复制创建 批量复制已经安装好的系统盘 `;.img centos7-$i.img && echo $i ;done 批量复制已经安装好 ...

  4. Beyond Compare 4 使用30天后过期续用方法

    Beyond Compare 4 使用30天后过期续用方法 windows上的Beyond Compare 4软件过期了,两个方法: 方案一: 找到Beyond Compare 4安装目录,安装时默认 ...

  5. localstorage ie11不支持

    据我所知,localstorage在高版本的ie.谷歌.火狐下都是支持的,以前没在ie上看过,不清楚,今天我用ie11打开我vue编译后的html,竟然发现不支持localstorage了,用仿真的i ...

  6. crypot.js 生成hash256, 在IE下的卡顿问题。

    项目需求: 上传大文件,调用crypto.js生成hash256码. 直接上传大文件,IE会直接崩溃. 于是利用file.slice分片检测.但是浏览器会出现卡顿问题.开始以为是内存泄漏.但看服务器进 ...

  7. [转载]作为理工科学生,我们为什么要练就好的文笔?我们需要发blog来记录学习历程?

    文/JoeyChen 工程师该怎样才能突破自己的能力瓶颈?写 blog! 工程师该怎样精进自己在职涯上所需要的能力?写 blog! 工程师该怎样才能保持学习与成长的动能?写 blog! 工程师该怎样才 ...

  8. python 生成金字塔

    num = eval(input("请输入一个整数:")) , num + ): , -): print(" ", end="\t") , ...

  9. js中的时间显示

    var approveTime; approveTime=new Date(da[i].approveTime).toLocaleDateString(); 结果是 xxxx年xx月xx日

  10. JavaWeb_(Spring框架)Spring整合Hibernate

    Dao层类要继承HibernateDaoSupport.java父类 原先使用Hibernate框架hibernate.cfg.xml配置数据库 <hibernate-configuration ...