DES加密解密问题,java 和 C#

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DES加密解密问题,java 和 C#相关的知识,希望对你有一定的参考价值。

用户是java那边创建的,密码是用des加密的,现在C#这边要登录就要解密或者加密用户输入的密码。
java那边加密所用的
key是:beLd7$lB
向量是:Sa#qk5usfmMI-@2dbZP9`jL3
111111加密后得到500C7C9864165AD6E8A35E1EFC5279C2

现在C#用des加密111111怎么也得不到500C7C9864165AD6E8A35E1EFC5279C2
解密500C7C9864165AD6E8A35E1EFC5279C2也是得不到111111

希望有大神能用C#把111111加密成500C7C9864165AD6E8A35E1EFC5279C2
或者把500C7C9864165AD6E8A35E1EFC5279C2解密成111111
谢谢

 using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security;
using System.Security.Cryptography;
/*----------------------------------------------
 *  DES加密、解密类库,字符串加密结果使用BASE64编码返回,支持文件的加密和解密
 *  作者: 三角猫/DeltaCat
 *  网址: 

 *  转载务必保留此信息
 * ---------------------------------------------
 */
namespace ZU14

    public sealed class DES
    
        string iv = "1234的yzo";
        string key = "123在yzo";
        /// <summary>
        /// DES加密偏移量,必须是>=8位长的字符串
        /// </summary>
        public string IV
        
            get  return iv; 
            set  iv = value; 
        
        /// <summary>
        /// DES加密的私钥,必须是8位长的字符串
        /// </summary>
        public string Key
        
            get  return key; 
            set  key = value; 
        
        /// <summary>
        /// 对字符串进行DES加密
        /// </summary>
        /// <param name="sourceString">待加密的字符串</param>
        /// <returns>加密后的BASE64编码的字符串</returns>
        public string Encrypt(string sourceString)
        
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream())
            
                byte[] inData = Encoding.Default.GetBytes(sourceString);
                try
                
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    
                    return Convert.ToBase64String(ms.ToArray());
                
                catch
                
                    throw;
                
            
        
        /// <summary>
        /// 对DES加密后的字符串进行解密
        /// </summary>
        /// <param name="encryptedString">待解密的字符串</param>
        /// <returns>解密后的字符串</returns>
        public string Decrypt(string encryptedString)
        
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            using (MemoryStream ms = new MemoryStream())
            
                byte[] inData = Convert.FromBase64String(encryptedString);
                try
                
                    using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    
                        cs.Write(inData, 0, inData.Length);
                        cs.FlushFinalBlock();
                    
                    return Encoding.Default.GetString(ms.ToArray());
                
                catch
                
                    throw;
                
            
        
        /// <summary>
        /// 对文件内容进行DES加密
        /// </summary>
        /// <param name="sourceFile">待加密的文件绝对路径</param>
        /// <param name="destFile">加密后的文件保存的绝对路径</param>
        public void EncryptFile(string sourceFile, string destFile)
        
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路径不存在!", sourceFile);
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);
            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            
                try
                
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateEncryptor(btKey, btIV), CryptoStreamMode.Write))
                    
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    
                
                catch
                
                    throw;
                
                finally
                
                    fs.Close();
                
            
        
        /// <summary>
        /// 对文件内容进行DES加密,加密后覆盖掉原来的文件
        /// </summary>
        /// <param name="sourceFile">待加密的文件的绝对路径</param>
        public void EncryptFile(string sourceFile)
        
            EncryptFile(sourceFile, sourceFile);
        
        /// <summary>
        /// 对文件内容进行DES解密
        /// </summary>
        /// <param name="sourceFile">待解密的文件绝对路径</param>
        /// <param name="destFile">解密后的文件保存的绝对路径</param>
        public void DecryptFile(string sourceFile, string destFile)
        
            if (!File.Exists(sourceFile)) throw new FileNotFoundException("指定的文件路径不存在!", sourceFile);
            byte[] btKey = Encoding.Default.GetBytes(key);
            byte[] btIV = Encoding.Default.GetBytes(iv);
            DESCryptoServiceProvider des = new DESCryptoServiceProvider();
            byte[] btFile = File.ReadAllBytes(sourceFile);
            using (FileStream fs = new FileStream(destFile, FileMode.Create, FileAccess.Write))
            
                try
                
                    using (CryptoStream cs = new CryptoStream(fs, des.CreateDecryptor(btKey, btIV), CryptoStreamMode.Write))
                    
                        cs.Write(btFile, 0, btFile.Length);
                        cs.FlushFinalBlock();
                    
                
                catch
                
                    throw;
                
                finally
                
                    fs.Close();
                
            
        
        /// <summary>
        /// 对文件内容进行DES解密,加密后覆盖掉原来的文件
        /// </summary>
        /// <param name="sourceFile">待解密的文件的绝对路径</param>
        public void DecryptFile(string sourceFile)
        
            DecryptFile(sourceFile, sourceFile);
        
    

追问

刚才才输入了个题目,还没描述问题你就回答了

追答

