在swift中使用TripleDes和MD5

我在java代码中有一个使用tripleDes和MD5的算法。 有我的java代码:

private String _encrypt(String message, String secretKey) throws Exception { MessageDigest md = MessageDigest.getInstance("MD5"); byte[] digestOfPassword = md.digest(secretKey.getBytes("utf-8")); byte[] keyBytes = Arrays.copyOf(digestOfPassword, 16); SecretKey key = new SecretKeySpec(keyBytes, "DESede/ECB/PKCS7Padding"); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS7Padding"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] plainTextBytes = message.getBytes("utf-8"); byte[] buf = cipher.doFinal(plainTextBytes); byte [] base64Bytes = Base64.encodeBase64(buf); String base64EncryptedString = new String(base64Bytes); return base64EncryptedString; } 

我想在swift中使用tripleDes和MD5,我将这个java代码转换为swift但是在swift中存在一个问题因为在java中使用16字节而swift使用24字节。 如何解决java和swift编码之间的这种差异? 有我的快速代码:

  func myEncrypt(encryptData:String) -> String?{ let myKeyData : NSData = ("Fanava@Wrapper!1395" as NSString).data(using: String.Encoding.utf8.rawValue)! as NSData let myRawData : NSData = encryptData.data(using: String.Encoding.utf8)! as NSData let mykeydatamd5 = Data(bytes: myKeyData.bytes, count: 24) // this key convert to 24 bytes but does not hash to md5 let mykeydatamd5 = Data(bytes: myKeyData.md5().bytes, count: 24) // this line converted key to md5(), 24byte, but it let buffer_size : size_t = myRawData.length + kCCBlockSize3DES let buffer = UnsafeMutablePointer.allocate(capacity: buffer_size) var num_bytes_encrypted : size_t = 0 let operation: CCOperation = UInt32(kCCEncrypt) let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES) let options: CCOptions = UInt32(kCCOptionECBMode | kCCOptionPKCS7Padding) let keyLength = size_t(kCCKeySize3DES) let Crypto_status: CCCryptorStatus = CCCrypt(operation, algoritm, options, mykeydatamd5.bytes , keyLength, nil, myRawData.bytes, myRawData.count, buffer, buffer_size, &num_bytes_encrypted) if UInt32(Crypto_status) == UInt32(kCCSuccess){ let myResult: NSData = NSData(bytes: buffer, length: num_bytes_encrypted) free(buffer) return myResult.base64EncodedString(options: []) }else{ free(buffer) return nil } } 

以下是可以轻松修改TrippleDES的示例代码:

从子集化的SO文档部分

用于CBC模式下的AES加密,随机IV(Swift 3+)

iv以加密数据为前缀

aesCBC128Encrypt将创建一个随机IV并以加密代码为前缀。
aesCBC128Decrypt将在解密期间使用前缀IV。

输入是数据,键是数据对象。 如果需要的编码forms(如Base64)在调用方法中转换为和/或来自。

密钥长度应为128位(16字节),192位(24字节)或256位(32字节)。 如果使用其他密钥大小,则会引发错误。

PKCS#7填充默认设置。

此示例需要Common Crypto
有必要为项目建立一个桥接头:
#import
Security.framework添加到项目中。

这是示例,而不是生产代码。

 enum AESError: Error { case KeyError((String, Int)) case IVError((String, Int)) case CryptorError((String, Int)) } // The iv is prefixed to the encrypted data func aesCBCEncrypt(data:Data, keyData:Data) throws -> Data { let keyLength = keyData.count let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256] if (validKeyLengths.contains(keyLength) == false) { throw AESError.KeyError(("Invalid key length", keyLength)) } let ivSize = kCCBlockSizeAES128; let cryptLength = size_t(ivSize + data.count + kCCBlockSizeAES128) var cryptData = Data(count:cryptLength) let status = cryptData.withUnsafeMutableBytes {ivBytes in SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivBytes) } if (status != 0) { throw AESError.IVError(("IV generation failed", Int(status))) } var numBytesEncrypted :size_t = 0 let options = CCOptions(kCCOptionPKCS7Padding) let cryptStatus = cryptData.withUnsafeMutableBytes {cryptBytes in data.withUnsafeBytes {dataBytes in keyData.withUnsafeBytes {keyBytes in CCCrypt(CCOperation(kCCEncrypt), CCAlgorithm(kCCAlgorithmAES), options, keyBytes, keyLength, cryptBytes, dataBytes, data.count, cryptBytes+kCCBlockSizeAES128, cryptLength, &numBytesEncrypted) } } } if UInt32(cryptStatus) == UInt32(kCCSuccess) { cryptData.count = numBytesEncrypted + ivSize } else { throw AESError.CryptorError(("Encryption failed", Int(cryptStatus))) } return cryptData; } // The iv is prefixed to the encrypted data func aesCBCDecrypt(data:Data, keyData:Data) throws -> Data? { let keyLength = keyData.count let validKeyLengths = [kCCKeySizeAES128, kCCKeySizeAES192, kCCKeySizeAES256] if (validKeyLengths.contains(keyLength) == false) { throw AESError.KeyError(("Invalid key length", keyLength)) } let ivSize = kCCBlockSizeAES128; let clearLength = size_t(data.count - ivSize) var clearData = Data(count:clearLength) var numBytesDecrypted :size_t = 0 let options = CCOptions(kCCOptionPKCS7Padding) let cryptStatus = clearData.withUnsafeMutableBytes {cryptBytes in data.withUnsafeBytes {dataBytes in keyData.withUnsafeBytes {keyBytes in CCCrypt(CCOperation(kCCDecrypt), CCAlgorithm(kCCAlgorithmAES128), options, keyBytes, keyLength, dataBytes, dataBytes+kCCBlockSizeAES128, clearLength, cryptBytes, clearLength, &numBytesDecrypted) } } } if UInt32(cryptStatus) == UInt32(kCCSuccess) { clearData.count = numBytesDecrypted } else { throw AESError.CryptorError(("Decryption failed", Int(cryptStatus))) } return clearData; } 

用法示例:

 let clearData = "clearData0123456".data(using:String.Encoding.utf8)! let keyData = "keyData890123456".data(using:String.Encoding.utf8)! print("clearData: \(clearData as NSData)") print("keyData: \(keyData as NSData)") var cryptData :Data? do { cryptData = try aesCBCEncrypt(data:clearData, keyData:keyData) print("cryptData: \(cryptData! as NSData)") } catch (let status) { print("Error aesCBCEncrypt: \(status)") } let decryptData :Data? do { let decryptData = try aesCBCDecrypt(data:cryptData!, keyData:keyData) print("decryptData: \(decryptData! as NSData)") } catch (let status) { print("Error aesCBCDecrypt: \(status)") } 

示例输出:

 clearData: <636c6561 72446174 61303132 33343536> keyData: <6b657944 61746138 39303132 33343536> cryptData: <92c57393 f454d959 5a4d158f 6e1cd3e7 77986ee9 b2970f49 2bafcf1a 8ee9d51a bde49c31 d7780256 71837a61 60fa4be0> decryptData: <636c6561 72446174 61303132 33343536> 

笔记:
CBC模式示例代码的一个典型问题是它将随机IV的创建和共享留给用户。 该示例包括IV的生成,加密数据的前缀并在解密期间使用前缀IV。 这使临时用户免于CBC模式所需的细节。

为了安全起见,加密数据也应该具有身份validation,此示例代码不提供为了小,并允许其他平台更好的互操作性。

还缺少密钥的密钥派生密钥,建议使用PBKDF2是文本密码用作密钥材料。

对于强大的生产准备好的多平台加密代码,请参阅RNCryptor 。

如果必须可以为3DES修改此function。

对于PBKDF2加密**基于密码的密钥派生2(Swift 3+)

基于密码的密钥派生既可用于从密码文本中导出加密密钥,也可用于保存密码以进行身份​​validation。

可以使用几种哈希算法,包括SHA1,SHA256,SHA512,这些算法由此示例代码提供。

rounds参数用于使计算变慢,以便攻击者必须在每次尝试上花费大量时间。 典型的延迟值在100ms到500ms之间,如果有不可接受的性能,可以使用更短的值。

此示例需要Common Crypto
有必要为项目建立一个桥接头:
#import
Security.framework添加到项目中。

参数:

 password password String salt salt Data keyByteCount number of key bytes to generate rounds Iteration rounds returns Derived key func pbkdf2SHA1(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA1), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) } func pbkdf2SHA256(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA256), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) } func pbkdf2SHA512(password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { return pbkdf2(hash:CCPBKDFAlgorithm(kCCPRFHmacAlgSHA512), password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) } func pbkdf2(hash :CCPBKDFAlgorithm, password: String, salt: Data, keyByteCount: Int, rounds: Int) -> Data? { let passwordData = password.data(using:String.Encoding.utf8)! var derivedKeyData = Data(repeating:0, count:keyByteCount) let derivationStatus = derivedKeyData.withUnsafeMutableBytes {derivedKeyBytes in salt.withUnsafeBytes { saltBytes in CCKeyDerivationPBKDF( CCPBKDFAlgorithm(kCCPBKDF2), password, passwordData.count, saltBytes, salt.count, hash, UInt32(rounds), derivedKeyBytes, derivedKeyData.count) } } if (derivationStatus != 0) { print("Error: \(derivationStatus)") return nil; } return derivedKeyData } 

用法示例:

 let password = "password" //let salt = "saltData".data(using: String.Encoding.utf8)! let salt = Data(bytes: [0x73, 0x61, 0x6c, 0x74, 0x44, 0x61, 0x74, 0x61]) let keyByteCount = 16 let rounds = 100000 let derivedKey = pbkdf2SHA1(password:password, salt:salt, keyByteCount:keyByteCount, rounds:rounds) print("derivedKey (SHA1): \(derivedKey! as NSData)") 

示例输出:

 derivedKey (SHA1): <6b9d4fa3 0385d128 f6d196ee 3f1d6dbf>