iOS 3DES与ECB返回一半正确的数据 [英] iOS 3DES with ECB return half correct data

查看:175
本文介绍了iOS 3DES与ECB返回一半正确的数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用3DES + ECB algo存在密码密码问题。
这是我使用的代码:

  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)

让数据:NSData! =(作为NSString传递).dataUsingEncoding(NSUTF8StringEncoding)作为NSData!
让dataLength = UInt(data.length)
让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)
让操作:CCOperation = UInt32(kCCEncrypt)
let algorithmit: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),\\\
cryptData = \(cryptData)\\\


base64cryptString = cryptData.base64EncodedStringWithOptions(nil)

} else {
println(Error:\(cryptStatus))
}

返回base64cryptString
}

}

这样做,但验证失败。我使用在线加密器,如 http://www.tools4noobs.com/online_tools/encrypt/
选择TripleDES和ECB



代码

  let encrypted = Utils.encryptPassword(123456789)

控制台显示

  cryptData =< 1dd50935 b702084b d164ce3e 9427c493> 

在线转换器显示

  1dd50935b702084bf9fbee67c9643874 

即前8个字节是正确的,但最后一个 - 不是。怎么可能?代码可能有问题?



===========编辑============



@ p @ as @Artjom说 - 应该有零值添加到完成块。



开头的这段代码添加了零值:

  //修剪密码
var password = pass.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

//添加null填充
let count = 8 - countElements(password)%8
对于我在1 ...计数{
密码+ =\0
}

然后使用passwordvar而不是传入pass来生成data



还可以删除填充选项的填充

  let algorithmit:CCAlgorithm = UInt32(kCCAlgorithm3DES)

谢谢

解决方案

这可能是一个不同的填充。 DES的块大小为8字节。所以第一个块是 12345678 ,第二个块是 9 。因为DES是块密码,所以明文必须填充到下一个块大小。



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



如果库不提供,您将不得不自己做零填充。使用 \0 字节填写密码,直到加密期间达到块大小的倍数,并在解密期间删除这些零字节。



不建议使用无加密的加密。



此外,密码通常不加密,而是随机盐和多次迭代。当您的用户数据库丢失时,您不希望发现它的用户数据能够轻松地将密码反转并以任何用户身份登录(假定加密密钥也很容易丢失)。另一方面,使用强密码散列函数的优点在于,颠倒散列是不可行的。


Got a problem with crypting password with 3DES + ECB algo. Here is the code I using:

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
    }

}

That works, but failed verifying. I used online-encryptor for that like http://www.tools4noobs.com/online_tools/encrypt/ Select TripleDES and ECB

For code

let encrypted = Utils.encryptPassword("123456789")

Console shows

cryptData = <1dd50935 b702084b d164ce3e 9427c493>

Online converter shows

1dd50935b702084bf9fbee67c9643874

i.e first 8 bytes are correct but the last ones - not. How could be that? What could be wrong with code?

=========== EDIT ============

As @Artjom said - there is should be zeroes values added to complete block.

This code in start adds zero values:

        // Trim password
        var password = pass.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

        // Adding null padding
        let count = 8 - countElements(password) % 8
        for i in 1...count {
            password += "\0"
        }

Then use "password" var instead incoming "pass" to generate "data"

And also remove Padding for options

let algoritm:  CCAlgorithm = UInt32(kCCAlgorithm3DES)

Thanks

解决方案

It is probably a different padding being used. DES has a block size of 8 byte. So the first block is 12345678 and the second block is 9. Since DES is a block cipher the plaintext must be padded to the next block size.

The online tool probably uses zero padding or no padding which basically means that the other bytes of the block are set to 0x00. You use in your code on the other hand PKCS#7 padding. Remove the PKCS#7 flag, to see if the output matches.

You will have to do the zero padding yourself if the library doesn't provide it. Fill up the password with \0 bytes until a multiple of the block size is reached during encryption and remove those zero bytes during decryption.

It is not recommended to use encryption without padding.

Also, password are not usually encrypted, but rather hashed with a random salt and multiple iterations. When your user database gets "lost", you don't want the one who found it, to be able to easily reverse the passwords and log in as any user (the assumption being that the encryption key is also easily "loseable"). Using a strong cryptographic hash function on the other hand has the advantage that it is really infeasible to reverse the hash.

这篇关于iOS 3DES与ECB返回一半正确的数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