iOS CryptoKit in Java

自古美人都是妖i 提交于 2020-02-28 09:43:06

问题


I am looking for settings/parameters of CryptoKit which will allow me to share data between iOS App and a Java Application. The flow would be something like below: - Use CryptoKit to encrypt a text using a fixed key and random initialization vector (IV). - In the Java application use standard javax libraries to perform the decryption using the same fixed key. The random IV will be transported/shared with the application along with the encrypted text.

Similarly, the reverse is also required, where text is encrypted using JavaX libraries using a fixed key and random IV. The random IV and encrypted text is shared with the iOS app where it should use CryptoKit to decrypt it.

Below is the code for Encrypt and Decrypt in 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);
}

The CryptoKit commands as below:

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)

Below are the steps to generate an encrypted text in 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);

To Decrypt this in SWIFT CryptoKit, I first need to create a sealed box with this CipherText however, the CryptoKit API to create a sealed box requires the following:

  • Nonce/IV (Available above)
  • CipherText (Available above)
  • Tag (NO IDEA FROM WHERE TO GET THIS????)
AES.GCM.SealedBox(nonce: , ciphertext: , tag: )

The other way, lets first encrypt data in 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()
}

If i pass this IV and CipherText to Java Decrypt function along with key (SHA265 hash of "12345" string), i get a TAG mismatch error.


回答1:


This is the final set of code in 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()

Write this data to a file (I am using google APIs to write this data to a file on google drive)

Read this data from the file in java and pass it to the functions as defined in the question using the below code:

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);



回答2:


I am trying to do exactly same but encyrpting in android and decrypting on iOS,i get the key and encrypted string and I am trying to open it using

    let sealedBoxToOpen = try! AES.GCM.SealedBox(combined: decryptToData)
if let decryptedData = try? AES.GCM.open(sealedBoxToOpen, using: key)

It throws an error CryptoKitError.authenticationFailure.There is a tag value used in java cipherEnc.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(rawEncryptionKey, "AES"), new GCMParameterSpec(TAG_LENGTH_BIT, iv))

How do I decrypt in iOS with encryption in android



来源:https://stackoverflow.com/questions/59577317/ios-cryptokit-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!