没有提供对应的算法吗?

追问

java里有这么一段解密的代码,在具体的我就知道了

追答

你这个貌似不是DES加密吧? MXCipher类是Des加密封装后的类?

追问

是的

参考技术A 按道理说,直接用C# 的DLL加密就该是一样的。
如果得不到一样的结果,说明别人加密的还是还带了其他的信息进去。
比如密码加上了用户名后再加密,很多系统都这么设计加密。
希望给你一个别的考虑思路。

C# 到 Java DES 加密

【中文标题】C# 到 Java DES 加密【英文标题】:C# to Java DES encryption 【发布时间】:2017-03-08 07:15:42 【问题描述】:

尝试创建 java 类,该类将像下面的 C# 代码一样加密和解密。

以下是我的 C# 代码,我需要将其转换为 Java。有人可以帮我怎么做吗?

我已经这样做了将近 2 天,但找不到任何关于如何转换它的解决方案。我是加密新手。

注意 - 似乎 C# 代码使用了 ACME 库。但在我的 java 中,我不应该使用 ACME jar 文件。

public static string EncryptBase64(string key, string clearText)
    
        if (key.Length > 8)
            key = key.Substring(0, 8);

        byte[] keyBytes = System.Text.Encoding.ASCII.GetBytes(key);
        byte[] clearBytes = GetClearTextBytes(clearText);

        // calculate the number of legitimate bytes in the last block
        byte lastByte = (byte)(8 - (clearBytes.Length - textEncoding.GetByteCount(clearText)));

        MemoryStream ms = new MemoryStream();

        DES des = new DESCryptoServiceProvider();
        des.Padding = PaddingMode.None;
        des.GenerateIV();

        System.Security.Cryptography.ICryptoTransform ict = des.CreateEncryptor(keyBytes, des.IV);
        CryptoStream cs = new CryptoStream(ms, ict, CryptoStreamMode.Write);
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.FlushFinalBlock();
        ms.Close();

        byte[] cipherBytes = ms.ToArray();

        // create a byte output stream for Acme compatibality
        MemoryStream acmeCompatStream = new MemoryStream();

        // Acme writes the IV to the frist block
        acmeCompatStream.Write(des.IV, 0, 8);

        for (int i = 0; i < cipherBytes.Length; i = i + 8)
        
            // write the next block
            acmeCompatStream.Write(cipherBytes, i, 8);

            // write the number of valid bytes in the block
            if (i == cipherBytes.Length - 8)
                acmeCompatStream.WriteByte(lastByte);
            else
                acmeCompatStream.WriteByte(8);
        

        acmeCompatStream.Close();

        cipherBytes = acmeCompatStream.ToArray();

        return (System.Convert.ToBase64String(cipherBytes));
    

以下是我在 java 中尝试过的代码。我有两种不同的加密功能。这两种加密方法我都试过了。但是两者都没有给出预期的加密字符串以在 acme 中解密。

    package com.abc.some.common.nativeDES;

    import java.io.ByteArrayOutputStream;
import java.security.spec.KeySpec;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.bind.DatatypeConverter;

public class DESEncrypt 
    public String keyValue = "123456789";
    public static void main(String[] args) 
        String text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>";
        String codedtext ="not encrypted";
        try
            codedtext = new DESEncrypt().Encrypt1(text);
            //codedtext = new DESEncrypt().encrypt(text);
        catch (Exception e) 
            System.out.println("Exception in Encryption.. " + e.getMessage());
        

        System.out.println(codedtext);

    
    public String Encrypt1(String CXML) 
        try 
            KeySpec myKey = new DESKeySpec(keyValue.getBytes("UTF8"));
        SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(myKey);
        Cipher ecipher = Cipher.getInstance("DES");
        ecipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] data = CXML.getBytes("ASCII");

        Cipher c = Cipher.getInstance("DES/CBC/PKCS5Padding");
        c.init(Cipher.ENCRYPT_MODE, key);

        byte[] crypt = ecipher.doFinal(data);
        //String encoded = DatatypeConverter.printBase64Binary(crypt.toString().getBytes("ASCII"));
        //String encoded = DatatypeConverter.printBase64Binary(crypt.getBytes("ASCII"));

        String encoded = DatatypeConverter.printBase64Binary(crypt).toString();

        System.out.println(encoded);

        return encoded;
         catch (Exception ex) 
        

        return null;
        

但我使用下面的 java 文件来加密使用 acme jar 文件的字符串。这按预期工作。但根据我的项目要求,我不应该使用外部(ACME)jar 文件。

package com.abc.common.encryption;

import java.io.FileInputStream;
import java.util.Properties;
import Acme.Crypto.SecurityDES;

public class ESBCryptoDES 

    public static void main(String args[])
