AES加密与java和WP7
本文关键字:WP7 java 加密 AES | 更新日期: 2023-09-27 18:05:47
我们在Java中有AES-128加密的代码,我们希望在WP7中有一些等效的代码。
然而,我们遇到了一个问题:两种实现产生不同的加密文本
下面是我们使用的代码: <<p> Java代码/strong>package com.emap.services;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESEcrypt1 {
static byte[] ibv = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
public String encryptData() {
String message = "Testing AES encryption-decryption amlgorithm for WP7.";
String encryptedStr = "";
try {
SecretKeySpec skeySpec = new SecretKeySpec("Passkey".getBytes(), "AES");
IvParameterSpec iv = new IvParameterSpec(ibv);
// Instantiate the cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(message.getBytes());
encryptedStr = Base64.encode(encrypted);
} catch (BadPaddingException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (IllegalBlockSizeException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (InvalidAlgorithmParameterException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (InvalidKeyException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (NoSuchAlgorithmException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (NoSuchPaddingException ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
} catch (Exception ex) {
System.out.println("Error: " + ex.getMessage());
encryptedStr = "error";
}
System.out.println("Encrypted: " + encryptedStr);
return encryptedStr;
}
}
<<p> WP7代码/strong> static byte[] ibv = new byte[]{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
public string Encrypt(string dataToEncrypt, string password)
//public string Encrypt(string dataToEncrypt)
{
AesManaged aes = null;
MemoryStream memStream = null;
CryptoStream crStream = null;
try
{
//Generate a Key based on a Password and Salt
//Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, Encoding.UTF8.GetBytes(salt));
Rfc2898DeriveBytes rfc2898 = new Rfc2898DeriveBytes(password, ibv);
aes = new AesManaged();
aes.Key = rfc2898.GetBytes(aes.KeySize / 8);
aes.IV = rfc2898.GetBytes(aes.BlockSize / 8);
memStream = new MemoryStream();
crStream = new CryptoStream(memStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
byte[] data = Encoding.UTF8.GetBytes(dataToEncrypt);
crStream.Write(data, 0, data.Length);
crStream.FlushFinalBlock();
//Return Base 64 String
return Convert.ToBase64String(memStream.ToArray());
}
finally
{
//cleanup
if (crStream != null)
crStream.Close();
if (memStream != null)
memStream.Close();
if (aes != null)
aes.Clear();
}
}
请注意,在Java中,密码指定有三个部分——算法、模式(CBC vs. ECB等)和填充。你必须匹配这三者,而不仅仅是算法。如果WP7不允许您显式指定模式和填充,请找出它们并在Java端进行匹配。
哦,确保键是相同的。从例子中看不出来。
编辑:对于调试填充问题,一个微不足道的键是一个很大的帮助。也就是说,一个使算法发出其明文副本作为密文的密钥。以RSA为例,它的公共指数是1。
看起来不像你在使用相同的键。在Windows Phone 7的实现中,你似乎正确地从密码中获得密钥,而Java代码则不正确地直接使用密码的某些编码。
关于Java中基于密码的加密的一般概述,请参阅我之前的回答。它将向您展示如何派生密钥(根据RFC 2898中的PBKDF2),并描述正确的生成和每个消息初始化向量的交换。
JB Nizet对这篇文章的评论让我更仔细地观察了你是如何使用
ibv
数据的,他是对的:你在两次手术中都没有使用相同的静脉注射。它在Java代码中用作IV,但在Windows代码中,它被用作密钥派生过程的"盐"。这是两个不同的目的,应该使用两个不同的值。
由于ibv
是一个固定值,因此更适合于密钥派生(每个密码应该有一个唯一的salt)。每条消息都应该有一个随机选择的新IV,并与密文一起发送。您可以在上面链接的Java示例中使用ibv
作为salt
。