【问题标题】:AES Crypto C# compatible JavaAES Crypto C# 兼容 Java
【发布时间】:2021-08-10 00:58:04
【问题描述】:

我在 C# 中有这段代码,它生成一个加密的密码。 我想让它在 Java 中兼容。

C#代码

private static string ccs = "&Ux#B*******";

    private static ICryptoTransform __Get_AES128_Transform(string password, bool AsDecryptor)
    {
        const int KEY_SIZE = 16;
        var sha256CryptoServiceProvider = new SHA256CryptoServiceProvider();
        var hash = sha256CryptoServiceProvider.ComputeHash(Encoding.Unicode.GetBytes(password));
        var key = new byte[KEY_SIZE];
        var iv = new byte[KEY_SIZE];
        Buffer.BlockCopy(hash, 0, key, 0, KEY_SIZE);
        if (AsDecryptor)
            return new AesCryptoServiceProvider().CreateDecryptor(key, iv);
        else
            return new AesCryptoServiceProvider().CreateEncryptor(key, iv);
    }

    public static string Encrypt(this string Value)
    {
        byte[] Buffer = Encoding.Unicode.GetBytes(Value);
        using (ICryptoTransform transform = __Get_AES128_Transform(ccs, false))
        {
            byte[] encyptedBlob = transform.TransformFinalBlock(Buffer, 0, Buffer.Length);
            return Convert.ToBase64String(encyptedBlob);
        }
    }

谁能给出用java解密的方向?

【问题讨论】:

  • 您是否特别需要该代码?
  • 是的,很遗憾这段代码已经在运行了。 ;/ 因为?
  • 好吧,Unicode 基本上是一个名不副实的 UTF-16LE,除此之外:你尝试过什么? SO 不是代码翻译服务。

标签: java c# passwords aes


【解决方案1】:

我的回答是互操作加密,希望对你有所帮助。结果可以从任何平台解密 - C# 代码或 Android/Java 代码。

  • 从 C# 加密 -> 从 C#、Android、Java 解密。
  • 从 Android 加密 -> 从 Android、Java、C# 解密。
  • 从 Java 加密 -> 从 Java、Android、C# 解密。
  • 加密结果包含密文+IV。
  • IV 是使用安全随机算法生成的。

加密过程

  1. 转换明文 => 明文字节
  2. 转换密码 => passwordBytes => Sha256(passwordbytes) = passwordHashBytes
  3. 生成随机 IV 字节 = ivBytes
  4. 使用plaintextbytes 和passwordHashBytes 加密
  5. 加入(加密字节 + ivBytes)
  6. 转换为 base64 连接字节。

解密过程

  1. 将 base64 字符串转换为字节。
  2. 拆分数组 encryptedBytes、ivBytes
  3. 转换密码 => passwordBytes => Sha256(passwordbytes) = passwordHashBytes
  4. 使用 ivBytes、EncryptedBytes、PasswordHashBytes 解密
  5. 将 DecryptedBytes 转换为字符串

IV 在每个 Encrypt 过程中都是随机的,以获得相同文本的不同输出,避免入侵者/攻击者轻易获得原始文本。

默认模式为 CBC。

使用的编码是 UTF-8。 UTF-8 是网络上使用最广泛的编码。检查Usage of character encodings broken down by ranking


参考文献

Initialization vector
Block cipher mode of operation


C# 实现

using System;
using System.Security.Cryptography;
using System.Text;

public enum HashAlgorithm
{
    MD5,
    SHA1,
    SHA256,
    SHA384,
    SHA512
}

public class HashManager
{
    public static byte[] ToRawHash(byte[] data, HashAlgorithm algorithm)
    {
        byte[] hash;
        switch (algorithm)
        {
            case HashAlgorithm.MD5:
                MD5 md5 = MD5.Create();
                hash = md5.ComputeHash(data, 0, data.Length);
                return hash;
            case HashAlgorithm.SHA1:
                SHA1Managed sha1 = new SHA1Managed();
                hash = sha1.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA256:
                SHA256Managed sha256 = new SHA256Managed();
                hash = sha256.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA384:
                SHA384Managed sha384 = new SHA384Managed();
                hash = sha384.ComputeHash(data);
                return hash;
            case HashAlgorithm.SHA512:
                SHA512Managed sha512 = new SHA512Managed();
                hash = sha512.ComputeHash(data, 0, data.Length);
                return hash;
            default:
                throw new ArgumentException("Invalid Algorithm");
        }
    }
}

public class AesManager
{
    private const int MAX_IV_LENGTH = 16;
    private const int MAX_KEY_LENGTH = 32;

    private static byte[] GenerateValidKey(byte[] keyBytes)
    {
        byte[] ret = new byte[MAX_KEY_LENGTH];
        byte[] hash = HashManager.ToRawHash(keyBytes, HashAlgorithm.SHA256);
        Array.Copy(hash, ret, MAX_KEY_LENGTH);
        return ret;
    }


