我在我的RESTful API項目中使用身份驗證方法,我非常喜歡生成HMAC-SHA256簽名作爲身份驗證方法的想法。使用散列「密碼」生成HMAC簽名
客戶端被創建具有幾個簡單的步驟的簽名:
# example client-side code
sig = hmac.new(bytes('SUPER_SECRET_KEY', 'utf-8'), b'', sha256)
sig.update(request_path)
sig.update(request_body)
# ...other variables needed for generating the signature...
signature = sig.hexdigest()
和增加它與他的「用戶名」沿着請求報頭(例如Authorization: THE_USER_NAME:abcd1234xyz890
)。
在服務器端,我想以同樣的方式重新創建它:
# example server-side code
def do_check(request):
# get user name from request header
username = request.headers['Authorization'].split(':')[0]
# some method to retrieve the "secret key" from database
user = db.User().filter(username=username).one()
# use user's "secret key" to generate the signature
sig = hmac.new(bytes(user.key, 'utf8'), b'', sha256)
sig.update(bytes(request.path, 'utf-8'))
sig.update(request.data)
# ...other variables needed for generating the signature...
return sig.hexdigest()
# compare the returned signature with the one client sent us...
這一切,只要我保存用戶的明文重點工作正常在我的數據庫:
| username | key |
------------------------------------
| THE_USER_NAME | SUPER_SECRET_KEY |
我們都知道,這是絕對不能接受的,所以我想簡單地散列SUPER_SECRET_KEY
與bcrypt
和存儲散列串inste廣告:
| username | key |
--------------------------------------------------------------------------------
| THE_USER_NAME | $2b$12$UOIKEBFBedbcYFhbXBclJOZIEgSGaFmeZYhQtaE4l6WobFW1qvIf6 |
我現在面臨的問題是「密鑰」的客戶端使用的未哈希版本生成對此我不能做服務器端,因爲我沒有它簽名用純文本了。
其中一個類似方法的例子是generating HMAC signature in Amazon Web Services(也是simplified explanation of the same process),它不需要任何額外的登錄或認證,也沒有爲密鑰/祕密組合提供任何令牌或「替換」。我真的懷疑AWS是否在數據庫中以純文本形式存儲祕密(?)
如何在服務器端使用數據庫中的「密鑰」散列版本重新創建HMAC簽名,而不是強制客戶端 - 一面改變它的簽名生成方法(例如,避免安裝bcrypt
或甚至散列祕密)?
感謝您澄清一些東西在這裏!我試着想想你的句子「...你通常使用其他方式進行身份驗證,然後使用hmac作爲實際的消息「,但有些服務使用與我描述的相同的方法,即使沒有額外的身份驗證......我用真實世界的示例更新了我的答案,請檢查它( ) – errata
你會注意到這個例子是一個共享密鑰,你可以通過登錄來創建它來管理訪問密鑰(http://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_access- keys.html),然後你有責任把它交給正確的人,並保護它免受錯誤的人的保護。 –
是的,我明白:)我的例子中還有一個「共享的祕密」(SUPER_SECRET_KEY)...我想知道的是如何避免將該密鑰存儲爲我的數據庫中的未加字符串... – errata