iOS CryptoKit на Java
Я ищу настройки / параметры CryptoKit, которые позволят мне обмениваться данными между приложением iOS и приложением Java. Последовательность действий будет примерно такой: - Используйте CryptoKit для шифрования текста с использованием фиксированного ключа и случайного вектора инициализации (IV). - В приложении Java используйте стандартные библиотеки javax для выполнения дешифрования с использованием того же фиксированного ключа. Случайный IV будет передан / передан приложению вместе с зашифрованным текстом.
Точно так же требуется обратное, когда текст шифруется с использованием библиотек JavaX с использованием фиксированного ключа и случайного IV. Случайный IV и зашифрованный текст передаются в приложение iOS, где оно должно использовать CryptoKit для его расшифровки.
Ниже приведен код для шифрования и дешифрования на Java.
public static byte[] encrypt(byte[] plaintext, byte[] key, byte[] IV) throws Exception
{
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES_256/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV);
// Initialize Cipher for ENCRYPT_MODE
cipher.init(Cipher.ENCRYPT_MODE, keySpec, gcmParameterSpec);
// Perform Encryption
byte[] cipherText = cipher.doFinal(plaintext);
return cipherText;
}
public static String decrypt(byte[] cipherText, byte[] key, byte[] IV) throws Exception
{
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES_256/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key, "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
// Perform Decryption
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
Команды CryptoKit, как показано ниже:
let mykey = SymmetricKey(data: passhash)
let myiv = try AES.GCM.Nonce()
let mySealedBox = try AES.GCM.seal(source.data(using: .utf8)!, using: mykey, nonce: myiv)
let myNewSealedBox = try AES.GCM.SealedBox(nonce: myiv, ciphertext: mySealedBox.ciphertext, tag: mySealedBox.tag)
let myText = try String(decoding: AES.GCM.open(myNewSealedBox, using: mykey), as: UTF8.self)
Ниже приведены шаги для создания зашифрованного текста на Java:
int GCM_IV_LENGTH = 12;
//Generate Key
MessageDigest md = MessageDigest.getInstance("SHA265");
byte[] key = md.digest("pass".getBytes(StandardCharsets.UTF_8));
// Generate IV
SecureRandom sr = new SecureRandom(pass.getBytes(StandardCharsets.UTF_8));
byte[] IV = new byte[GCM_IV_LENGTH];
sr.nextBytes(IV);
//Encrypt
byte[] cipherText = encrypt("Text to encrypt".getBytes(), key, IV);
//Base64 Encoded CipherText
String cipherTextBase64 = Base64.getEncoder().encodeToString(cipherText);
Чтобы расшифровать это в SWIFT CryptoKit, мне сначала нужно создать запечатанный блок с этим CipherText, однако API CryptoKit для создания запечатанного блока требует следующего:
- Nonce / IV (доступно выше)
- CipherText (доступно выше)
- Тег (НЕТ ИДЕИ ОТ ГДЕ ПОЛУЧИТЬ ЭТО????)
AES.GCM.SealedBox(nonce: , ciphertext: , tag: )
Другой способ - сначала зашифровать данные в CryptoKit.
let mykey = SymmetricKey(data: SHA256.hash(data: "12345".data(using: .utf8)!))
let myiv = AES.GCM.Nonce()
let mySealedBox = try AES.GCM.seal("Text to encrypt".data(using: .utf8)!, using: mykey, nonce: myiv)
let cipherText = mySealedBox.cipherText.base64EncodedString()
let iv = myiv.withUnsafeBytes{
return Data(Array($0)).base64EncodedString()
}
Если я передаю этот IV и CipherText функции Java Decrypt вместе с ключом (хэш SHA265 строки "12345"), я получаю ошибку несоответствия TAG.
1 ответ
Это последний набор кода в SWIFT:
let pass = “Password”
let data = “Text to encrypt”.data(using: .utf8)!
let key = SymmetricKey(data: SHA256.hash(data: pass.datat(using: .utf8)!))
let iv = AES.GCM.Nonce()
let mySealedBox = try AES.GCM.seal(data, using: key, nonce: iv)
dataToShare = mySealedBox.combined?.base64EncodedData()
Запишите эти данные в файл (я использую API Google для записи этих данных в файл на диске Google)
Прочтите эти данные из файла в java и передайте их функциям, как определено в вопросе, используя следующий код:
byte[] iv = Base64.getDecoder().decode(text.substring(0,16));
cipher[] = Base64.getDecoder().decode(text.substring(16));
byte[] key = md.digest(pass.getBytes(StandardCharsets.UTF_8));
String plainText = decrypt(cipher, key, iv);