简体   繁体   English

解密AES/GCM/PKCS5Padding iOS Swift

[英]Decryption AES/GCM/PKCS5Padding iOS Swift

I am trying to decrypt a Base64Encoded String message with AES decryption.我正在尝试使用 AES 解密来解密 Base64Encoded String 消息。

Encrypted Message (Base64Encoded String): tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==加密消息(Base64Encoded 字符串): tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q=

Password (String) = "SOMEPASSWORDSTRING"密码(字符串) =“SOMEPASSWORDSTRING”

Steps to Decrypt the Message:解密消息的步骤:

  1. The data must be decoded from base 64 to normal string.数据必须从 base 64 解码为普通字符串。

  2. Extract the IV and the encrypted text from input从输入中提取 IV 和加密文本

  3. Use IV and the same passphrase to generate the key that was used to encrypt the text.使用 IV 和相同的密码生成用于加密文本的密钥。 The key generation should follow the same steps as below.密钥生成应遵循与以下相同的步骤。

  4. A PBE Secret Key is generated (256 bits)生成 PBE 密钥(256 位)

     a. Specs created with passphrase and IV as salt, 62233 as iteration count b. Used PBKDF2WithHmacSHA256 to generate a secret factory because it's appropriate for turning passwords into keys. c. This key is further encoded and converted to another key with AES encryption.
  5. With the generated key and IV, initialize the cipher in the exact same way as below使用生成的密钥和 IV,以与以下完全相同的方式初始化密码

  6. This key initializes the cipher object此密钥初始化密码 object

     a. Used AES in GCM, GCM specs are prepared using tag size of 128 bits and the IV b. Cipher object is initialized using AES/GCM/PKCS5Padding. c. Based on operational mode the cipher is initialized with op mode(encryption), secret key and GCM params.
  7. Generate the cipher to get the message from the encrypted text.生成密码以从加密文本中获取消息。

Below is the JAVA Code that is working to decrypt the input message下面是用于解密输入消息的 JAVA 代码

public class Decryption {
    private static final String KEY_GENERATING_ALGO = "PBKDF2WithHmacSHA256";
      private static final String ENCRYPTION = "AES";
      private static final String TRANSFORMATION_ALGORITHM= "AES/GCM/PKCS5Padding";
       
      private static final int KEY_SIZE_BITS = 256;
      private static final int TAG_SIZE_BITS = 128;
      private static final int ITERATION_COUNT  = 62233;
      
    // Use following sample data to test the decryption-
//tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIOrxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==
      
      // This key has is base 64 encoded with IV prepended with encrypted text
      public Cipher initCipher(int encryptMode, String password, byte[] iv) throws InvalidKeySpecException {
            try {
                GCMParameterSpec gcmparams = new GCMParameterSpec(TAG_SIZE_BITS, iv);
                PBEKeySpec pbeKeySpec = new PBEKeySpec(password.toCharArray(), iv, ITERATION_COUNT, KEY_SIZE_BITS);
                SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_GENERATING_ALGO);
                SecretKey pbeKey = factory.generateSecret(pbeKeySpec);
                byte[] keyBytes = pbeKey.getEncoded();
                SecretKey key = new SecretKeySpec(keyBytes, ENCRYPTION);
                Cipher cipher = Cipher.getInstance(TRANSFORMATION_ALGORITHM);
                cipher.init(encryptMode, key, gcmparams);
                return cipher;
            } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException
                    | InvalidAlgorithmParameterException | InvalidKeySpecException ex) {
                throw new AssertionError(ex);
            }
        }
    //Decryption Algo
        public String decrypt(String encrypted){
            byte[] decFeeder = Base64.getDecoder().decode(encrypted);
            String key = "someKey"; // A new key will be provided by APIF through a secure channel
            char[] password = key.toCharArray();
            try {
                byte[] iv = Arrays.copyOfRange(decFeeder, 0, 32);
                byte[] ciphertext = Arrays.copyOfRange(decFeeder, iv.length, decFeeder.length);
                Cipher cipher = initCipher(Cipher.DECRYPT_MODE, key, iv);
                byte[] message = cipher.doFinal(ciphertext);
                String decrypted = new String(message);
                return decrypted;
            } catch (IllegalBlockSizeException | BadPaddingException | InvalidKeySpecException ex) {
                throw new AssertionError(ex);
            }
        }
} 

