本文翻譯自 How to select a JOSE / JWT cryptographic algorithm for your application在旱。
JOSE 即 JavaScript Object Signing and Encryption摇零,已采用了一系列標(biāo)準(zhǔn)加密算法,包括新的 Edwards 曲線算法(2017年新增)桶蝎。那么應(yīng)該使用哪種算法來保護(hù) JWT 或應(yīng)用程序中的其他對(duì)象呢驻仅?本指南將提供一些基本準(zhǔn)則,以便做出明智的選擇登渣。 但是噪服,也請(qǐng)咨詢?cè)擃I(lǐng)域的文章,文獻(xiàn)和專家胜茧,以仔細(xì)檢查您的假設(shè)粘优,并確保沒有遺漏任何重要問題。
一呻顽、常見的數(shù)據(jù)安全關(guān)注點(diǎn)
我們保護(hù)數(shù)據(jù)(例如令牌)的需求通常來自一個(gè)或多個(gè)關(guān)注的問題:
- 完整性
關(guān)注數(shù)據(jù)未被篡改 - 真實(shí)性
關(guān)注可以驗(yàn)證數(shù)據(jù)的來源 - 不可抵賴
數(shù)據(jù)的來源必須可由其他人驗(yàn)證 - 保密
對(duì)未經(jīng)授權(quán)的各方和操作保密
選擇合適的 JOSE 算法的第一步雹顺,是了解我們所關(guān)注的安全因素。
二芬位、可用的 JOSE 算法類
JOSE 提供了三種截然不同的加密算法類无拗,以解決四個(gè)安全問題,它們具有部分重疊的屬性:
算法 | 完整性 | 真實(shí)性 | 不可抵賴性 | 保密性 |
---|---|---|---|---|
HMAC | ? | ? | ||
數(shù)字簽名 | ? | ? | ? | |
認(rèn)證加密 | ? | ? | ? |
HMAC 算法:一種特殊的超高效哈希(HMAC)昧碉,用于確保數(shù)據(jù)的完整性和真實(shí)性英染。 為了計(jì)算 HMAC,您需要一個(gè)密鑰被饿。
數(shù)字簽名:提供 HMAC 的特性四康,以及加密的不可否認(rèn)性(使簽名者以外的其他人可以檢查簽名的有效性)。 數(shù)字簽名基于公鑰/私鑰密碼術(shù)狭握。 需要一對(duì)公鑰/私鑰(類型為 RSA闪金,橢圓曲線(EC)或愛德華茲曲線八位密鑰對(duì)(OKP))。
認(rèn)證加密:在加密數(shù)據(jù)的同時(shí)论颅,還確保其完整性和真實(shí)性(例如 HMAC)哎垦。 JOSE 通過公鑰/私鑰,秘密(共享)密鑰和密碼來提供加密恃疯。
1漏设、基于哈希的消息認(rèn)證碼(HMAC)
- 功能:完整性、認(rèn)證
- JOSE 格式:JSON Web Signature(JWS)
- 秘鑰類型:密碼
- 算法:HMAC with SHA-2
- HS256
- HS384
- HS512
- 用例:
- 存儲(chǔ)在瀏覽器 Cookie 中的無狀態(tài)會(huì)話
- 電子郵件驗(yàn)證碼
- 會(huì)話 ID 能夠區(qū)分過期 ID 和無效 ID
- Token 的頒發(fā)者和最終用戶是==同一角色==
- 備注
- HMAC 不是數(shù)字簽名今妄!
- 使用更長(zhǎng)的密鑰/哈希(例如 HS512 )以提高安全性
- 長(zhǎng)于哈希大小的密鑰不能提供額外的安全性
對(duì)于令牌和其他需要向外發(fā)送或存儲(chǔ)的信息郑口,如果最終由頒發(fā)它的應(yīng)用程序使用,那么 HMAC 算法(帶有 JOSE alg 標(biāo)識(shí)符 HS256盾鳞,HS384 和 HS512)是理想的選擇犬性。
這里的主要關(guān)注點(diǎn)是確保:
1)當(dāng)我們?nèi)』財(cái)?shù)據(jù)時(shí)數(shù)據(jù)的完整性,以及
2)數(shù)據(jù)實(shí)際上是由我們產(chǎn)生的腾仅。
示例 JWT 聲明了無狀態(tài)會(huì)話 Cookie:
{
"sub" : "user-12345",
"email" : "alice@wonderland.net",
"login_ip" : "172.16.254.1",
"exp" : 1471102267
}
一個(gè)常見的誤解乒裆,是消息身份驗(yàn)證代碼可以視為數(shù)字簽名。 其實(shí)并不是推励! 這是因?yàn)轵?yàn)證的過程需要用到計(jì)算 HMAC 時(shí)使用的原始密鑰鹤耍,并且從本質(zhì)上講,該密鑰不能與他人分享吹艇,因?yàn)椴荒茏屗司邆渖勺约旱?HMAC 的能力惰蜜。 如果想要不可否認(rèn)性,請(qǐng)使用 RSA受神,EC 或 EdDSA 簽名抛猖。
2、數(shù)字簽名
功能:完整性鼻听、認(rèn)證财著、不可抵賴性
JOSE 格式:JSON Web Signature(JWS)
-
秘鑰類型:公鑰/私鑰對(duì)
- RSA
- EC
- OKP
-
算法
-
RSA signature with PKCS #1 and SHA-2
- RS256
- RS384
- RS512
-
- PS256
- PS384
- PS512
-
- ES256
- ES384
- ES512
-
Edwards-curve DSA signature with SHA-2
- Ed25519
- Ed448
-
-
用例
- ID tokens (OpenID Connect)
- Self-contained access tokens (OAuth 2.0)
- 在域之間傳遞安全性斷言和令牌
- 需要必須由其他人驗(yàn)證數(shù)據(jù)的完整性和真實(shí)性的場(chǎng)景
-
備注
- 私鑰一定要保密!
- 推薦的 RSA 密鑰大小為 2048 位
- EdDSA 簽名提供最佳性能
數(shù)字簽名適用于發(fā)行令牌撑碴、聲明撑教、斷言和文檔,且這些文檔的完整性和真實(shí)性必須由其他各方進(jìn)行驗(yàn)證的場(chǎng)景醉拓。
使用示例:
- 由 OpenID 提供者發(fā)行的身份令牌伟姐,依賴方需要對(duì)其進(jìn)行驗(yàn)證才能登錄用戶收苏。
- 由 OAuth 2.0 服務(wù)器發(fā)出的訪問令牌,資源服務(wù)器 / Web API 必須在提供請(qǐng)求之前對(duì)其進(jìn)行驗(yàn)證愤兵。
數(shù)字簽名僅適用于公用/專用密鑰:
- 頒發(fā)者需要先生成 公鑰/私鑰對(duì)鹿霸,然后才能對(duì) JWT 或其他對(duì)象進(jìn)行簽名。
- 簽名是用私鑰計(jì)算的懦鼠,私鑰必須始終保持安全,否則會(huì)有冒充的風(fēng)險(xiǎn)屹堰。
- JWT 或 JWS 對(duì)象的簽名需要使用公鑰驗(yàn)證肛冶。接收者發(fā)現(xiàn)和下載公鑰的方法是特定于應(yīng)用程序的。 例如扯键,OpenID Connect 服務(wù)器在 JWK 格式的 URL 上發(fā)布其公鑰睦袖。
選擇哪種數(shù)字簽名算法?
如果您需要廣泛的支持忧陪,請(qǐng)選擇 RS256扣泊。 該算法基于 RSA PKCS#1,它仍然是公鑰/私鑰密碼術(shù)使用最廣泛的標(biāo)準(zhǔn)嘶摊。 任何足夠好的 JWT 庫都應(yīng)支持它延蟹。 RSxxx 簽名也花費(fèi)很少的 CPU 時(shí)間進(jìn)行驗(yàn)證(有助于確保在資源服務(wù)器上快速處理訪問令牌)。 推薦的 RSA 密鑰長(zhǎng)度為 2048 位叶堆。
ESxxx 簽名算法使用橢圓曲線(EC)加密阱飘。 它們需要較短的密鑰,并且產(chǎn)生較小的簽名(相當(dāng)于 RSA 強(qiáng)度)虱颗。 但是沥匈,EC 簽名有一個(gè)缺點(diǎn):它們的驗(yàn)證速度很慢。
新的 Edxxx 算法提供了最佳的簽名/驗(yàn)證性能組合忘渔。 特別是通過 P-265 曲線簽名高帖,比2048 位 RSA 高 62 倍,比 EC DSA 高 14 倍畦粮。
我們有 RSA散址,EC 和 EdDSA 簽名的 JWT 的示例。
3宣赔、認(rèn)證加密
功能:機(jī)密性预麸、完整性、認(rèn)證
JOSE 格式:JSON Web Encryption(JWE)
-
秘鑰類型:
- Public / private key pair:
- RSA
- EC
- OKP
- Secret (shared) key
- Password
- Public / private key pair:
-
算法
-
公鑰/私鑰加密
- RSA
-
RSA OAEP
- RSA-OAEP
- RSA-OAEP-256
- RSA PKCS #1
-
RSA OAEP
- EC
- RSA
-
秘密(共享)密鑰加密
-
Direct AES encryption
- dir
-
AES key wrap
- A128KW
- A192KW
- A256KW
-
AES GCM key encryption
- A128GCMKW
- A192GCMKW
- A256GCMKW
-
Direct AES encryption
-
基于密碼加密
-
PBES2
- PBES2-HS256+A128KW
- PBES2-HS384+A192KW
- PBES2-HS512+A256KW
-
PBES2
-
-
用例
- 簽名和加密的ID令牌(OpenID Connect)
- 簽名并加密的自包含訪問令牌(OAuth 2.0)
- 加密的文檔和數(shù)據(jù)儒将,具有完整性和真實(shí)性檢查
-
備注
- 保持私鑰和私鑰的安全吏祸!
- 推薦的 RSA 密鑰大小為 2048 位
JOSE 通過以下方式提供加密:
如果您想自己加密數(shù)據(jù),請(qǐng)使用密鑰钩蚊。 如果秘密密鑰是與其他方共享的(通過某種帶外方式)贡翘,則他們也可以使用它來加密數(shù)據(jù)/解密密文蹈矮。 請(qǐng)查看上表,了解可用的密鑰加密算法床估。
收件人提供的公共密鑰(RSA含滴,EC 或 OKP)诱渤。 例如丐巫,OpenID Connect 提供程序以可發(fā)現(xiàn)的 URL 以 JWK 格式發(fā)布其公共密鑰。 接收者然后可以使用其匹配的私鑰解密 JWT / JOSE 對(duì)象勺美。 在不可能或不可行帶外通信的情況下递胧,公鑰/私鑰密碼術(shù)是理想的選擇。
如果您想使用可以記住的短語加密數(shù)據(jù)赡茸,則為密碼缎脾。
JOSE 中的加密始終是經(jīng)過身份驗(yàn)證的,這意味著密文的完整性受到保護(hù)占卧,不會(huì)被篡改遗菠。 因此,經(jīng)過身份驗(yàn)證的加密使 HMAC JWT 嵌套在 JSON Web 加密(JWE)中變得多余华蜒。 僅使用 JWE 加密辙纬。
JWE 加密是一個(gè)“兩步”過程:
1、數(shù)據(jù)或內(nèi)容始終使用 AES 密鑰(稱為內(nèi)容加密密鑰或 CEK)進(jìn)行加密叭喜,并且每個(gè) JWT / JWE 對(duì)象都使用不同的 CEK贺拣。 Nimbus 庫將自動(dòng)為您生成此 AES 密鑰,并且其長(zhǎng)度將取決于 enc(加密方法)標(biāo)頭參數(shù)(例如捂蕴,"enc": "A128GCM"
將導(dǎo)致生成 128 位 AES 密鑰)譬涡。 除了可以選擇三種 AES 密鑰長(zhǎng)度(128、198 和 256)之外啥辨,JOSE 還支持兩種內(nèi)容加密模式:AxxxCBC-HSxxx 和 AxxxGCM涡匀。 通常,更廣泛地支持 AxxxCBC-HSxxx 模式溉知。
2陨瘩、第二步是使用輸入密鑰(即您提供的秘密密鑰,公共密鑰或密碼)對(duì)生成的 AES CEK 進(jìn)行加密(也稱為包裝)着倾。 這由 alg JWE 標(biāo)頭參數(shù)指定拾酝。 如果要跳過第二步,直接提供 AES CEK卡者,請(qǐng)選擇直接加密并指定 "alg": "dir"
JWE 標(biāo)頭參數(shù)蒿囤。
示例 JWE 標(biāo)頭,其中的內(nèi)容在 GCM 模式下使用 128 位 AES 加密崇决,而 AES CEK 本身使用公共 RSA 密鑰加密(使用 RSA OAEP 加密):
{
"alg" : "RSA-OAEP",
"enc" : "A128GCM"
}
您可以查看使用 RSA 公鑰加密 JWT 的示例材诽。
三底挫、嵌套簽名和加密
可以對(duì)簽名的 JWT / JWS 對(duì)象進(jìn)行附加加密,從而為數(shù)據(jù)提供完整性脸侥,真實(shí)性建邓,不可否認(rèn)性和機(jī)密性。
這是通過簡(jiǎn)單的嵌套實(shí)現(xiàn)的(請(qǐng)參見示例):
1睁枕、JWT 用專用的 RSA官边,EC 或 OKP 密鑰簽名。
2外遇、然后注簿,簽名的 JWT 成為 JWE 對(duì)象的有效負(fù)載(純文本),該JWE對(duì)象使用接收者的公鑰(RSA跳仿,EC诡渴,OKP)或已在兩方之間共享的秘密密鑰進(jìn)行加密。
處理嵌套的 JWT 向后工作:
1菲语、使用適當(dāng)?shù)拿荑€(RSA妄辩,EC 或 OKP 的私鑰或已建立的私鑰)解密 JWE 對(duì)象。
2山上、然后將提取的有效負(fù)載(純文本)解析為簽名的 JWT眼耀,并使用發(fā)行者的公鑰(RSA,EC 或 OKP)進(jìn)行驗(yàn)證胶哲。
Nimbus JOSE + JWT 庫提供了用于處理嵌套 JWT 的完整框架畔塔。
四、OpenID Connect 中的算法選擇
通過以下規(guī)則鸯屿,您可以了解在給定客戶端注冊(cè)后哪些 ID 令牌算法可行:
1澈吨、具有 client_secret 的客戶端可以接收由 HMAC(其中 client_secret 充當(dāng) HMAC 秘密密鑰)或簽名(RSA,EC 或 EdDSA)保護(hù)的 ID 令牌寄摆。 為了驗(yàn)證 RSA谅辣,EC 或 EdDSA 簽名的 ID 令牌,客戶端僅需要(從其 JWK 設(shè)置 URL 中)檢索 OpenID 提供程序的匹配公鑰婶恼。
2桑阶、帶有 client_secret 的客戶端也可以接收加密的 ID 令牌,其中 client_secret 用于從中導(dǎo)出秘密 AES 密鑰勾邦。
3蚣录、如果使用 HMAC,則要求的 client_secrets 必須足夠長(zhǎng)以適合所需的密鑰長(zhǎng)度眷篇。 例如萎河,一個(gè) 256 位 client_secret 允許 HMAC 與 HS256 一起使用。
4、為了使客戶端能夠接收 RSA 或 ECDH 加密的 ID 令牌虐杯,它必須具備使用 OpenID 提供方注冊(cè)的 RSA玛歌,EC 或 OKP 公鑰。
5擎椰、OpenID Connect 還允許沒有 client_secret 的客戶端支子。 此類客戶端需要向 OpenID 提供程序注冊(cè)的 RSA,EC 或 OKP 公鑰达舒,并使用該密鑰在令牌端點(diǎn)進(jìn)行身份驗(yàn)證(通過 JWT)值朋。 如上所述,可以將 ID 令牌加密為該公共密鑰休弃。
五吞歼、參考資料
(完)