Swift 使用 Java 的 AES 加密
Swift AES encryption with Java
我在 Swift 上的 AES GCM 加密有问题
我们在Java上有应用程序,加密没问题,服务器可以读取和处理数据,但我的结果服务器无法读取
我们有 2 个不同的结果。
起初我尝试使用加密 CBC 和 ECB,但他们告诉我应该使用 GCM。
如果有人明白我做错了什么,请帮助我
Java代码:
final String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ==";
static Cipher cipher=null;
SecretKeySpec new_key=null;
Key kateKey=null;
public void onCreate() {
super.onCreate();
handler = new Handler();
if (doCryptoAes) {
new_key = new SecretKeySpec(airSecretKey.getBytes(), "AES");
kateKey = (Key) new SecretKeySpec(airSecretKey.getBytes(), "AES");
}
}
void generateCliper(){
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding"); ///", "BC
} catch (NoSuchAlgorithmException e) {
Log.e("AES 1", e.toString());
} catch (NoSuchPaddingException e) {
Log.e("AES 2", e.toString());
} /*catch (NoSuchProviderException e) {
Log.e("AES 3", e.toString());
}*/
}
protected String encryptAir(String testText) {
byte[] encodedBytes = null;
String s_encode_result = "";
try {
byte[] iv = new byte[12];
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
if (cipher==null){
generateCliper();
}
cipher.init(Cipher.ENCRYPT_MODE, kateKey, ivParameterSpec); //new_key //
encodedBytes = cipher.doFinal(testText.getBytes());
for (int i=0;i<encodedBytes.length; i++){
s_encode_result+=getEncodeHex(encodedBytes[i]);//+" ";
}
} catch (Exception e) {
Log.e(e.toString());
}
return "<BJSN>"+s_encode_result+"</BJSN>";
}
protected String decryptAir(String encodedText) {
if (encodedText.length()<20) return "";
byte[] encryptedTextByte = getConvAES(encodedText);
//Base64.decode(encodedText, Base64.DEFAULT);
byte[] iv = new byte[12];
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
try {
cipher.init(Cipher.DECRYPT_MODE, kateKey, ivParameterSpec);
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] decryptedByte = new byte[0];
try {
decryptedByte = cipher.doFinal(encryptedTextByte);
} catch (BadPaddingException e) {
Log.e("AES 1", e.toString());
} catch (IllegalBlockSizeException e) {
Log.e("AES 2", e.toString());
}
String decryptedText = new String(decryptedByte);
// MainActivity.toast_str="Decrypted: "+decryptedText;
return decryptedText;
}
byte[] getConvAES(String textAesStr) {
int i_len = (textAesStr.length()-13)/2;
byte[] aesNonce= new byte[i_len];
if (textAesStr.indexOf( "<BJSN>") == 0 &&
textAesStr.indexOf( "</BJSN>") > 0 && i_len > 0) {
for (int i = 3; i < i_len+3; i++) {
String s_hex = "";
s_hex+=textAesStr.charAt(i*2);
s_hex+=textAesStr.charAt(i*2+1);
int i_binary=0;
try {
i_binary=Integer.parseInt(s_hex, 16);
aesNonce[i-3]=(byte) i_binary;
} catch (Exception e) {
aesNonce[i-3]=0;
}
}
}
return aesNonce;
}
我的Swift代码:
import CryptoKit
let key = SymmetricKey(size: .bits192)
let plain = "BSD AIR"
func cryptoDemoCombinedData() {
let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!)
let tag = Data(base64Encoded: "Wk+Uzyyn8991w/2V5OIqiQ==")!
// Encrypt
let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce, authenticating: tag)
// Decrypt
let sealedBoxRestored = try! AES.GCM.SealedBox(combined: sealedBox.combined!)
let decrypted = try! AES.GCM.open(sealedBoxRestored, using: key, authenticating: tag)
print("Crypto Demo II\n••••••••••••••••••••••••••••••••••••••••••••••••••\n")
print("Combined:\n\(sealedBox.combined!.base64EncodedString())\n")
print("Cipher:\n\(sealedBox.ciphertext.base64EncodedString())\n")
print("Nonce:\n\(nonce.withUnsafeBytes { Data(Array([=13=])).base64EncodedString() })\n")
print("Tag:\n\(tag.base64EncodedString())\n")
print("Decrypted:\n\(String(data: decrypted, encoding: .utf8)!)\n")
}
这不是加密的工作原理。每次加密相同的明文,都必须得到不同的输出。使用 GCM,这是通过每次使用唯一的随机 IV 来实现的 - 一个随机数(n使用的数字 一次)。
GCM has its own requirements on IV, namely that an IV shall never be reused, and that is important.
String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ=="; // this key is now public so you cannot use it
SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(airSecretKey), "AES");
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[12];
secureRandom.nextBytes(iv);
AlgorithmParameters params = new GCMParameterSpec(128, iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, params, secureRandom);
cipher.updateAAD(...); // if used
byte[] encrypted = cipher.doFinal(plaintext);
Swift 版本应该执行相同的操作。 Java 生成标签并将其附加到密文中。在 Swift 中,您似乎必须手动处理它。
我在 Swift 上的 AES GCM 加密有问题 我们在Java上有应用程序,加密没问题,服务器可以读取和处理数据,但我的结果服务器无法读取 我们有 2 个不同的结果。 起初我尝试使用加密 CBC 和 ECB,但他们告诉我应该使用 GCM。 如果有人明白我做错了什么,请帮助我
Java代码:
final String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ==";
static Cipher cipher=null;
SecretKeySpec new_key=null;
Key kateKey=null;
public void onCreate() {
super.onCreate();
handler = new Handler();
if (doCryptoAes) {
new_key = new SecretKeySpec(airSecretKey.getBytes(), "AES");
kateKey = (Key) new SecretKeySpec(airSecretKey.getBytes(), "AES");
}
}
void generateCliper(){
try {
cipher = Cipher.getInstance("AES/GCM/NoPadding"); ///", "BC
} catch (NoSuchAlgorithmException e) {
Log.e("AES 1", e.toString());
} catch (NoSuchPaddingException e) {
Log.e("AES 2", e.toString());
} /*catch (NoSuchProviderException e) {
Log.e("AES 3", e.toString());
}*/
}
protected String encryptAir(String testText) {
byte[] encodedBytes = null;
String s_encode_result = "";
try {
byte[] iv = new byte[12];
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
if (cipher==null){
generateCliper();
}
cipher.init(Cipher.ENCRYPT_MODE, kateKey, ivParameterSpec); //new_key //
encodedBytes = cipher.doFinal(testText.getBytes());
for (int i=0;i<encodedBytes.length; i++){
s_encode_result+=getEncodeHex(encodedBytes[i]);//+" ";
}
} catch (Exception e) {
Log.e(e.toString());
}
return "<BJSN>"+s_encode_result+"</BJSN>";
}
protected String decryptAir(String encodedText) {
if (encodedText.length()<20) return "";
byte[] encryptedTextByte = getConvAES(encodedText);
//Base64.decode(encodedText, Base64.DEFAULT);
byte[] iv = new byte[12];
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
try {
cipher.init(Cipher.DECRYPT_MODE, kateKey, ivParameterSpec);
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] decryptedByte = new byte[0];
try {
decryptedByte = cipher.doFinal(encryptedTextByte);
} catch (BadPaddingException e) {
Log.e("AES 1", e.toString());
} catch (IllegalBlockSizeException e) {
Log.e("AES 2", e.toString());
}
String decryptedText = new String(decryptedByte);
// MainActivity.toast_str="Decrypted: "+decryptedText;
return decryptedText;
}
byte[] getConvAES(String textAesStr) {
int i_len = (textAesStr.length()-13)/2;
byte[] aesNonce= new byte[i_len];
if (textAesStr.indexOf( "<BJSN>") == 0 &&
textAesStr.indexOf( "</BJSN>") > 0 && i_len > 0) {
for (int i = 3; i < i_len+3; i++) {
String s_hex = "";
s_hex+=textAesStr.charAt(i*2);
s_hex+=textAesStr.charAt(i*2+1);
int i_binary=0;
try {
i_binary=Integer.parseInt(s_hex, 16);
aesNonce[i-3]=(byte) i_binary;
} catch (Exception e) {
aesNonce[i-3]=0;
}
}
}
return aesNonce;
}
我的Swift代码:
import CryptoKit
let key = SymmetricKey(size: .bits192)
let plain = "BSD AIR"
func cryptoDemoCombinedData() {
let nonce = try! AES.GCM.Nonce(data: Data(base64Encoded: "fv1nixTVoYpSvpdA")!)
let tag = Data(base64Encoded: "Wk+Uzyyn8991w/2V5OIqiQ==")!
// Encrypt
let sealedBox = try! AES.GCM.seal(plain.data(using: .utf8)!, using: key, nonce: nonce, authenticating: tag)
// Decrypt
let sealedBoxRestored = try! AES.GCM.SealedBox(combined: sealedBox.combined!)
let decrypted = try! AES.GCM.open(sealedBoxRestored, using: key, authenticating: tag)
print("Crypto Demo II\n••••••••••••••••••••••••••••••••••••••••••••••••••\n")
print("Combined:\n\(sealedBox.combined!.base64EncodedString())\n")
print("Cipher:\n\(sealedBox.ciphertext.base64EncodedString())\n")
print("Nonce:\n\(nonce.withUnsafeBytes { Data(Array([=13=])).base64EncodedString() })\n")
print("Tag:\n\(tag.base64EncodedString())\n")
print("Decrypted:\n\(String(data: decrypted, encoding: .utf8)!)\n")
}
这不是加密的工作原理。每次加密相同的明文,都必须得到不同的输出。使用 GCM,这是通过每次使用唯一的随机 IV 来实现的 - 一个随机数(n使用的数字 一次)。
GCM has its own requirements on IV, namely that an IV shall never be reused, and that is important.
String airSecretKey = "Wk+Uzyyn8991w/2V5OIqiQ=="; // this key is now public so you cannot use it
SecretKey key = new SecretKeySpec(Base64.getDecoder().decode(airSecretKey), "AES");
SecureRandom secureRandom = new SecureRandom();
byte[] iv = new byte[12];
secureRandom.nextBytes(iv);
AlgorithmParameters params = new GCMParameterSpec(128, iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key, params, secureRandom);
cipher.updateAAD(...); // if used
byte[] encrypted = cipher.doFinal(plaintext);
Swift 版本应该执行相同的操作。 Java 生成标签并将其附加到密文中。在 Swift 中,您似乎必须手动处理它。