JOSESwift 是一个用于 JOSE 标准的 JWS、JWE 和 JWK 的模块化和可扩展框架,使用 Swift 编写。
💡 请注意,此 JOSE 标准的实现目前尚不完整。例如,目前只有有限的支持算法可用。此外,我们目前仅支持 JOSE 类型的紧凑序列化。如果您缺少特定的功能、算法或序列化,请随时 提交拉取请求。
内容
特性
- JWS:使用 JWS 标准对任意数据进行数字签名和验证。
- JWE:使用 JWE 标准对任意数据进行加密和解密。
- JWK:加密和解密密钥。
如果您缺少特定的功能、算法或序列化,请随时 提交拉取请求。
加密算法
🔏 JWS | 🔐 JWE | 🔑 JWK | |||||||
---|---|---|---|---|---|---|---|---|---|
数字签名和MAC | 密钥管理 | 内容加密 | 密钥 | ||||||
HS256 | ✅ | RSA1_5 | ✅ | A128CBC-HS256 | ✅ | RSA | ✅ | ||
HS384 | ✅ | RSA-OAEP | ✅ | A192CBC-HS384 | EC | ✅ | |||
HS512 | ✅ | RSA-OAEP-256 | ✅ | A256CBC-HS512 | ✅ | oct | ✅ | ||
RS256 | ✅ | A128KW | ✅ | A128GCM | |||||
RS384 | ✅ | A192KW | ✅ | A192GCM | |||||
RS512 | ✅ | A256KW | ✅ | A256GCM | |||||
ES256 | ✅ | dir | ✅ | ||||||
ES384 | ✅ | ECDH-ES | |||||||
ES512 | ✅ | ECDH-ES+A128KW | |||||||
PS256 | ✅ | ECDH-ES+A192KW | |||||||
PS384 | ✅ | ECDH-ES+A256KW | |||||||
PS512 | ✅ | A128GCMKW | |||||||
A192GCMKW | |||||||||
A256GCMKW | |||||||||
PBES2-HS256+A128KW | |||||||||
PBES2-HS384+A192KW | |||||||||
PBES2-HS512+A256KW |
序列化
为了可互操作性,JOSESwift 目前支持 JWS 的紧凑序列化以及 JWE。
紧凑序列化 | JSON 序列化 |
---|---|
✅ |
压缩算法
JOSESwift 支持用于 JWE 的 DEFLATE 压缩算法。
安装
JOSESwift 可以很好地整合到您的 iOS 和 macOS 项目中。我们支持以下软件包管理器
CocoaPods
要将 JOSESwift 整合到您的 Xcode 项目中,请在您的 Podfile
中包含它
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '10.0'
use_frameworks!
target '<Your Target Name>' do
pod 'JOSESwift', '~> 2.3'
end
然后通过运行 pod install
安装。有关使用 CocoaPods 的更多文档,请在此处查找。
Carthage
要将 JOSESwift 整合到您的 Xcode 项目中,请将其包含在您的 Cartfile
中
github "airsidemobile/JOSESwift" ~> 2.3
然后通过运行 carthage update
构建,并将构建的框架拖入您的 Xcode 项目中。有关使用 Carthage 的更多文档,请在此处查找。
Swift Package Manager
要将 JOSESwift 整合到您的 Xcode 项目作为 Swift 包,请遵循 Apple 关于如何在为您的应用程序添加包依赖项的文章。
另一种方法是,在手动使用 Swift Package Manager 时,将以下依赖项包含在您的 Package.swift
文件中。有关指定依赖项版本要求的更多详情,请参阅Apple的文档。
.package(url: "https://github.com/airsidemobile/JOSESwift.git", from: "2.3.0")
使用
JOSESwift 包含三个功能方面
JWS:数字签名
JWS
通过使用数字签名对数据进行封装和加密,该签名可以被 JWS
的接收者验证。
签名数据
为了构建 JWS,我们需要提供以下部分:
- 头部
- 有效载荷
- 签名者
头部
let header = JWSHeader(algorithm: .RS512)
可选地,您可以设置其他参数
header.kid = "2018-10-08"
header.typ = "JWS"
负载
let message = "Summer ⛱, Sun ☀️, Cactus 🌵".data(using: .utf8)!
let payload = Payload(message)
签名者
签名算法必须与报头算法相匹配。
let privateKey: SecKey = /* ... */
let signer = Signer(signingAlgorithm: .RS512, privateKey: privateKey)!
序列化
JWS 紧缩序列化是一个 URL 安全的字符串,可以方便地使用您选择的任何方法发送给第三方。
guard let jws = try? JWS(header: header, payload: payload, signer: signer) else { ... }
print(jws.compactSerializedString) // ey (...) J9.U3 (...) LU.na (...) 1A
有关构造 JWS 的更多详细信息,可以在 维基百科中找到。
验证数据
let publicKey: SecKey = /* ... */
let serialization = "ey (..) n0.HK (..) pQ.yS (..) PA.AK (..) Jx.hB (..) 7w"
do {
let jws = try JWS(compactSerialization: serialization)
let verifier = Verifier(verifyingAlgorithm: .RS512, publicKey: publicKey)!
let payload = try jws.validate(using: verifier).payload
let message = String(data: payload.data(), encoding: .utf8)!
print(message) // Summer ⛱, Sun ☀️, Cactus 🌵
}
有关验证现有序列化 JWS 的更多详细信息,可以在 维基百科中找到。
JWE:加密与解密
JWE通过对数据进行加密来封装并保护数据。它可以由JWE的接收者解密。
数据加密
为了构建一个JWE,我们需要提供以下部分:
- 头部
- 有效载荷
- 加密器
头部
let header = JWEHeader(keyManagementAlgorithm: .RSA1_5, contentEncryptionAlgorithm: .A256CBCHS512)
可选地,您可以设置其他参数
header.kid = "2018-10-08"
header.typ = "JWE"
有效载荷
let message = "Summer ⛱, Sun ☀️, Cactus 🌵".data(using: .utf8)!
let payload = Payload(message)
加密器
加密算法必须与头部算法匹配。
let publicKey: SecKey = /* ... */
let encrypter = Encrypter(keyManagementAlgorithm: .RSA1_5, contentEncryptionAlgorithm: .A256CBCHS512, encryptionKey: publicKey)!
请注意,提供的加密密钥类型必须与以下表中指定的密钥管理算法相匹配。
密钥管理算法 | 加密密钥类型 |
---|---|
RSA1_5 | SecKey |
RSAOAEP | SecKey |
RSAOAEP256 | SecKey |
A128KW | 数据 |
A192KW | 数据 |
A256KW | 数据 |
直接 | 数据 |
序列化
JWE 紧凑序列化是一种 URL 安全的字符串,您可以使用任意方法轻松将其传输给第三方。
guard let jwe = try? JWE(header: header, payload: payload, encrypter: encrypter) else { ... }
print(jwe.compactSerializedString) // ey (..) n0.HK (..) pQ.yS (..) PA.AK (..) Jx.hB (..) 7w
有关构建 JWE 的更多详细信息,请参阅 维基百科。
解密数据
let privateKey: SecKey = /* ... */
let serialization = "ey (..) n0.HK (..) pQ.yS (..) PA.AK (..) Jx.hB (..) 7w"
do {
let jwe = try JWE(compactSerialization: serialization)
let decrypter = Decrypter(keyManagementAlgorithm: .RSA1_5, contentEncryptionAlgorithm: .A256CBCHS512, decryptionKey: privateKey)!
let payload = try jwe.decrypt(using: decrypter)
let message = String(data: payload.data(), encoding: .utf8)!
print(message) // Summer ⛱, Sun ☀️, Cactus 🌵
}
有关解密现有序列化 JWE 的更多详细信息,请参阅 维基百科。
请注意,提供的解密密钥类型必须与以下表中指定的密钥管理算法相匹配。
密钥管理算法 | 解密密钥类型 |
---|---|
RSA1_5 | SecKey |
RSAOAEP | SecKey |
RSAOAEP256 | SecKey |
A128KW | 数据 |
A192KW | 数据 |
A256KW | 数据 |
直接 | 数据 |
JWK:表示密钥
JWK 是一种 JSON 数据结构,用于表示加密密钥。例如,您可以使用它将公钥作为 JWS 或 JWE的有效负载发送到服务器。
RSA 公钥编码
let publicKey: SecKey = /* ... */
let jwk = try! RSAPublicKey(publicKey: publicKey)
let json = jwk.jsonString()! // {"kty":"RSA","n":"MHZ4L...uS2d3","e":"QVFBQg"}
有关RSA公钥编码的更多细节可参见维基百科。
解码RSA公钥
let json: Data = /* ... */
let jwk = try! RSAPublicKey(data: json)
let publicKey: SecKey = try! jwk.converted(to: SecKey.self)
有关RSA公钥解码的更多细节可参见维基百科。
"key_ops"
和"x5c"
。这是因为我们解码实现中存在的一个错误。有关详细信息,请参阅#117。
安全
JOSESwift使用Apple的Security框架和Apple的CommonCrypto进行加密。
有关安全披露或相关事项,请联系[email protected]。
有关更多信息,请参阅我们的安全策略。
贡献
欢迎并向本项目的贡献,也非常欢迎。🤓
如果您想做出贡献,请提交拉取请求。要提出功能请求、进行讨论或报告错误,只需打开一个问题。
有关更多信息,请参阅我们的贡献指南。
资源
在相应的RFC中您可以找到有关相关JOSE标准的详细信息。
- RFC-7515: JSON Web签名 (JWS)
- RFC-7516: JSON Web加密 (JWE)
- RFC-7517: JSON Web密钥 (JWK)
- RFC-7518: JSON Web算法 (JWA)
不要忘了查看我们的wiki获取更详细的文档。
联系
欢迎通过[email protected]联系项目的维护人员。
鸣谢
JOSESwift由Airside Mobile维护。
项目作者和维护者
@carol-mohemian, @daniel-mohemian, @gigi-mohemian
审稿人
Logo
这个标志是由Ivan Leuzzi设计的。
感谢
以下项目在开发过程中为我们提供了参考和灵感
许可证
JOSESwift遵循Apache License 2.0许可。有关详细信息,请参阅LICENSE。