ios - 解密 AES/GCM/PKCS5Padding iOS Swift

标签 ios swift aes-gcm commoncrypto apple-cryptokit

我正在尝试使用 AES 解密来解密 Base64Encoded String 消息。
加密消息(Base64Encoded 字符串):
tNC6umcfBS/gelbo2VJF3i4LAhUKMp4oDHWN5KyYUTWeJIQKKYx6oAcQnGncIrPJNC1tUYMKV4kJQj3q9voIorxc1n7FmRFvDXeRgWGNcGYO66dH3VjoEgF0oxZOpfzwSZKSv3Jm7Q==
密码(字符串) = "一些密码字符串"
解密消息的步骤:

  • 数据必须从 base 64 解码为普通字符串。
  • 从输入中提取 IV 和加密文本
  • 使用 IV 和相同的密码生成用于加密文本的 key 。 key 生成应遵循与以下相同的步骤。
  • 生成 PBE key (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.
    
  • 使用生成的 key 和 IV,以与以下完全相同的方式初始化密码
  • 此 key 初始化密码对象
            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.
    
  • 生成密码以从加密文本中获取消息。

  • 下面是用于解密输入消息的 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);
                }
            }
    } 
    
    我在 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)
           }
    
    
    用法:
     guard let encryptedData = Data(base64Encoded: input) else{
      return nil
    }
    let decryptData = aesDecrypt3(encryptedData: encryptedData)
    let decryptedMessage = String(data: decryptData, encoding: .utf8) ?? "Unable to Decrypt"
    
    任何线索将不胜感激,我想知道在尝试快速转换时是否缺少一些配置或数据转换。

    最佳答案

    我能够使用“CryptoSwift”框架解密输入,想知道我们是否可以使用苹果 iOS 来解决这个问题通用加密 框架。
    任何使用“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
        }
    

    关于ios - 解密 AES/GCM/PKCS5Padding iOS Swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62586164/

    相关文章:

    具有自定义类类型的 Swift CoreData 保存属性

    java - 使用 Java-8 AES/GCM 验证/加密部分数据 block

    iphone - 如何以编程方式使 UIToolbar 覆盖?

    android - 如何在 Xamarin.Forms 中获取/检测屏幕大小?

    ios - "Swift is not supported for static libraries"测试 cocoapod 时

    ios - 如何从充满搜索 Controller 结果的表格中进行 Segue

    java - 在 Android 中使用 AES/GCM/NoPadding 加密的消息解密时出错

    安卓 : AES Encryption & Decryption using GCM mode in android?

    ios - 动态更改动画 IOS 中的图像

    ios - xcode 5 UITableView 总是填满屏幕的整个长度