iOS Java 中的 CryptoKit

iOS CryptoKit in Java

我正在寻找 settings/parameters 的 CryptoKit,它将允许我在 iOS 应用程序和 Java 应用程序之间共享数据。流程如下所示: - 使用 CryptoKit 使用固定密钥和随机初始化向量 (IV) 加密文本。 - 在 Java 应用程序中使用标准 javax 库使用相同的固定密钥执行解密。随机 IV 将与应用程序一起 transported/shared 以及加密文本。

同样,也需要相反的方法,其中使用 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 创建一个密封盒,但是,CryptoKit API 创建一个密封盒需要以下内容:

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([=16=])).base64EncodedString()
}

如果我将此 IV 和 CipherText 与密钥(“12345”字符串的 SHA265 散列)一起传递给 Java 解密函数,我会收到 TAG 不匹配错误。

这是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()

将此数据写入文件(我正在使用 google API 将此数据写入 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);