2016-02-26 46 views
1

我目前正在玩MongooseIM一點點,並希望與scram一起使用HTTP認證。我使用Python passlib創建急停散列:MongooseIM/ejabberd:http認證使用scram

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認證所接受。我看了一下代碼,並試圖找出急停的serialzed形式如何散列密碼,看起來像在這裏: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),據我所知,但是從Erlang代碼的StoredKey和ServerKey呢?如何通過host/get_password返回正確的序列化HTTP主體?

由於提前, 馬格努斯

回答

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() 

驗證:

([email protected])2> base64:encode(scram:salted_password(<<"1234">>, <<"salt">>, 4096)).  
<<"vbpf4gmRPxs/+ru4TZJO3toJdw0=">> 

([email protected])4> base64:encode(scram:stored_key(scram:client_key(scram:salted_password(<<"1234">>, <<"salt">>, 4096)))). 
<<"bXKEekOUoWNAx0f21H/fIZ4dj6Y=">> 

([email protected])3> base64:encode(scram:server_key(scram:salted_password(<<"1234">>, <<"salt">>, 4096))). 
<<"eVwl7wTir232HDy7Tzq3SXZHn+4=">> 

==SCRAM==,bXKEekOUoWNAx0f21H/fIZ4dj6Y=,eVwl7wTir232HDy7Tzq3SXZHn+4=,c2FsdA==,4096 
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 ==前綴是恆定的,其它部分取決於密碼。

希望有所幫助。

+0

謝謝,但究竟什麼是StoredKey和ServerKey?如何使用我自己的認證服務從MongooseIM服務器中分離出相應的生成密碼哈希? – Magnus

+0

您可以檢查[password_to_scram](https://github.com/esl/MongooseIM/blob/master/apps/ejabberd/src/scram.erl#L139-L147)。基本上這個SCRAM認證方法是這裏描述的SCRAM-SHA-1機制的實現[RFC 5802](https://tools.ietf.org/html/rfc5802) – michalwski

+0

我只注意到你已經知道了。幹得好! – michalwski