为什么不同的scrypt实现产生不同的结果?

Eri*_*eim 1 scrypt

我使用这个scrypt实现实现了一个简单的gode,用于使用Go确定性地生成密码.我的代码在这里,这是一个相关部分的提取:

const keyLen = 8

// recommended cost parameters for interactive login in 2009
const N = 16384
const r = 8
const p = 1

func main() {    
    dk, _ := scrypt.Key([]byte("mypassword"), []byte("mysalt"), N, r, p, keyLen)
    for _, v := range dk {
        fmt.Printf("%x ", v)
    }

    fmt.Println()
}
Run Code Online (Sandbox Code Playgroud)

运行代码我得到输出:

19 e5 59 39 fe 1 2b ef
Run Code Online (Sandbox Code Playgroud)

然而,当我尝试C实现基于libscrypt我会得到的结果相同.我会得到:

68 56 66 b2 86 19 2f 6e
Run Code Online (Sandbox Code Playgroud)

C代码在这里,这是主要部分:

int N = 16384;
int r = 8;
int p = 1;
const int keyLen = 8;

int main(void) {
    unsigned char digest[keyLen];
    const unsigned char password[] = "mypassword";
    const unsigned char salt[] = "mysalt";

    libscrypt_scrypt(password, sizeof(password), salt, sizeof(salt), N, r, p, digest, keyLen);

    for (int i = 0; i < keyLen; ++i) {
        printf("%x ", digest[i]);
    }
    printf("\n");

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我还遇到了另一个实现scrypt-jane,它在散列时给出了另一个结果.虽然我意识到这可能是因为scrypt jane允许您选择使用哪种散列函数.在任何情况下我都没有使用随机盐.

我试图在这里验证我自己的预感是没有关于scrypt使用什么散列函数的明确标准.如果是这样,我如何确保Go,C,python或JavaScript中的实现都产生相同的结果?我宁愿避免自己移植代码,因为据我所知,这是密码学中的风险业务.

Eri*_*eim 6

调用libscrypt_scrypt库中方法的C代码包含两个错误,这会导致计算错误的结果.违规部分是:

sizeof(password)
sizeof(salt)
Run Code Online (Sandbox Code Playgroud)

sizeof将包括在所述字符串的末尾的0 termnating所以代替"输入mypassword"和"mysalt"渐长度10和6分别他们得到11和7.因此计算散列当两个额外的0的也包括在内.

所以问题可以通过写:

strlen((const char *)password)
strlen((const char *)salt)
Run Code Online (Sandbox Code Playgroud)

要么

sizeof(password) - 1
sizeof(salt) - 1
Run Code Online (Sandbox Code Playgroud)

用于哈希函数的saltpassword参数scrypt.