【问题标题】:Different Session Keys in SRP6SRP6 中的不同会话密钥
【发布时间】:2014-05-15 23:04:27
【问题描述】:

我正在尝试使用加密模块在 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

【问题讨论】:

    标签: erlang srp-protocol


    【解决方案1】:

    很遗憾,这是 OTP SRP 实现中的一个错误,会影响客户端密钥的计算。

    有一个可用的修复: https://github.com/erlang/otp/pull/369

    或者,您可以自己计算客户端密钥,类似这些。

    computeClientKey() ->
        ServerPublic = getServerPublic(),
        ClientPrivate = getClientPrivate(),
        ClientPublic = getClientPublic(),
        Generator = getGenerator(),
        Prime = getPrime(),
        Version = getVersion(),
        DerivedKey = getDerivedKey(),
    
        Multiplier = getMultiplier(Version, Generator, Prime),
    
        U = crypto:hash(sha, [padded(ClientPublic, Prime), padded(ServerPublic, Prime)]),
        PrimeI = bin_to_int(Prime),
        BX = crypto:mod_pow(Generator, DerivedKey, Prime),
        BTMPI0 = bin_to_int(ServerPublic) - bin_to_int(Multiplier) * bin_to_int(BX),
        BTMPI = BTMPI0 rem PrimeI,
        Base = if
            BTMPI > 0 -> int_to_bin(BTMPI);
            true -> int_to_bin(BTMPI + PrimeI)
        end,
        Exponent = int_to_bin(bin_to_int(ClientPrivate) + bin_to_int(U) * bin_to_int(DerivedKey)),
        crypto:mod_pow(Base, Exponent, Prime).
    
    padded(V, N) when byte_size(V) =:= byte_size(N) -> V;
    padded(V, N) when byte_size(V) < byte_size(N) ->
        NLen = byte_size(N),
        PadLen = (NLen - byte_size(V)) * 8,
        Pad = <<0:PadLen>>,
        [Pad, V].
    
    int_to_bin(Int) ->
        Len0 = length(erlang:integer_to_list(Int, 16)),
        Len1 = Len0 + (Len0 rem 2),
        Bits = Len1 * 4,
        <<Int:Bits>>.
    
    bin_to_int(Bin) ->
        Bits = byte_size(Bin) * 8,
        <<Val:Bits>> = Bin,
        Val.
    
    getMultiplier('6a', Generator, Prime) ->
        crypto:hash(sha, [Prime, padded(Generator, Prime)]);
    getMultiplier('6', _Generator, _Prime) ->
        <<3/integer>>;
    getMultiplier('3', _Generator, _Prime) ->
        <<1/integer>>.
    

    【讨论】:

      猜你喜欢
      • 2014-05-31
      • 2017-02-14
      • 2016-12-05
      • 1970-01-01
      • 2013-12-25
      • 2018-03-17
      • 1970-01-01
      • 2021-09-02
      • 1970-01-01
      相关资源
      最近更新 更多