带有ECB的iOS 3DES返回一半正确的数据

时间:2015-02-11 16:43:59

标签: ios swift encryption 3des tripledes

使用3DES + ECB算法加密密码时遇到问题。 这是我使用的代码:

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
    }

}

这有效,但验证失败。我使用了在线加密器,就像http://www.tools4noobs.com/online_tools/encrypt/一样 选择TripleDES和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"
        }

然后使用&#34;密码&#34; var代替传入&#34;传递&#34;生成&#34;数据&#34;

并删除填充选项

let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)

由于

1 个答案:

答案 0 :(得分:3)

可能使用了不同的填充。 DES的块大小为8字节。所以第一个块是12345678,第二个块是9。由于DES是分组密码,因此必须将明文填充到下一个块大小。

在线工具可能使用零填充或无填充,这基本上意味着块的其他字节设置为0x00。另一方面,您在代码中使用PKCS#7填充。删除PKCS#7标志,以查看输出是否匹配。

如果库没有提供,则必须自己进行零填充。使用\0字节填写密码,直到加密期间达到块大小的倍数,并在解密期间删除这些零字节。

不建议在没有填充的情况下使用加密。

此外,密码通常不会加密,而是使用随机盐和多次迭代哈希。当您的用户数据库“丢失”时,您不希望找到它的人能够轻松地反转密码并以任何用户身份登录(假设加密密钥也很容易“丢失”)。另一方面,使用强大的加密哈希函数的优点是反转哈希是不可行的。