iOS 3DES with ECB return 一半正确的数据
iOS 3DES with ECB return half correct data
使用 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/
Select 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 += "[=16=]"
}
然后用"password"var代替传入"pass"生成"data"
并删除选项的填充
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
谢谢
可能使用了不同的填充。 DES 的块大小为 8 字节。所以第一块是12345678
,第二块是9
。由于 DES 是块密码,因此必须将明文填充到下一个块大小。
在线工具可能使用零填充或无填充,这基本上意味着块的其他字节设置为 0x00。另一方面,您在代码中使用 PKCS#7 填充。删除 PKCS#7 标志,查看输出是否匹配。
如果图书馆不提供,您将不得不自己进行零填充。用 [=12=]
字节填充密码,直到在加密期间达到块大小的倍数,并在解密期间删除那些零字节。
不建议使用无填充加密。
此外,密码通常不加密,而是使用随机盐和多次迭代 散列。当您的用户数据库获得 "lost" 时,您不希望找到它的人能够轻松地反转密码并以任何用户身份登录(假设加密密钥也很容易 "loseable").另一方面,使用强大的加密哈希函数的优点是它确实无法反转哈希。
使用 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/ Select 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 += "[=16=]"
}
然后用"password"var代替传入"pass"生成"data"
并删除选项的填充
let algoritm: CCAlgorithm = UInt32(kCCAlgorithm3DES)
谢谢
可能使用了不同的填充。 DES 的块大小为 8 字节。所以第一块是12345678
,第二块是9
。由于 DES 是块密码,因此必须将明文填充到下一个块大小。
在线工具可能使用零填充或无填充,这基本上意味着块的其他字节设置为 0x00。另一方面,您在代码中使用 PKCS#7 填充。删除 PKCS#7 标志,查看输出是否匹配。
如果图书馆不提供,您将不得不自己进行零填充。用 [=12=]
字节填充密码,直到在加密期间达到块大小的倍数,并在解密期间删除那些零字节。
不建议使用无填充加密。
此外,密码通常不加密,而是使用随机盐和多次迭代 散列。当您的用户数据库获得 "lost" 时,您不希望找到它的人能够轻松地反转密码并以任何用户身份登录(假设加密密钥也很容易 "loseable").另一方面,使用强大的加密哈希函数的优点是它确实无法反转哈希。