SHA1 MessageDigest 和 CommonCrypto 更新得到不同的结果
SHA1 MessageDigest and CommonCrypto updates getting different results
我正在尝试从 VB.NET 重新创建 PasswordDeriveBytes 的实现,到目前为止,我已经在 iOS Objective C 代码中实现了它给了我与 [=34= 不同的结果] 实施。
我们尝试重新创建 PasswordDeriveBytes 实现的原因是因为客户端服务器端正在使用它来处理 encrypt/decrypt 数据,根据我的搜索,PasswordDeriveBytes 使用 PBKDF1,它已经过时了。 Java 实现正在返回预期的加密值并且正在被服务器成功解密。然而,从 iOS ObjC 实现返回的值是不正确的。
下面是构造函数的 Java 实现,取自这个答案:
public static class PasswordDeriveBytes{
private final MessageDigest hash;
private final byte[] firstToLastDigest;
private final byte[] outputBuffer;
private int position = 0;
public PasswordDeriveBytes(String password, byte[] salt, int iterations) {
try {
this.hash = MessageDigest.getInstance("SHA-1");
this.hash.update(password.getBytes("UTF-8"));
this.hash.update(salt);
this.firstToLastDigest = this.hash.digest();
// At this point, the Obj-C and Java values are the same
// this.firstToLastDigest = b8fa3d36....
for (int i = 1; i < iterations - 1; i++) {
System.out.println( " Iterate " + i);
hash.update(firstToLastDigest);
hash.digest(firstToLastDigest, 0, firstToLastDigest.length);
}
this.outputBuffer = hash.digest(firstToLastDigest);
// However at this point, they become different
// Java has outputBuffer = f498e100...
// Obj-C has outputBuffer = <d7d5fa71...
} catch (UnsupportedEncodingException|NoSuchAlgorithmException | DigestException e) {
throw new IllegalStateException("SHA-1 digest should always be available", e);
}
}
下面是Objective C构造函数的代码,使用这个库:https://github.com/TakahikoKawasaki/nv-ios-digest
@implementation PasswordDeriveBytesObjC
{
SHA1 *hash;
Byte *firstToLastDigest;
Byte *outputBuffer;
int position;
}
- (instancetype)initWithPassword:(NSString *)password salt:(NSData *)salt iterations:(int)iterations
{
self = [[[self class] alloc] init];
if (self){
hash = [[SHA1 alloc] init];
const char* ASCIIpassword = [password cStringUsingEncoding:NSUTF8StringEncoding];
NSData *passwordData = [NSData dataWithBytes:ASCIIpassword length:strlen(ASCIIpassword)];
[hash updateWith:[passwordData bytes] length:(CC_LONG)[passwordData length]];
[hash updateWith:[salt bytes] length:(CC_LONG)[salt length]];
firstToLastDigest = [hash final];
// At this point, the Obj-C and Java values are the same
// firstToLastDigest = <b8fa3d36....
for ( int i = 1; i < iterations - 1; i++ ){
[hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)];
}
[hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)];
outputBuffer = [hash final];
// However at this point, they become different
// Java has outputBuffer = f498e100...
// Obj-C has outputBuffer = <d7d5fa71...
}
return self;
}
据我研究,java 的 hash.digest(input)
的实现与 Obj-C 中的 [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; outputBuffer = [hash final];
相同,但我得到不同的结果。
在这一点上,我对它们为何获得不同的值没有其他想法,因此欢迎提供任何指导或建议。
在扯掉我的头发 4 天后回答我自己的问题。
CommonCrypto 的 CC_SHA1_Final() 似乎没有重置 CC_SHA1_CTX
对象上下文,尽管 apple 文档说明它会重置,这会导致输出差异。
From Apple Docs: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/CC_SHA1_Final.3cc.html
CC_SHA1_Final() places the message digest in md, which must have space for CC_SHA1_DIGEST_LENGTH == 20
bytes of output, and erases the CC_SHA1_CTX.
我必须编辑 nv-ios-digest 库并在每个 - (unsigned char *)final
方法中手动重置 CC_SHA1_CTX
对象,如下所示:
- (unsigned char *)final
{
CC_SHA1_Final(_digest, &_context); // <-- _context does not reset
CC_SHA1_Init(&_context); // <-- manually reset the CC_SHA1_CTX object
_description = [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
_digest[ 0], _digest[ 1], _digest[ 2], _digest[ 3],
_digest[ 4], _digest[ 5], _digest[ 6], _digest[ 7],
_digest[ 8], _digest[ 9], _digest[10], _digest[11],
_digest[12], _digest[13], _digest[14], _digest[15],
_digest[16], _digest[17], _digest[18], _digest[19]];
return _digest;
}
希望这对某人有所帮助。 :)
我正在尝试从 VB.NET 重新创建 PasswordDeriveBytes 的实现,到目前为止,我已经在 iOS Objective C 代码中实现了它给了我与 [=34= 不同的结果] 实施。
我们尝试重新创建 PasswordDeriveBytes 实现的原因是因为客户端服务器端正在使用它来处理 encrypt/decrypt 数据,根据我的搜索,PasswordDeriveBytes 使用 PBKDF1,它已经过时了。 Java 实现正在返回预期的加密值并且正在被服务器成功解密。然而,从 iOS ObjC 实现返回的值是不正确的。
下面是构造函数的 Java 实现,取自这个答案:
public static class PasswordDeriveBytes{
private final MessageDigest hash;
private final byte[] firstToLastDigest;
private final byte[] outputBuffer;
private int position = 0;
public PasswordDeriveBytes(String password, byte[] salt, int iterations) {
try {
this.hash = MessageDigest.getInstance("SHA-1");
this.hash.update(password.getBytes("UTF-8"));
this.hash.update(salt);
this.firstToLastDigest = this.hash.digest();
// At this point, the Obj-C and Java values are the same
// this.firstToLastDigest = b8fa3d36....
for (int i = 1; i < iterations - 1; i++) {
System.out.println( " Iterate " + i);
hash.update(firstToLastDigest);
hash.digest(firstToLastDigest, 0, firstToLastDigest.length);
}
this.outputBuffer = hash.digest(firstToLastDigest);
// However at this point, they become different
// Java has outputBuffer = f498e100...
// Obj-C has outputBuffer = <d7d5fa71...
} catch (UnsupportedEncodingException|NoSuchAlgorithmException | DigestException e) {
throw new IllegalStateException("SHA-1 digest should always be available", e);
}
}
下面是Objective C构造函数的代码,使用这个库:https://github.com/TakahikoKawasaki/nv-ios-digest
@implementation PasswordDeriveBytesObjC
{
SHA1 *hash;
Byte *firstToLastDigest;
Byte *outputBuffer;
int position;
}
- (instancetype)initWithPassword:(NSString *)password salt:(NSData *)salt iterations:(int)iterations
{
self = [[[self class] alloc] init];
if (self){
hash = [[SHA1 alloc] init];
const char* ASCIIpassword = [password cStringUsingEncoding:NSUTF8StringEncoding];
NSData *passwordData = [NSData dataWithBytes:ASCIIpassword length:strlen(ASCIIpassword)];
[hash updateWith:[passwordData bytes] length:(CC_LONG)[passwordData length]];
[hash updateWith:[salt bytes] length:(CC_LONG)[salt length]];
firstToLastDigest = [hash final];
// At this point, the Obj-C and Java values are the same
// firstToLastDigest = <b8fa3d36....
for ( int i = 1; i < iterations - 1; i++ ){
[hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)];
}
[hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)];
outputBuffer = [hash final];
// However at this point, they become different
// Java has outputBuffer = f498e100...
// Obj-C has outputBuffer = <d7d5fa71...
}
return self;
}
据我研究,java 的 hash.digest(input)
的实现与 Obj-C 中的 [hash updateWith:firstToLastDigest length:(CC_LONG)strlen(firstToLastDigest)]; outputBuffer = [hash final];
相同,但我得到不同的结果。
在这一点上,我对它们为何获得不同的值没有其他想法,因此欢迎提供任何指导或建议。
在扯掉我的头发 4 天后回答我自己的问题。
CommonCrypto 的 CC_SHA1_Final() 似乎没有重置 CC_SHA1_CTX
对象上下文,尽管 apple 文档说明它会重置,这会导致输出差异。
From Apple Docs: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/CC_SHA1_Final.3cc.html
CC_SHA1_Final() places the message digest in md, which must have space for CC_SHA1_DIGEST_LENGTH == 20 bytes of output, and erases the CC_SHA1_CTX.
我必须编辑 nv-ios-digest 库并在每个 - (unsigned char *)final
方法中手动重置 CC_SHA1_CTX
对象,如下所示:
- (unsigned char *)final
{
CC_SHA1_Final(_digest, &_context); // <-- _context does not reset
CC_SHA1_Init(&_context); // <-- manually reset the CC_SHA1_CTX object
_description = [NSString stringWithFormat:
@"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
_digest[ 0], _digest[ 1], _digest[ 2], _digest[ 3],
_digest[ 4], _digest[ 5], _digest[ 6], _digest[ 7],
_digest[ 8], _digest[ 9], _digest[10], _digest[11],
_digest[12], _digest[13], _digest[14], _digest[15],
_digest[16], _digest[17], _digest[18], _digest[19]];
return _digest;
}
希望这对某人有所帮助。 :)