繁体   English   中英

C# AES 加密到 java 8 解密

[英]C# AES encrypt to java 8 decrypt

我试图在 C# 中模拟 Java 加密例程,因为端点是基于 Java 的,并且将解密 C# 生成的值。

我已经尝试了使用AesCryptoServiceProviderAesManaged从 SO 和网络上的几个示例中找到的不同实现,但我仍然无法让 java 端点成功解密该值,它出现错误{"message":"AUTHENTICATION_ERROR: Error while decrypting the cipher.","status":"Error"}

使用邮递员,我能够调用 java 端点并使用下面发布的 java 代码生成的加密文本检索文档,因此该部分得到了肯定的验证。

端点使用标头值解密文本并验证内容,以下是相关代码片段:

java加密

  private static Cipher generateCipher(int mode, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
    byte[] saltBytes = salt.getBytes("UTF-8"); byte[]ivBytes = iv.getBytes("UTF-8");
    // Derive the key
    SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
    PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, iterations, keySize);

    SecretKey secretKey = factory.generateSecret(spec);
    SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
    //encrypt the message
    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(mode, secret, new IvParameterSpec(ivBytes));
    return cipher;
  }

  public static String AES_encrypt(String plainText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
    Cipher cipher = generateCipher(Cipher.ENCRYPT_MODE, password, salt, iv, iterations, keySize);
    byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
    Base64.Encoder encoder = Base64.getEncoder();
    return encoder.encodeToString(encryptedTextBytes);
  }

标题

  interface_name: interfaceName  
  strength: 256  
  salt: salt_sixteen1234  
  iterate: 100  
  iv: sixteen_value_12  
  ciphertext: ECtKO7VluxCPFS/D8LVsb2bOQjhViIZm+O3zfMqSwJOLLTpDL4xdgwmIWr+41n5j  

C# 加密

  ...
   using (var csp = new AesCryptoServiceProvider())
   {
          ICryptoTransform e = GetCryptoTransform(csp, true, key, salt, iv);
          byte[] inputBuffer = Encoding.UTF8.GetBytes(plainText);
          byte[] output = e.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
         string encrypted = Convert.ToBase64String(output);

        return encrypted;
   }
  ...

   private static ICryptoTransform GetCryptoTransform(AesCryptoServiceProvider csp, bool encrypting, string password, string salt, string iv, int iterations)
   {
        csp.Mode = CipherMode.CBC;
        csp.Padding = PaddingMode.PKCS7;
        var spec = new Rfc2898DeriveBytes(Encoding.UTF8.GetBytes(password), Encoding.UTF8.GetBytes(salt), iterations);
        byte[] key = spec.GetBytes(16);

        csp.IV = Encoding.UTF8.GetBytes(iv);
        csp.Key = key;
        if (encrypting)
        {
            return csp.CreateEncryptor();
        }
        return csp.CreateDecryptor();
   }

为了测试任何 C# 加密,我在您的 Java 代码中添加了一个解密方法并成功运行了一整轮(加密和解密)。

对于 C# 部分,我懒得检查您的代码(正如@Topaco 所做的那样)并使用我自己的代码和您的凭据来获取您可以提供给 Java 解密方法的输出。

让我们从更长的安全警告开始:代码使用静态初始化向量和静态盐,并且 PBKDF2 密钥派生的迭代计数太低(应至少使用 10.000) 这些代码没有任何异常处理,仅用于教育目的。

运行 C# 代码会给出一个简短的输出:

AES CBC 256 string encryption with PBKDF2 SHA1 key derivation
plaintext:      The quick brown fox jumps over the lazy dog
ciphertext:     5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4

将密文呈现给 Java 解密将给出以下输出:

C# AES encrypt to java 8 decrypt
plaintext: The quick brown fox jumps over the lazy dog
ciphertext: 5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4
decryptedtext: The quick brown fox jumps over the lazy dog

decryption of a ciphertext from C#
ciphertextFromCsharp: 5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4
decryptedtextFromCsharp: The quick brown fox jumps over the lazy dog

