我试图在C#中模拟一个java加密例程,因为端点是基于java的,并且将解密C#生成的值。
我尝试过使用AesCryptoServiceProvider和AesManaged来实现不同的实现,这些实现来自于web中的几个例子,但我仍然无法让java端点成功地解密值,这是{"message":"AUTHENTICATION_ERROR: Error while decrypting the cipher.","status":"Error"}的错误。
使用postman,我能够调用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();
}发布于 2020-10-23 09:38:05
为了测试任何C#加密,我在您的Java代码中添加了一个解密方法,并成功地运行了一个完整的循环(加密和解密)。
对于C#部分,我懒得检查您的代码(正如@Topaco所做的那样),并且使用我自己的代码和您的凭据来获得一个输出,您可以将输出呈现给Java方法。
让我们从一个更长的安全警告开始:代码使用静态初始化向量和静态salt,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);
}
}https://stackoverflow.com/questions/64493398
复制相似问题