I used below code in Swift to generate the same as above JAVA code, but I am unable to decrypt the message/cipherText.我在 Swift 中使用了下面的代码来生成与上面的 JAVA 代码相同的代码,但我无法解密消息/密文。

 func aesDecrypt(encryptedData: Data, password: String) -> Data? {
       
        let iv = Array([UInt8](encryptedData)[0 ..< 33])
        let ivData = Data(iv)
        let encryptedCipher = [UInt8](encryptedData)[iv.count ..< encryptedData.count]
        let encryptedCipherData = Data(encryptedCipher)
        
        let passwordKey = createKey(password:Data(password.utf8) , salt: ivData)

        var decryptSuccess = false
        let size = (encryptedCipher.count) + kCCBlockSizeAES128
        var clearTextData = Data.init(count: size)
        
        var numberOfBytesDecrypted : size_t = 0
        let cryptStatus = ivData.withUnsafeBytes {ivBytes in
            clearTextData.withUnsafeMutableBytes {clearTextBytes in
                encryptedCipherData.withUnsafeBytes {encryptedBytes in
                    passwordKey.withUnsafeBytes {keyBytes in
                        CCCrypt(CCOperation(kCCDecrypt),
                                CCAlgorithm(kCCAlgorithmAES128),
                                CCOptions(kCCOptionPKCS7Padding),
                                keyBytes,
                                passwordKey.count,
                                ivBytes,
                                encryptedBytes,
                                (encryptedCipher.count),
                                clearTextBytes,
                                size,
                                &numberOfBytesDecrypted)
                    }
                }
            }
        }
        if cryptStatus == Int32(kCCSuccess)
        {
            clearTextData.count = numberOfBytesDecrypted
            debugPrint(clearTextData)
            decryptSuccess = true
        }
        
        
        return decryptSuccess ? clearTextData : Data.init(count: 0)
    }

    func createKey(password: Data, salt: Data) -> Data? {
           let length = kCCKeySizeAES256
           var status = Int32(0)
           var derivedBytes = [UInt8](repeating: 0, count: length)
           password.withUnsafeBytes { (passwordBytes: UnsafePointer<Int8>!) in
               salt.withUnsafeBytes { (saltBytes: UnsafePointer<UInt8>!) in
                   status = CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2),  // algorithm
                                                 passwordBytes,                // password
                                                 password.count,               // passwordLen
                                                 saltBytes,                    // salt
                                                 salt.count,                   // saltLen
                                                 UInt32(kCCPRFHmacAlgSHA256),  // prf
                                                 UInt32(62233),                // rounds
                                                 &derivedBytes,                // derivedKey
                                                 length)                       // derivedKeyLen
               }
           }
           guard status == 0 else {
              return nil
           }
           return Data(bytes: UnsafePointer<UInt8>(derivedBytes), count: length)
       }

Usage:用法:

 guard let encryptedData = Data(base64Encoded: input) else{
  return nil
}
let decryptData = aesDecrypt3(encryptedData: encryptedData)
let decryptedMessage = String(data: decryptData, encoding: .utf8) ?? "Unable to Decrypt"

Any leads would be greatly appreciated, I wonder if I am missing some configuration or data conversion when trying to convert in swift.任何线索将不胜感激,我想知道在 swift 中尝试转换时是否缺少一些配置或数据转换。

I was able to decrypt the input using "CryptoSwift" framework, was wondering if we can solve the same using the apple iOS CommonCrypto framework.我能够使用“CryptoSwift”框架解密输入,想知道我们是否可以使用苹果 iOS CommonCrypto框架来解决这个问题。

Any leads with using "CommonCrypto" would be greatly appreciated任何使用“CommonCrypto”的线索将不胜感激

 class func decryptCode123(_ cipher:String)-> String{
        
        let key = "SOMEKEY"
        
        var keyBytes: [UInt8] = []
        var codeBytes: [UInt8] = []
        var code = ""

        if let keyData = NSData(base64Encoded:key, options: .ignoreUnknownCharacters) {
            keyBytes = [UInt8](keyData as Data)
        }
        if let codeData = NSData(base64Encoded: cipher, options: .ignoreUnknownCharacters) {
            codeBytes = [UInt8](codeData as Data)
        }

        debugPrint(codeBytes)

        let codeBytescount = [UInt8](codeBytes).count

        let iv = Array([UInt8](codeBytes)[0 ..< 32])
        let cipher = Array([UInt8](codeBytes)[iv.count ..< codeBytescount])
        do{
            let gcm = GCM(iv: iv, mode: .combined)
            let derKey = createKey(password:Data(key.utf8), salt: Data(iv))!
            
            keyBytes = [UInt8](derKey)
            
            let aes = try AES(key: keyBytes, blockMode: gcm, padding: .pkcs5)
            
            print("aes created")
            let decrypted = try aes.decrypt(cipher)
            print("decrypted completed")
            if let decryptedString = String(bytes: decrypted, encoding: .utf8) {
                code = decryptedString
            }
            
            debugPrint(code)

        }catch let error as AES.Error {
            debugPrint(error.localizedDescription)
            return code
        } catch {
            return code
        }
        return code
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM