feat: jose

This commit is contained in:
2024-11-13 00:15:30 +08:00
parent 9b2c40d662
commit 2a9d6dfaac
4 changed files with 616 additions and 29 deletions

View File

@@ -2,6 +2,54 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "adler2"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aes"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
"cpufeatures",
"zeroize",
]
[[package]]
name = "aes-gcm-stream"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "163d1209787b2226543db17d317f5e9f5f54fd0d0f20834318f92013ebd78f37"
dependencies = [
"aes",
"cipher",
"ghash",
"zeroize",
]
[[package]]
name = "aes-kw"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c"
dependencies = [
"aes",
]
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
@@ -17,6 +65,12 @@ dependencies = [
"libc",
]
[[package]]
name = "anyhow"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775"
[[package]]
name = "autocfg"
version = "1.4.0"
@@ -57,6 +111,12 @@ dependencies = [
"serde_json",
]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "block-buffer"
version = "0.10.4"
@@ -105,6 +165,16 @@ dependencies = [
"windows-targets",
]
[[package]]
name = "cipher"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
dependencies = [
"crypto-common",
"inout",
]
[[package]]
name = "const-oid"
version = "0.9.6"
@@ -117,6 +187,24 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ca741a962e1b0bff6d724a1a0958b686406e853bb14061f218562e1896f95e6"
dependencies = [
"libc",
]
[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
[[package]]
name = "crypto-bigint"
version = "0.5.5"
@@ -156,6 +244,15 @@ dependencies = [
"zeroize",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.10.7"
@@ -167,6 +264,27 @@ dependencies = [
"crypto-common",
]
[[package]]
name = "dirs-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "elliptic-curve"
version = "0.13.8"
@@ -201,6 +319,31 @@ dependencies = [
"subtle",
]
[[package]]
name = "flate2"
version = "1.0.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0"
dependencies = [
"crc32fast",
"miniz_oxide",
]
[[package]]
name = "foreign-types"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
dependencies = [
"foreign-types-shared",
]
[[package]]
name = "foreign-types-shared"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
[[package]]
name = "generic-array"
version = "0.14.7"
@@ -223,6 +366,16 @@ dependencies = [
"wasi",
]
[[package]]
name = "ghash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
"polyval",
]
[[package]]
name = "group"
version = "0.13.0"
@@ -273,6 +426,15 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "inout"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
dependencies = [
"generic-array",
]
[[package]]
name = "itoa"
version = "1.0.11"
@@ -325,16 +487,37 @@ dependencies = [
name = "jose-test"
version = "0.1.0"
dependencies = [
"aes-gcm-stream",
"aes-kw",
"base64",
"biscuit",
"jose-jwe",
"jose-jwk",
"josekit",
"rand",
"rsa",
"rust_util",
"serde",
"serde_json",
]
[[package]]
name = "josekit"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a603084e34e151e215d232e401df0d9299bdced264b8054e4888ea614e59bb06"
dependencies = [
"anyhow",
"base64",
"flate2",
"openssl",
"regex",
"serde",
"serde_json",
"thiserror",
"time",
]
[[package]]
name = "js-sys"
version = "0.3.72"
@@ -365,6 +548,16 @@ version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
]
[[package]]
name = "log"
version = "0.4.22"
@@ -377,6 +570,15 @@ version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1"
dependencies = [
"adler2",
]
[[package]]
name = "num-bigint"
version = "0.4.6"
@@ -404,6 +606,12 @@ dependencies = [
"zeroize",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-integer"
version = "0.1.46"
@@ -440,6 +648,50 @@ version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "opaque-debug"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
[[package]]
name = "openssl"
version = "0.10.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5"
dependencies = [
"bitflags",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
"openssl-macros",
"openssl-sys",
]
[[package]]
name = "openssl-macros"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "openssl-sys"
version = "0.9.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741"
dependencies = [
"cc",
"libc",
"pkg-config",
"vcpkg",
]
[[package]]
name = "p256"
version = "0.13.2"
@@ -490,6 +742,30 @@ dependencies = [
"spki",
]
[[package]]
name = "pkg-config"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "polyval"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures",
"opaque-debug",
"universal-hash",
]
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.20"
@@ -556,6 +832,46 @@ dependencies = [
"getrandom",
]
[[package]]
name = "redox_users"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "ring"
version = "0.17.8"
@@ -591,6 +907,24 @@ dependencies = [
"zeroize",
]
[[package]]
name = "rust_util"
version = "0.6.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bca5d3493eb29d08dc76ee784a78723fe366fec5dfe67ab37da9d50fb868f7c"
dependencies = [
"lazy_static",
"libc",
"term",
"term_size",
]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ryu"
version = "1.0.18"
@@ -698,6 +1032,66 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "term"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f"
dependencies = [
"dirs-next",
"rustversion",
"winapi",
]
[[package]]
name = "term_size"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e4129646ca0ed8f45d09b929036bafad5377103edd06e50bf574b353d2b08d9"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"num-conv",
"powerfmt",
"serde",
"time-core",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "typenum"
version = "1.17.0"
@@ -710,12 +1104,28 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
[[package]]
name = "universal-hash"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
dependencies = [
"crypto-common",
"subtle",
]
[[package]]
name = "untrusted"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
version = "0.9.5"
@@ -783,6 +1193,28 @@ version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.52.0"
@@ -893,4 +1325,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
dependencies = [
"serde",
"zeroize_derive",
]
[[package]]
name = "zeroize_derive"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

View File

@@ -4,11 +4,15 @@ version = "0.1.0"
edition = "2021"
[dependencies]
aes-gcm-stream = "0.2.3"
aes-kw = { version = "0.2.1", features = ["alloc"] }
base64 = "0.22.1"
biscuit = "0.7.0"
jose-jwe = "0.0.0"
jose-jwk = { version = "0.1.2", features = ["rsa"] }
josekit = "0.10.0"
rand = { version = "0.8.5", features = [] }
rsa = "0.9.6"
rust_util = "0.6.47"
serde = "1.0.214"
serde_json = "1.0.132"

View File

@@ -0,0 +1,153 @@
use aes_gcm_stream::Aes256GcmStreamEncryptor;
use aes_kw::Kek;
use base64::engine::general_purpose::URL_SAFE_NO_PAD;
use base64::Engine;
use josekit::jwe;
use josekit::jwe::alg::aeskw::AeskwJweAlgorithm;
use josekit::jwe::alg::rsaes::RsaesJweAlgorithm;
use josekit::jwe::JweHeader;
use josekit::jwk::alg::rsa::RsaKeyPair;
use josekit::jwk::Jwk;
use rand::random;
use rand::rngs::OsRng;
use rsa::RsaPrivateKey;
use rust_util::XResult;
use serde::Serialize;
use serde_json::Value;
const LOCAL_KMS_PREFIX: &str = "LKMS:";
// JWE format:
// BASE64URL(UTF8(JWE Protected Header)) || '.' ||
// BASE64URL(JWE Encrypted Key) || '.' || BASE64URL(JWE Initialization Vector)
// || '.' || BASE64URL(JWE Ciphertext) || '.' || BASE64URL(JWE Authentication Tag).
//
// RSA JWE Header:
// {"enc":"A256GCM","vendor":"local-mini-kms","alg":"RSA-OAEP"}
// eyJlbmMiOiJBMjU2R0NNIiwidmVuZG9yIjoibG9jYWwtbWluaS1rbXMiLCJhbGciOiJSU0EtT0FFUCJ9.VQ_R
// yGjXqQlUIbRIMgaYRSaX5FMRBzZ6ApfdZ2yAwiG70hjNfR3ss7x4PYqMm6QtITm1O4_fp7I3bY8iUz5Njyth_
// Min7Xm2-WsQ6gq9yN58btkUBFm60c7SC5XLaqE1pEtBAz7786bJk6M4NeOtDAOFAmIb2j1EwnS5vweBtmNv7N
// UFIgvx806T3WkCFDOkMSJ10_6LSa0z-lIac-s68svsU5WW8CXVKxHAbxaHyX_otu2HxXzDZlF5Goamh5ZJtr0
// 0yW_bzDCx3hZ2nMK3Ve7IJ2ZLAMmvhj9LKWkPtoqH0dGHaPHWff5P3rZ4vtKywt_h5b6SYII_mEoJcpByMyGw
// TXCtZymDt82Tyv_FesW2721JgyGxnukuOxQRTw4MfGYIO5bldL3uGGI_H4HXlXhM_kp3wuPAZ0vH4Jj2KD6MV
// DDTJQaEBQIEF07i7WiNynr57kbahYwextRXYP7LgoUHfFwA5GGGpN-UkuWLlKkYLTmXGrPYnL6Cf9D3euP7nF
// ml2oA2hjig-UuYf9A_QSEqNsMxYDuG-rggn3H_iXNl4ooYcxSVOXhTKfoV578MkNwG75BdHN5FeRYIKq0HCTM
// lGqqBWmDibPtMd7Uq1JrDd8774lnA8JcZcCMSia4m6WJSbG0kOuJ4NJPOUrYtNEJXgWKU3FQzDB-apLMQdac.
// WYJgsdZRLk310KWd.P333-S2VYg.PCfruTdk8vh3a8wcjJCe-g
//
// RSA-OAEP RSA using Optimal Asymmetric Encryption Padding (OAEP), as defined in RFC 3447 [RFC3447]
// A256GCM Advanced Encryption Standard (AES) using 256 bit keys in Galois/Counter Mode, as defined in [FIPS197] and [NIST80038D]
//
// AES JWE Header:
// {"enc":"A256GCM","vendor":"local-mini-kms","version":"5b90f66a1c6a918d","alg":"A256KW"}
// eyJlbmMiOiJBMjU2R0NNIiwidmVuZG9yIjoibG9jYWwtbWluaS1rbXMiLCJ2ZXJzaW9uIjoiNWI5MGY2NmExYz
// ZhOTE4ZCIsImFsZyI6IkEyNTZLVyJ9.K2_P-b_Gq9wbrssbcS5AmiUwcnNTnnZSe7rBI1SixVrC7TfFK0fruw.
// ez3OKjOHAIIYnfM0.wSO3aXo.-vGJwk8JQKhi3voIlAA9gQ
//
// A256GCM Advanced Encryption Standard (AES) using 256 bit keys in Galois/Counter Mode, as defined in [FIPS197] and [NIST80038D]
// A256KW Advanced Encryption Standard (AES) Key Wrap Algorithm using 256 bit keys, as defined in RFC 3394 [RFC3394]
pub fn generate_rsa_key_2(bits: u32) -> XResult<RsaPrivateKey> {
let mut rng = OsRng::default();
Ok(RsaPrivateKey::new(&mut rng, bits as usize)?)
}
pub fn generate_rsa_key(bits: u32) -> XResult<RsaKeyPair> {
Ok(RsaKeyPair::generate(bits)?)
}
pub fn serialize_jwe_rsa_2(payload: &[u8], jwk: &Jwk) {
// TODO ...
}
pub fn serialize_jwe_rsa(payload: &[u8], jwk: &Jwk) -> XResult<String> {
let mut header = JweHeader::new();
header.set_content_encryption("A256GCM");
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
let encrypter = RsaesJweAlgorithm::RsaOaep.encrypter_from_jwk(jwk)?;
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
}
pub fn deserialize_jwe_rsa(jwe: &str, jwk: &Jwk) -> XResult<(Vec<u8>, JweHeader)> {
let decrypter = RsaesJweAlgorithm::RsaOaep.decrypter_from_jwk(jwk)?;
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
}
// JWE Header: {"alg":"dir","enc":"A256GCM"}
// Encrypted key (CEK): (blank)
// IV: Vlf_WdLm-spHbfJe
// Ciphertext: RxMPrw
// Authentication Tag: 5VC8Y_qSPdSubbGNGyfn6A
//
// JWE Header: {"alg":"A256KW","enc":"A256GCM"}
// Encrypted key (CEK): 66xZoxFI18zfvLMO6WU1zzqqX1tT8xu_qZzMQyPcfVuajPNkOJUXQA
// IV: X5ZL8yaOektXmfny
// Ciphertext: brz-Lg
// Authentication Tag: xG-EvM-9hrw0XRiuRW7HrA
//
// https://security.stackexchange.com/questions/80966/what-is-the-point-of-aes-key-wrap-with-json-web-encryption
#[derive(Serialize)]
struct JweHeader2 {
pub enc: String,
pub alg: String,
pub vendor: String,
}
pub fn serialize_jwe_aes_2(payload: &[u8], key: [u8; 32]) -> XResult<String> {
let header = JweHeader2 {
enc: "A256GCM".to_string(),
alg: "A256KW".to_string(),
vendor: "local-mini-kms".to_string(),
};
let header_str = serde_json::to_string(&header).unwrap();
let header_b64 = URL_SAFE_NO_PAD.encode(header_str.as_bytes());
// let key: [u8; 32] = key.into();
let data_key: [u8; 32] = random();
let nonce: [u8; 12] = random();
let mut encryptor = Aes256GcmStreamEncryptor::new(data_key, &nonce);
encryptor.init_adata(header_b64.as_bytes());
let mut e = encryptor.update(payload);
let (f, t) = encryptor.finalize();
e.extend_from_slice(&f);
let kek = Kek::from(key);
let wrap_key = kek.wrap_vec(&data_key[..]).unwrap();
let mut jwe = String::new();
jwe.push_str(&header_b64);
jwe.push_str(".");
jwe.push_str(&URL_SAFE_NO_PAD.encode(&wrap_key));
jwe.push_str(".");
jwe.push_str(&URL_SAFE_NO_PAD.encode(&nonce));
jwe.push_str(".");
jwe.push_str(&URL_SAFE_NO_PAD.encode(&e));
jwe.push_str(".");
jwe.push_str(&URL_SAFE_NO_PAD.encode(&t));
Ok(jwe)
}
pub fn serialize_jwe_aes(payload: &[u8], key: &[u8]) -> XResult<String> {
let mut header = JweHeader::new();
header.set_content_encryption("A256GCM");
header.set_claim("vendor", Some(Value::String("local-mini-kms".to_string())))?;
// header.set_claim("version", Some(Value::String(get_master_key_checksum(key))))?;
let encrypter = AeskwJweAlgorithm::A256kw.encrypter_from_bytes(key)?;
Ok(format!("{}{}", LOCAL_KMS_PREFIX, jwe::serialize_compact(payload, &header, &encrypter)?))
}
pub fn deserialize_jwe_aes(jwe: &str, key: &[u8]) -> XResult<(Vec<u8>, JweHeader)> {
let decrypter = AeskwJweAlgorithm::A256kw.decrypter_from_bytes(key)?;
Ok(jwe::deserialize_compact(&get_jwe(jwe), &decrypter)?)
}
fn get_jwe(jwe: &str) -> String {
if jwe.starts_with(LOCAL_KMS_PREFIX) {
jwe.chars().skip(LOCAL_KMS_PREFIX.len()).collect()
} else {
jwe.to_string()
}
}

View File

@@ -1,41 +1,27 @@
mod jose;
use base64::Engine;
use jose_jwk::jose_b64::serde::Bytes;
use jose_jwk::Rsa;
use rand::random;
use rand::rngs::ThreadRng;
use rsa::Pkcs1v15Encrypt;
use serde_json::Value;
use crate::jose::{deserialize_jwe_aes, serialize_jwe_aes_2};
fn main() {
// JWE format:
// BASE64URL(UTF8(JWE Protected Header)) || '.' ||
// BASE64URL(JWE Encrypted Key) || '.' || BASE64URL(JWE Initialization Vector)
// || '.' || BASE64URL(JWE Ciphertext) || '.' || BASE64URL(JWE Authentication Tag).
//
// RSA JWE Header:
// {"enc":"A256GCM","vendor":"local-mini-kms","alg":"RSA-OAEP"}
// eyJlbmMiOiJBMjU2R0NNIiwidmVuZG9yIjoibG9jYWwtbWluaS1rbXMiLCJhbGciOiJSU0EtT0FFUCJ9.VQ_R
// yGjXqQlUIbRIMgaYRSaX5FMRBzZ6ApfdZ2yAwiG70hjNfR3ss7x4PYqMm6QtITm1O4_fp7I3bY8iUz5Njyth_
// Min7Xm2-WsQ6gq9yN58btkUBFm60c7SC5XLaqE1pEtBAz7786bJk6M4NeOtDAOFAmIb2j1EwnS5vweBtmNv7N
// UFIgvx806T3WkCFDOkMSJ10_6LSa0z-lIac-s68svsU5WW8CXVKxHAbxaHyX_otu2HxXzDZlF5Goamh5ZJtr0
// 0yW_bzDCx3hZ2nMK3Ve7IJ2ZLAMmvhj9LKWkPtoqH0dGHaPHWff5P3rZ4vtKywt_h5b6SYII_mEoJcpByMyGw
// TXCtZymDt82Tyv_FesW2721JgyGxnukuOxQRTw4MfGYIO5bldL3uGGI_H4HXlXhM_kp3wuPAZ0vH4Jj2KD6MV
// DDTJQaEBQIEF07i7WiNynr57kbahYwextRXYP7LgoUHfFwA5GGGpN-UkuWLlKkYLTmXGrPYnL6Cf9D3euP7nF
// ml2oA2hjig-UuYf9A_QSEqNsMxYDuG-rggn3H_iXNl4ooYcxSVOXhTKfoV578MkNwG75BdHN5FeRYIKq0HCTM
// lGqqBWmDibPtMd7Uq1JrDd8774lnA8JcZcCMSia4m6WJSbG0kOuJ4NJPOUrYtNEJXgWKU3FQzDB-apLMQdac.
// WYJgsdZRLk310KWd.P333-S2VYg.PCfruTdk8vh3a8wcjJCe-g
//
// RSA-OAEP RSA using Optimal Asymmetric Encryption Padding (OAEP), as defined in RFC 3447 [RFC3447]
// A256GCM Advanced Encryption Standard (AES) using 256 bit keys in Galois/Counter Mode, as defined in [FIPS197] and [NIST80038D]
//
// AES JWE Header:
// {"enc":"A256GCM","vendor":"local-mini-kms","version":"5b90f66a1c6a918d","alg":"A256KW"}
// eyJlbmMiOiJBMjU2R0NNIiwidmVuZG9yIjoibG9jYWwtbWluaS1rbXMiLCJ2ZXJzaW9uIjoiNWI5MGY2NmExYz
// ZhOTE4ZCIsImFsZyI6IkEyNTZLVyJ9.K2_P-b_Gq9wbrssbcS5AmiUwcnNTnnZSe7rBI1SixVrC7TfFK0fruw.
// ez3OKjOHAIIYnfM0.wSO3aXo.-vGJwk8JQKhi3voIlAA9gQ
//
// A256GCM Advanced Encryption Standard (AES) using 256 bit keys in Galois/Counter Mode, as defined in [FIPS197] and [NIST80038D]
// A256KW Advanced Encryption Standard (AES) Key Wrap Algorithm using 256 bit keys, as defined in RFC 3394 [RFC3394]
let key: [u8; 32] = random();
let payload = b"hello world";
let e = serialize_jwe_aes_2(payload, key).unwrap();
println!("{}", e);
let (d, h) = deserialize_jwe_aes(&e, &key).unwrap();
println!("{:?}", d);
println!("{:?}", h);
}
fn main2() {
let rsa_jwk = r##"{
"kty":"RSA",
"e":"AQAB",