这两个代码都可用于现场自测(Java: https : //repl.it/@javacrypto/JavaAes256EncryptionWithPBKDF2SHA1keyderivation,C#https : //repl.it/@javacrypto/CsharpAes256Pbkdf2Encryption#main.cs )。

C#-代码:

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

public class Program {
    public static void Main() {
        Console.WriteLine("AES CBC 256 string encryption with PBKDF2 SHA1 key derivation");
        // credentials
    string plaintext = "The quick brown fox jumps over the lazy dog";
        string password = "myPassword";
    string saltString = "salt_sixteen1234";
    var iterationsCount = 100;
    string ivString = "sixteen_value_12";

    Encoding enc = Encoding.UTF8;
        byte[] saltBytes = enc.GetBytes(saltString);
    byte[] iv = enc.GetBytes(ivString);
    byte[] key;

        try {
      // pbkdf2 sha1 key derivation
      using (var pbkdf2 = new Rfc2898DeriveBytes(
            password,
            saltBytes,
            iterationsCount,
            HashAlgorithmName.SHA1))
          {
            key = pbkdf2.GetBytes(32);
          }
            Console.WriteLine("plaintext:      {0}", plaintext);
            string ciphertext = encrypt(key, iv, plaintext);
            Console.WriteLine("ciphertext:     {0}", ciphertext);
        }
        catch(Exception e) {
            Console.WriteLine("Error: {0}", e.Message);
        }
    }

    static string encrypt(byte[] key, byte[] IV, string data) {
        byte[] encrypted;
        using(Aes aesAlg = Aes.Create()) {
            aesAlg.Key = key;
            aesAlg.IV = IV;
            aesAlg.Mode = CipherMode.CBC;
            var encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
            // create the streams used for encryption.
            using(var msEncrypt = new MemoryStream()) {
                using(var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
                    using(var swEncrypt = new StreamWriter(csEncrypt)) {
                        //Write all data to the stream.
                        swEncrypt.Write(data);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        return Convert.ToBase64String(encrypted);
    }
}

Java代码:

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println("C# AES encrypt to java 8 decrypt");

        String plaintext = "The quick brown fox jumps over the lazy dog";
        String password = "myPassword";
        String iv = "sixteen_value_12";
        String salt = "salt_sixteen1234";
        int iterations = 100;
        int keySize = 256;
        System.out.println("plaintext: " + plaintext);
        String ciphertext = AES_encrypt(plaintext, password, salt, iv, iterations, keySize);
        System.out.println("ciphertext: " + ciphertext);
        String decryptedtext = AES_decrypt(ciphertext, password, salt, iv, iterations, keySize);
        System.out.println("decryptedtext: " + decryptedtext);
        System.out.println("\ndecryption of a ciphertext from C#");
        String ciphertextFromCsharp = "5HMLSQKEgG+RADgPmf5Eyw0F/GG9sXFuWiHeuZxgpmJP+UoH4MZlvnQDrgnofQy4";
        System.out.println("ciphertextFromCsharp: " + ciphertextFromCsharp);
        String decryptedtextFromCsharp = AES_decrypt(ciphertextFromCsharp, password, salt, iv, iterations, keySize);
        System.out.println("decryptedtextFromCsharp: " + decryptedtextFromCsharp);
   }

    private static Cipher generateCipher(int mode, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
        byte[] saltBytes = salt.getBytes("UTF-8"); byte[]ivBytes = iv.getBytes("UTF-8");
        // Derive the key
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
        PBEKeySpec spec = new PBEKeySpec(password.toCharArray(), saltBytes, iterations, keySize);
        SecretKey secretKey = factory.generateSecret(spec);
        SecretKeySpec secret = new SecretKeySpec(secretKey.getEncoded(), "AES");
        //encrypt the message
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(mode, secret, new IvParameterSpec(ivBytes));
        return cipher;
    }

    public static String AES_encrypt(String plainText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
        Cipher cipher = generateCipher(Cipher.ENCRYPT_MODE, password, salt, iv, iterations, keySize);
        byte[] encryptedTextBytes = cipher.doFinal(plainText.getBytes("UTF-8"));
        Base64.Encoder encoder = Base64.getEncoder();
        return encoder.encodeToString(encryptedTextBytes);
    }

    public static String AES_decrypt(String cipherText, String password, String salt, String iv, Integer iterations, Integer keySize) throws Exception {
        Base64.Decoder decoder = Base64.getDecoder();
        Cipher cipher = generateCipher(Cipher.DECRYPT_MODE, password, salt, iv, iterations, keySize);
        return new String(cipher.doFinal(decoder.decode(cipherText)), StandardCharsets.UTF_8);
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM