使用ECB的iOS 3DES会返回一半正确的数据
使用3DES + ECBalgorithmencryption密码时出现问题。 这里是我使用的代码:
class func encryptPassword(pass: String) -> String { let keyString = "123456789012345678901234" let keyData: NSData! = (keyString as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! let keyBytes = UnsafePointer<UInt8>(keyData.bytes) let data: NSData! = (pass as NSString).dataUsingEncoding(NSUTF8StringEncoding) as NSData! let dataLength = UInt(data.length) let dataBytes = UnsafePointer<UInt8>(data.bytes) var cryptData = NSMutableData(length: Int(dataLength) + kCCBlockSize3DES)! var cryptPointer = UnsafeMutablePointer<UInt8>(cryptData.mutableBytes) var cryptLength = size_t(cryptData.length) let keyLength = size_t(kCCKeySize3DES) let operation: CCOperation = UInt32(kCCEncrypt) let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES) let options: CCOptions = UInt32(kCCOptionECBMode | kCCOptionPKCS7Padding) var numBytesEncrypted :UInt = 0 var cryptStatus = CCCrypt(operation, algoritm, options, keyBytes, keyLength, nil, dataBytes, dataLength, cryptPointer, cryptLength, &numBytesEncrypted) var base64cryptString = "" if UInt32(cryptStatus) == UInt32(kCCSuccess) { let x: UInt = numBytesEncrypted cryptData.length = Int(numBytesEncrypted) println("cryptLength = \(numBytesEncrypted),\n cryptData = \(cryptData)\n") base64cryptString = cryptData.base64EncodedStringWithOptions(nil) } else { println("Error: \(cryptStatus)") } return base64cryptString } }
这有效,但validation失败。 我使用在线encryption器,如http://www.tools4noobs.com/online_tools/encrypt/selectTripleDES和ECB
代码
let encrypted = Utils.encryptPassword("123456789")
控制台显示
cryptData = <1dd50935 b702084b d164ce3e 9427c493>
在线转换器显示
1dd50935b702084bf9fbee67c9643874
即前8个字节是正确的,但最后一个 – 不是。 这怎么可能? 代码有什么问题?
===========编辑============
正如@Artjom所说 – 应该有零值添加到完整的块。
这个代码在开始时添加了零值:
// Trim password var password = pass.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) // Adding null padding let count = 8 - countElements(password) % 8 for i in 1...count { password += "\0" }
然后使用“密码”var而不是传入“传递”来生成“数据”
同时也删除填充选项
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
谢谢
这可能是一个不同的填充正在使用。 DES的块大小为8个字节。 所以第一块是12345678
,第二块是9
。 由于DES是分组密码,明文必须填充到下一个块大小。
在线工具可能使用零填充或不填充,这基本上意味着该块的其他字节被设置为0x00。 另一方面,您在代码中使用PKCS#7填充。 删除PKCS#7标志,以查看输出是否匹配。
如果库不提供它,你将不得不自己做零填充。 用\0
字节填充密码,直到在encryption期间达到块大小的倍数,并在解密期间除去那些零字节。
不build议使用没有填充的encryption。
而且,密码通常不是经过encryption的,而是用随机盐和多次迭代进行哈希处理。 当你的用户数据库变得“丢失”时,你不希望发现它的人能够轻易地反转密码并以任何用户身份login(假设encryption密钥也很容易“失去”)。 另一方面,使用强大的encryption散列函数具有反转散列真的不可行的优点。