我正在尝试使用加密模块在 Erlang 中实现 SRP6,但我无法让会话密钥匹配。我使用的是 256 位素数。当我使用 1024 位素数时,它们匹配。我在 crypto:compute_key 中省略了可选的扰频器参数,但它没有区别。
谁能帮我弄清楚为什么我的会话密钥不匹配?
-module(srp).
-export([test/0]).
getUsername() -> <<"alice">>.
getPassword() -> <<"password123">>.
getSalt() -> <<"mystrongsalt">>.
getGenerator() -> <<7>>.
%% srp version 6
getVersion() -> '6'.
% randomly generated 32 byte number
getClientPrivate() ->
<<16#C49F832EE8D67ECF9E7F2785EB0622D8B3FE2344C00F96E1AEF4103CA44D51F9:256>>.
% randomly generated 32 byte number
getServerPrivate() ->
<<16#6C78CCEAAEC15E69068A87795B2A20ED7B45CFC5A254EBE2F17F144A4D99DB18:256>>.
%% 32 byte prime number
%% used in mangos: https://github.com/mangoszero/server/blob/master/src/realmd/AuthSocket.cpp#L190
%% used in arcemu: http://arcemu.org/wiki/Server_Logon_Challenge
getPrime() ->
<<16#894B645E89E1535BBDAD5B8B290650530801B18EBFBF5E8FAB3C82872A3E9BB7:256>>.
%% v = g^x
getVerifier() ->
Generator = getGenerator(),
Prime = getPrime(),
DerivedKey = getDerivedKey(),
crypto:mod_pow(Generator, DerivedKey, Prime).
%% x = H(salt, H(username, :, password))
getDerivedKey() ->
Username = getUsername(),
Password = getPassword(),
Salt = getSalt(),
crypto:hash(sha, [Salt, crypto:hash(sha, [Username, <<$:>>, Password])]).
%% client public key
getClientPublic() ->
PrivateKey = getClientPrivate(),
Generator = getGenerator(),
Prime = getPrime(),
Version = getVersion(),
{Pub, PrivateKey} = crypto:generate_key(srp, {user, [Generator, Prime, Version]}, PrivateKey),
Pub.
%% server public key
getServerPublic() ->
PrivateKey = getServerPrivate(),
Generator = getGenerator(),
Prime = getPrime(),
Version = getVersion(),
Verifier = getVerifier(),
{Pub, PrivateKey} = crypto:generate_key(srp, {host, [Verifier, Generator, Prime, Version]}, PrivateKey),
Pub.
%% client session key
computeClientKey() ->
ServerPublic = getServerPublic(),
ClientPrivate = getClientPrivate(),
ClientPublic = getClientPublic(),
Generator = getGenerator(),
Prime = getPrime(),
Version = getVersion(),
DerivedKey = getDerivedKey(),
crypto:compute_key(srp, ServerPublic, {ClientPublic, ClientPrivate}, {user, [DerivedKey, Prime, Generator, Version]}).
%% server session key
computeServerKey() ->
ClientPublic = getClientPublic(),
ServerPrivate = getServerPrivate(),
ServerPublic = getServerPublic(),
Prime = getPrime(),
Version = getVersion(),
Verifier = getVerifier(),
crypto:compute_key(srp, ClientPublic, {ServerPublic, ServerPrivate}, {host, [Verifier, Prime, Version]}).
test() ->
%% these session keys should match
ClientKey = computeClientKey(),
ServerKey = computeServerKey(),
io:format("client skey: ~p~n", [ClientKey]),
io:format("server skey: ~p~n", [ServerKey]),
ClientKey == ServerKey.
可以在这里找到要点https://gist.github.com/jcclinton/4cdc9f616927677737a2