使用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散列函数具有反转散列真的不可行的优点。

Interesting Posts