1

現在、MongooseIM を少しいじっていて、スクラムと一緒に HTTP 認証を使用したいと考えています。python passlib を使用してスクラム ハッシュを作成しています。

import sys
from passlib.hash import scram


def main():
    hash = scram.encrypt(sys.argv[1], rounds=4096, salt_size=16)
    print hash


if __name__ == "__main__":
    main()

それから私はこのようなものになります:

$scram$4096$BmAsRcgZA4AwRijl3FtLyQ$sha-1=AXh5FzYzEnf6PaVQNR79AZhkwz8,sha-256=YZceXCVhfCBrr8sM9k3eS.5bztHugerGzjO97emvn20,sha-512=2NyVspiE7MP6xBAEycAV5Z/nIbBlki3sHfWvVUPPnEkMt5b4VbZfDZ0s8lvE/ns0scPGWmfKhUobmZbjfFH6RA

残念ながら、この形式は MongooseIM の HTTP 認証では受け入れられません。私はコードを見て、スクラムのハッシュ化されたパスワードのシリアル化された形式がどのように見えるかを調べようとしました: https://github.com/esl/MongooseIM/blob/master/apps/ejabberd/src/scram.erl

deserialize(<<?SCRAM_SERIAL_PREFIX, Serialized/binary>>) ->
    case catch binary:split(Serialized, <<",">>, [global]) of
        [StoredKey, ServerKey,Salt,IterationCount] ->
            {ok, #scram{storedkey = StoredKey,
                        serverkey = ServerKey,
                        salt = Salt,
                        iterationcount = binary_to_integer(IterationCount)}};
        _ ->
            ?WARNING_MSG("Incorrect serialized SCRAM: ~p, ~p", [Serialized]),
            {error, incorrect_scram}
    end;

passlib から、私が理解している限り、ソルト、反復回数、およびソルト (ハッシュ) パスワードの実際のダイジェスト (sha-1、sha-256、sha-512) を取得しますが、StoredKey と ServerKey はどうですか?アーランコード? host/get_password によって返される正しいシリアライズされた HTTP 本文はどのようになりますか?

前もってありがとう、マグナス

4

2 に答える 2

2

それは非常に良い質問であり、実際に文書化されていないことに気づきました. 私たちはそれを修正します。

今のところ、予想される形式は次のようになります (MongooseIM のデバッグ シェルを使用して生成できます)。

scram:serialize(scram:password_to_scram(<<"ala_ma_kota">>, 4096)).
<<"==SCRAM==,xB2++RvZklv0rV5I1iuCpoxLqL0=,sKXBkOFrtyGxKqYo/dlzeKfYszU=,oplvMJ5VDxQ7rJZuIj0ZfA==,4096">>

つまり、MongooseIM は次のような形式を期待しています。

==SCRAM==,StoredKey,ServerKey,Salt,IterationCount

==SCRAM== プレフィックスは一定で、他の部分はパスワードに依存します。

それが役立つことを願っています。

于 2016-02-26T14:02:21.967 に答える
1

だから私はそれを理解し、期待されるフォーマットを生成するための小さなPythonスクリプトを書きました。

import base64
import hashlib
import hmac
import sys
from passlib.hash import scram


# password_to_scram(Password, IterationCount) ->
#     Salt = crypto:rand_bytes(?SALT_LENGTH),
#     SaltedPassword = salted_password(Password, Salt, IterationCount),
#     StoredKey = stored_key(scram:client_key(SaltedPassword)),
#     ServerKey = server_key(SaltedPassword),
#     #scram{storedkey = base64:encode(StoredKey),
#            serverkey = base64:encode(ServerKey),
#            salt = base64:encode(Salt),
#            iterationcount = IterationCount}.
def main():
    rounds = 4096
    hash = scram.encrypt(sys.argv[1], rounds=rounds, salt_size=16)
    hash = scram.encrypt('1234', rounds=rounds, salt='salt')
    salt, iterations, salted_password = scram.extract_digest_info(hash, "sha-1")

    # server_key(SaltedPassword) ->
    # crypto:hmac(sha, SaltedPassword, <<"Server Key">>).
    server_key = hmac.new(key=salted_password, msg='Server Key', digestmod=hashlib.sha1).digest()

    # client_key(SaltedPassword) ->
    # crypto:hmac(sha, SaltedPassword, <<"Client Key">>).
    client_key = hmac.new(key=salted_password, msg='Client Key', digestmod=hashlib.sha1).digest()

    # StoredKey = stored_key(scram:client_key(SaltedPassword)),
    stored_key = hashlib.sha1(client_key).digest()

    result = '==SCRAM==,%s,%s,%s,%d' % \
          (base64.b64encode(stored_key), base64.b64encode(server_key), base64.b64encode(salt), rounds)

    print result

if __name__ == '__main__':
    main()

検証:

(mongooseim@localhost)2> base64:encode(scram:salted_password(<<"1234">>, <<"salt">>, 4096)).    
<<"vbpf4gmRPxs/+ru4TZJO3toJdw0=">>

(mongooseim@localhost)4> base64:encode(scram:stored_key(scram:client_key(scram:salted_password(<<"1234">>, <<"salt">>, 4096)))).
<<"bXKEekOUoWNAx0f21H/fIZ4dj6Y=">>

(mongooseim@localhost)3> base64:encode(scram:server_key(scram:salted_password(<<"1234">>, <<"salt">>, 4096))).
<<"eVwl7wTir232HDy7Tzq3SXZHn+4=">>

==SCRAM==,bXKEekOUoWNAx0f21H/fIZ4dj6Y=,eVwl7wTir232HDy7Tzq3SXZHn+4=,c2FsdA==,4096
于 2016-02-26T16:29:15.877 に答える