//      DESEncrypt("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?><SomeRequest><OrderNumber>1564578</OrderNumber></SomeRequest>"
//              ,"D:\\name\\proj\\order\\Encryption\\st.properties");
        DESDecrypt("vQ9C7ZrLzjQpHvZjtHvUb0mFCr824/aClY2jKbeciczsRVr+kEETFvDuHgdBS/aLskYV3WX3U5TANSlK3pH80r3xOyn9Q8rTjlB/yXyU7J9MgibJ66jJx0wrqeloAkmQzqj+b5+I/lXANSlK3pH80kT1D+jqWAeV"
                ,"D:\\name\\proj\\order\\Encryption\\stDecrypt.properties");
    
    public static String DESEncrypt(String SourceStrForCrypt,String PropPath) 
        String encrypt = "";
        String decrypt = "";
        // Load the property file.
        Properties prop = new Properties();
        try 
            FileInputStream in = new FileInputStream(PropPath);
            prop.load(in);
            in.close();
         catch (Exception e) 
            System.out.println("Exception in loading property file.. "
                    + e.getMessage());
        

        // Encrypt the given content.
        try 
            String keypath = prop.getProperty("proj.sample.DEV");
            System.out.println("sample" + keypath);

            String SourceToEncrypt = SourceStrForCrypt; //This will provide the xml string to encrypt
            // Encryption
            encrypt = SecurityDES.DesEncryptBase64(keypath,SourceToEncrypt);
            System.out.println(encrypt);
            // Decryption
            decrypt = SecurityDES.DesDecryptBase64(keypath, encrypt);
            System.out.println(decrypt);

         catch (Exception e) 
            System.out.println("Exception in Encryption.. " + e.getMessage());
        
        return encrypt;
    

    public static String DESDecrypt(String SourceStrForCrypt,String PropPath) 
        // TODO Auto-generated method stub
        String decrypt = "";

        Properties prop = new Properties();

        try 
            FileInputStream in = new FileInputStream(PropPath);
            prop.load(in);
            in.close();
         catch (Exception e) 
            System.out.println("Exception in loading property file.. "+ e.getMessage());
        

        try 
            String abc_keyPath = prop
                    .getProperty("proj.abc.DEV");
            System.out.println("keypath" + abc_keyPath);
            // Decryption
            decrypt = SecurityDES.DesDecryptBase64(abc_keyPath, SourceStrForCrypt);
            System.out.println("decrypted..."+decrypt);

         catch (Exception e) 
            System.out.println("Exception in Encryption.. " + e.getMessage());
        
        return decrypt;

    

【问题讨论】:

向我们展示您的尝试,并准确告诉我们问题所在。 *** 不是代码转换服务。而且你不应该使用 DES。 如果您使用 ACME 表示内置,也就是您应该自己编写 DES(大概是作为家庭作业),那么请参阅 FIPS PUB 46(-3) 了解算法和 NIST SP 800-17(附录A) 用于测试验证。 -- 如果你不应该自己编写 DES,你至少需要解释你想出的错误答案。 @JBNizet .. 我很抱歉没有分享我尝试过的 java 工作。用我尝试过的 java 代码更新了我的问题。你能说明一下我的 java 代码出了什么问题吗? 【参考方案1】: 调用doFinal() 两次没有意义。 打印byte[].toString() 的值没有意义。它不包含密文。 将其转换为 base-64 没有意义。它仍然不包含密文。

您需要将第一个doFinal()调用直接返回的byte[]数组转换为base-64,而不需要调用toString()引起的往返String()然后是`getBytes()。

NB 出于某种原因,您的 decrypt 方法中有一个名为 encrypt 的变量,并且出于一些更奇怪的原因,您返回它而不是 decrypt,它实际上是唯一的变量包含明文。

【讨论】:

我已根据您的 cmets 更新了我的代码。仍然当我调用 base64 而不转换为字符串时,会引发错误。我已经尝试过如下声明。 //字符串编码 = DatatypeConverter.printBase64Binary(crypt.toString().getBytes("ASCII"));字符串编码 = DatatypeConverter.printBase64Binary(crypt.getBytes("ASCII")); 叹息。打字前请三思。 crypt 已经是 byte[]。我特别说“将它直接转换为base-64”。您无需执行任何操作即可将其作为byte[] 获取。而你不能。编译器刚刚告诉你。注意它没有“给你一个错误”。编译器消息被打印,而不是被抛出。运行时抛出异常。思路清晰,报告内容清晰。 我接受我的错误并根据您的 cmets 更新了我的 java 代码。尝试了一些类似下面的东西。字符串编码 = DatatypeConverter.printBase64Binary(crypt).toString();现在我得到了一些加密的字符串,我尝试使用 ACME jar 类解密它,它给我一个错误,说“加密的字节长度:120 无效的密文字节数” DatatypeConverter.printBase64Binary()的输出类型是什么?以及为什么需要将其转换为String 删除了字符串转换,正如您所提到的,它不是必需的。

以上是关于DES加密解密问题,java 和 C#的主要内容,如果未能解决你的问题,请参考以下文章

使用C# DES解密java DES加密的字符串

DES加密,如何解决C#、Java互通时补位算法的问题

C# 到 Java DES 加密

一个java的DES加解密类转换成C#

java的 DES 加密解密方法 求对应C#的加密解密方法,急切

java 与 c# 3des 加解密