    public static byte[] EncryptRaw(byte[] PlainBytes, byte[] Key)
    {
        AesManaged AesAlgorithm = new AesManaged()
        {
            Key = GenerateValidKey(Key)
        };
        AesAlgorithm.GenerateIV();
        var Encrypted = AesAlgorithm.CreateEncryptor().TransformFinalBlock(PlainBytes, 0, PlainBytes.Length);
        byte[] ret = new byte[Encrypted.Length + MAX_IV_LENGTH];
        Array.Copy(Encrypted, ret, Encrypted.Length);
        Array.Copy(AesAlgorithm.IV, 0, ret, ret.Length - MAX_IV_LENGTH, MAX_IV_LENGTH);
        return ret;
    }

    public static byte[] DecryptRaw(byte[] CipherBytes, byte[] Key)
    {
        AesManaged AesAlgorithm = new AesManaged()
        {
            Key = GenerateValidKey(Key)
        };
        byte[] IV = new byte[MAX_IV_LENGTH];
        Array.Copy(CipherBytes, CipherBytes.Length - MAX_IV_LENGTH, IV, 0, MAX_IV_LENGTH);
        AesAlgorithm.IV = IV;
        byte[] RealBytes = new byte[CipherBytes.Length - MAX_IV_LENGTH];
        Array.Copy(CipherBytes, RealBytes, CipherBytes.Length - MAX_IV_LENGTH);
        return AesAlgorithm.CreateDecryptor().TransformFinalBlock(RealBytes, 0, RealBytes.Length); ;
    }


    public static String EncryptToBase64(String Plaintext, String Key)
    {
        byte[] PlainBytes = Encoding.UTF8.GetBytes(Plaintext);
        return Base64Manager.ToBase64(EncryptRaw(PlainBytes, Encoding.UTF8.GetBytes(Key)), false);
    }



    public static String DecryptFromBase64(String CipherText, String Key)
    {
        byte[] CiPherBytes = Base64Manager.Base64ToByteArray(CipherText);
        byte[] Encrypted = DecryptRaw(CiPherBytes, Encoding.UTF8.GetBytes(Key));
        return Encoding.UTF8.GetString(Encrypted, 0, Encrypted.Length);
    }

}

public class Base64Manager
{
    public static byte[] Base64ToByteArray(String base64)
    {
        return Convert.FromBase64String(base64);
    }

    public static String ToBase64(byte[] data, Boolean insertLineBreaks = default(Boolean))
    {
        return insertLineBreaks ? Convert.ToBase64String(data, Base64FormattingOptions.InsertLineBreaks) : Convert.ToBase64String(data);
    }
}


public class Program
{
    public static void Main()
    {
        string plainText = "plain text";
        string password = "password";
        string encrypted = AesManager.EncryptToBase64(plainText, password);
        Console.WriteLine(encrypted);
        Console.WriteLine(AesManager.DecryptFromBase64(encrypted, password));
        Console.ReadLine();
    }
}


Android/Java 实现

public enum HashAlgorithm {

    SHA512("SHA-512"),
    SHA256("SHA-256"),
    SHA384("SHA-384"),
    SHA1("SHA-1"),
    MD5("MD5");

    private String Value = "";

    HashAlgorithm(String Value) {
        this.Value = Value;
    }

    @Override
    public String toString() {
        return Value;
    }

}

import java.security.MessageDigest;
public class HashManager {
    public static byte[] toRawHash(byte[] data,
                                   HashAlgorithm algorithm) throws Exception
    {
        byte[] buffer = data;
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm.toString());
        messageDigest.reset();
        messageDigest.update(buffer);
        return messageDigest.digest();
    }
}

Base64Manager 类 Android 实现

    import android.util.Base64;
    
    public class Base64Manager {
        public static String toBase64(byte[] data,
                                      boolean insertLineBreaks) throws Exception
        {
            String ret;
            if (insertLineBreaks)
            {
                ret = Base64.encodeToString(data, Base64.DEFAULT);
            }
            else
            {
                ret = Base64.encodeToString(data, Base64.NO_WRAP);
            }
            return ret;
        }
    
        public static String toBase64(String data,
                                      boolean insertLineBreaks) throws Exception
        {
            return toBase64(data.getBytes("UTF-8"), insertLineBreaks);
        }
    
        public static byte[] base64ToByteArray(String base64) throws Exception
        {
            return base64.contains(System.getProperty("line.separator")) ? Base64.decode(base64, Base64.DEFAULT) : Base64.decode(base64, Base64.NO_WRAP);
        }
    }

Base64Manager 类 Java8+ 实现

    import java.util.Base64;
    
    public class Base64Manager {    
        public static String toBase64(byte[] data, Boolean insertLineBreaks) throws Exception {
            String ret;
            if (insertLineBreaks) {
                ret = Base64.getMimeEncoder().encodeToString(data);
            } else {
                ret = Base64.getEncoder().encodeToString(data);
            }
            return ret;
        }
    
        public static String toBase64(String data, Boolean insertLineBreaks) throws Exception {
            return toBase64(data.getBytes("UTF-8" ), insertLineBreaks);
        }
    
        public static byte[] base64ToByteArray(String base64) throws Exception {
            return base64.contains(System.getProperty("line.separator")) ? Base64.getMimeDecoder().decode(base64) : Base64.getDecoder().decode(base64);
        }    
    }


    import java.security.SecureRandom;
    import java.util.Arrays;
    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    public class AesManager {
    
        private static final int MAX_IV_LENGTH = 16;
        private static final int MAX_KEY_LENGTH = 32;
    
        public static String decryptFromBase64(String cipherText, String key) throws Exception {
            byte[] CiPherBytes = Base64Manager.base64ToByteArray(cipherText);
            byte[] KeyBytes = key.getBytes("UTF-8");
            return new String((decryptRaw(CiPherBytes, KeyBytes)));
        }
    
        public static byte[] generateValidKey(byte[] key) throws Exception {
            return Arrays.copyOf(HashManager.toRawHash(key, HashAlgorithm.SHA256), MAX_KEY_LENGTH);
        }
    
    
        public static byte[] decryptRaw(byte[] cipherBytes, byte[] keyBytes) throws Exception {
            byte[] IV = Arrays.copyOfRange(cipherBytes, cipherBytes.length - MAX_IV_LENGTH, cipherBytes.length);
            byte[] RealBytes = Arrays.copyOf(cipherBytes, cipherBytes.length - MAX_IV_LENGTH);
            Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding" );
            byte[] ValidKeyBytes = generateValidKey(keyBytes);
            SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(IV);
            AesAlgorithm.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] Decrypted = AesAlgorithm.doFinal(RealBytes);
            return Decrypted;
        }
    
        public static byte[] encryptRaw(byte[] plainBytes, byte[] keyBytes) throws Exception {
            Cipher AesAlgorithm = Cipher.getInstance("AES/CBC/PKCS5Padding");
            byte[] ValidKeyBytes = generateValidKey(keyBytes);
            SecretKeySpec secretKeySpec = new SecretKeySpec(ValidKeyBytes, "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(generateIV());
            AesAlgorithm.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
            byte[] Encrypted = AesAlgorithm.doFinal(plainBytes);
            byte[] ret = new byte[Encrypted.length + MAX_IV_LENGTH];
            System.arraycopy(Encrypted, 0, ret, 0, Encrypted.length);
            System.arraycopy(ivParameterSpec.getIV(), 0, ret, Encrypted.length, MAX_IV_LENGTH);
            return ret;
        }
    
        private static byte[] generateIV() throws Exception {
            return generateRandomArray(MAX_IV_LENGTH);
        }
    
        public static byte[] generateRandomArray(int size) {
            SecureRandom RandomGenerator = new SecureRandom();
            byte[] ret = new byte[size];
            RandomGenerator.nextBytes(ret);
            return ret;
        }
    
        public static String encryptToBase64(String plaintext, String key) throws Exception {
            byte[] PlainBytes = plaintext.getBytes("UTF-8");
            byte[] KeyBytes = key.getBytes("UTF-8");
            return Base64Manager.toBase64(encryptRaw(PlainBytes, KeyBytes), false);
        }
    
    }


    public class Program {
        public static  void main(String[] args) throws Exception
        {
            String plainText = "plain text";
            String password = "password";
            String encrypted = AesManager.encryptToBase64(plainText, password);
            System.out.println(encrypted);
            System.out.println(AesManager.decryptFromBase64(encrypted, password));
        }
    }

输出

Java

PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
leHBoUoB54bd9JEa9s9INohjVjmb2RZqVzrz2uYEstg=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
wC6o7cUqZn9KS88L11OuNR2lGDcJ6zBrK1etJEpMHEg=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target> java -cp .\TestAes-1.0-SNAPSHOT.jar com.mycompany.testaes.Program
gfM1uVf2a3x6Q/N0XhpDI4svUZx4kTmcl0wkjJfNQrw=
plain text
PS C:\Users\Megam\OneDrive\Documentos\NetBeansProjects\TestAes\target>

点网

PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
4GTqXhjkh0tXNI6Q4hShSdPPrKcWVEqA5LRBn6fBCH8=
plain text

PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
aYY1sxre9KfLqkA1XtvN4IwGau6mYInmuvkopFXuKQA=
plain text

PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0> .\ConsoleAppCs.exe
7lesPYAHQxdiCN4Cv5yWyWJlf5pqIukznZzpZTOOFeg=
plain text

PS C:\Users\Megam\source\repos\ConsoleApplication1\ConsoleAppCs\bin\Debug\net5.0>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-14
    • 2014-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多