diff --git a/Cargo.lock b/Cargo.lock index 89bb834..982530c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "android_system_properties" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +dependencies = [ + "libc", +] + [[package]] name = "atty" version = "0.2.14" @@ -40,6 +49,12 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "base64ct" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdca834647821e0b13d9539a8634eb62d3501b6b6c2cec1722786ee6671b851" + [[package]] name = "bindgen" version = "0.60.1" @@ -69,6 +84,27 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "block-buffer" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + [[package]] name = "cc" version = "1.0.73" @@ -92,15 +128,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.19" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1" dependencies = [ - "libc", + "iana-time-zone", + "js-sys", "num-integer", "num-traits", "serde", "time", + "wasm-bindgen", "winapi", ] @@ -117,9 +155,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "3.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" dependencies = [ "atty", "bitflags", @@ -132,13 +170,40 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] +[[package]] +name = "const-oid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" + +[[package]] +name = "const-oid" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "722e23542a15cea1f65d4a1419c4cfd7a26706c70871a13a04238ca3f40f1661" + +[[package]] +name = "core-foundation-sys" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" + +[[package]] +name = "cpufeatures" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1079fb8528d9f9c888b1e8aa651e6e079ade467323d58f75faf1d30b1808f540" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.3.2" @@ -148,6 +213,26 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crypto-bigint" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c6a1d5fa1de37e071642dfa44ec552ca5b299adb128fab16138e24b548fd21" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "darling" version = "0.14.1" @@ -189,6 +274,42 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" +[[package]] +name = "der" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6919815d73839e7ad218de758883aae3a257ba6759ce7a9992501efbb53d705c" +dependencies = [ + "const-oid 0.7.1", + "crypto-bigint", + "pem-rfc7468 0.3.1", +] + +[[package]] +name = "der" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f" +dependencies = [ + "const-oid 0.9.0", + "der_derive", + "flagset", + "pem-rfc7468 0.6.0", + "zeroize", +] + +[[package]] +name = "der_derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e0925824edd2cc2de26da32852c7cd30844011dbf4956c12c88ad2f42d910" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "derive_builder" version = "0.11.2" @@ -220,6 +341,24 @@ dependencies = [ "syn", ] +[[package]] +name = "digest" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" +dependencies = [ + "generic-array", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "crypto-common", +] + [[package]] name = "doc-comment" version = "0.3.3" @@ -228,9 +367,9 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "either" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "env_logger" @@ -245,6 +384,12 @@ dependencies = [ "termcolor", ] +[[package]] +name = "flagset" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda653ca797810c02f7ca4b804b40b8b95ae046eb989d356bce17919a8c25499" + [[package]] name = "flate2" version = "1.0.24" @@ -286,15 +431,25 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "generic-array" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if", "libc", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", ] [[package]] @@ -305,9 +460,9 @@ checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" @@ -330,6 +485,19 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "iana-time-zone" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "js-sys", + "wasm-bindgen", + "winapi", +] + [[package]] name = "ident_case" version = "1.0.1" @@ -349,19 +517,31 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", ] +[[package]] +name = "js-sys" +version = "0.3.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin", +] [[package]] name = "lazycell" @@ -371,9 +551,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libloading" @@ -385,6 +565,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "libm" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" + [[package]] name = "libxml" version = "0.3.1" @@ -442,6 +628,23 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566d173b2f9406afbc5510a90925d5a2cd80cae4605631f1212303df265de011" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -452,6 +655,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -459,19 +673,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ "autocfg", + "libm", ] [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" + +[[package]] +name = "opaque-debug" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if", @@ -501,9 +722,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg", "cc", @@ -514,9 +735,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" [[package]] name = "peeking_take_while" @@ -524,12 +745,52 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" +[[package]] +name = "pem-rfc7468" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01de5d978f34aa4b2296576379fcc416034702fd94117c56ffd8a1a767cefb30" +dependencies = [ + "base64ct", +] + +[[package]] +name = "pem-rfc7468" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac" +dependencies = [ + "base64ct", +] + [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +[[package]] +name = "pkcs1" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a78f66c04ccc83dd4486fd46c33896f4e17b24a7a3a6400dedc48ed0ddd72320" +dependencies = [ + "der 0.5.1", + "pkcs8", + "zeroize", +] + +[[package]] +name = "pkcs8" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cabda3fb821068a9a4fab19a683eac3af12edf0f34b94a8be53c4972b8149d0" +dependencies = [ + "der 0.5.1", + "spki 0.5.4", + "zeroize", +] + [[package]] name = "pkg-config" version = "0.3.25" @@ -542,20 +803,44 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.23.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9279fbdacaad3baf559d8cabe0acc3d06e30ea14931af31af79578ac0946decc" +checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b" dependencies = [ "memchr", "serde", @@ -563,9 +848,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] @@ -602,9 +887,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -613,9 +898,29 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" + +[[package]] +name = "rsa" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "4cf22754c49613d2b3b119f0e5d46e34a2c628a937e3024b8762de4e7d8c710b" +dependencies = [ + "byteorder", + "digest 0.10.3", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "smallvec", + "subtle", + "zeroize", +] [[package]] name = "rustc-hash" @@ -642,38 +947,60 @@ dependencies = [ "pkg-config", "quick-xml", "rand", + "rsa", "serde", + "sha2", "snafu", "url", "uuid", + "x509-cert", ] [[package]] name = "serde" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", "syn", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer", + "cfg-if", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "shlex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +[[package]] +name = "smallvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" + [[package]] name = "snafu" version = "0.7.1" @@ -696,17 +1023,49 @@ dependencies = [ "syn", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "spki" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d01ac02a6ccf3e07db148d2be087da624fea0221a16152ed01f0496a6b0a27" +dependencies = [ + "base64ct", + "der 0.5.1", +] + +[[package]] +name = "spki" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" +dependencies = [ + "base64ct", + "der 0.6.0", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subtle" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" + [[package]] name = "syn" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", @@ -730,11 +1089,12 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi", ] @@ -753,6 +1113,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +[[package]] +name = "typenum" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" + [[package]] name = "unicode-bidi" version = "0.3.8" @@ -761,15 +1127,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] @@ -801,11 +1167,77 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" [[package]] name = "which" @@ -848,3 +1280,21 @@ 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 = "x509-cert" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd27a832a85efcf56cad058e4e3256d1781b927e113a9e37d96916d639e4af7" +dependencies = [ + "const-oid 0.9.0", + "der 0.6.0", + "flagset", + "spki 0.6.0", +] + +[[package]] +name = "zeroize" +version = "1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f" diff --git a/Cargo.toml b/Cargo.toml index 7d21818..a1e5e25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ build = "bindings.rs" doctest = false [features] +default = ["openssl"] +openssl = ["dep:openssl", "openssl-sys", "openssl-probe"] +rustcrypto = ["rsa", "sha2", "x509-cert"] xmlsec = ["libc", "lazy_static", "libxml"] [build-dependencies] @@ -23,20 +26,27 @@ pkg-config = "^0.3.17" bindgen = "^0.60.1" [dependencies] -openssl = "0.10" -openssl-sys = "0.9" -openssl-probe = "0.1.2" -url = "2.1.1" -quick-xml = { version = "0.23.0", features = [ "serialize" ] } -serde = { version = "1.0", features = ["derive"] } -chrono = { version = "0.4", features = ["serde"] } base64 = "0.13" -flate2 = "1.0" -snafu = "0.7" -rand = "0.8.4" +chrono = { version = "0.4", features = ["serde"] } +data-encoding = "2.2.0" derive_builder = "0.11.2" +flate2 = "1.0" +lazy_static = {version = "^1.4.0", optional = true} +libc = {version = "^0.2.66", optional = true} libxml = { version = "0.3.0", optional = true} +quick-xml = { version = "0.22.0", features = [ "serialize" ] } +rand = "0.8.4" +serde = { version = "1.0", features = ["derive"] } +snafu = "0.7" +url = "2.1.1" uuid = { version = ">=0.8.0, <2.0.0", features = [ "v4" ] } -data-encoding = "2.2.0" -libc = {version = "^0.2.66", optional = true} -lazy_static = {version = "^1.4.0", optional = true} + +# openssl +openssl = { version = "0.10", optional = true } +openssl-probe = { version = "0.1.2", optional = true } +openssl-sys = { version = "0.9", optional = true } + +# rustcrypto +rsa = { version = "0.6.1", optional = true } +sha2 = { version = "0.9", optional = true } +x509-cert = { version = "^0.1.0", features = [ "pem", "std" ], optional = true } \ No newline at end of file diff --git a/src/bindings.rs b/src/bindings.rs index 7a59f64..c00fcea 100644 --- a/src/bindings.rs +++ b/src/bindings.rs @@ -5,7 +5,6 @@ #![allow(non_snake_case)] #![allow(non_camel_case_types)] #![allow(non_upper_case_globals)] - #![allow(improper_ctypes)] include!(concat!(env!("OUT_DIR"), "/bindings.rs")); diff --git a/src/crypto.rs b/src/crypto/mod.rs similarity index 94% rename from src/crypto.rs rename to src/crypto/mod.rs index e9f9a82..609d777 100644 --- a/src/crypto.rs +++ b/src/crypto/mod.rs @@ -1,3 +1,4 @@ +use crate::crypto::x509::CertificateLike; use std::collections::HashMap; use std::convert::TryInto; use std::ffi::CString; @@ -5,11 +6,22 @@ use std::str::FromStr; use snafu::Snafu; +#[cfg(not(any(feature = "rustcrypto", feature = "openssl")))] +compile_error!("No crypto backend is enabled! Please enable either rustcrypto or openssl."); + +#[cfg(all(feature = "rustcrypto", feature = "openssl"))] +compile_error!("Only one crypto backend may be enabled!"); + +pub mod rsa; +pub mod x509; + #[cfg(feature = "xmlsec")] use crate::xmlsec::{self, XmlSecKey, XmlSecKeyFormat, XmlSecSignatureContext}; #[cfg(feature = "xmlsec")] use libxml::parser::Parser as XmlParser; +use self::rsa::PublicKeyLike; + #[cfg(feature = "xmlsec")] const XMLNS_XML_DSIG: &str = "http://www.w3.org/2000/09/xmldsig#"; #[cfg(feature = "xmlsec")] @@ -54,7 +66,7 @@ pub enum Error { error: Box, }, - #[cfg(feature = "xmlsec")] + #[cfg(all(feature = "xmlsec", feature = "openssl"))] #[snafu(display("OpenSSL error stack: {}", error))] OpenSSLError { error: openssl::error::ErrorStack, @@ -81,7 +93,7 @@ impl From for Error { } } -#[cfg(feature = "xmlsec")] +#[cfg(all(feature = "xmlsec", feature = "openssl"))] impl From for Error { fn from(error: openssl::error::ErrorStack) -> Self { Error::OpenSSLError { error } @@ -422,7 +434,7 @@ fn remove_unverified_elements(node: &mut libxml::tree::Node) { #[cfg(feature = "xmlsec")] pub(crate) fn reduce_xml_to_signed( xml_str: &str, - certs: &[openssl::x509::X509], + certs: &[x509::Certificate], ) -> Result { let mut xml = XmlParser::default().parse_string(xml_str)?; let mut root_elem = xml.get_root_element().ok_or(Error::XmlMissingRootElement)?; @@ -436,8 +448,8 @@ pub(crate) fn reduce_xml_to_signed( for sig_node in signature_nodes.drain(..) { let mut sig_ctx = XmlSecSignatureContext::new()?; let mut verified = false; - for openssl_key in certs { - let key_data = openssl_key.to_der()?; + for cert in certs { + let key_data = cert.public_key(); let key = XmlSecKey::from_memory(&key_data, XmlSecKeyFormat::CertDer)?; sig_ctx.insert_key(key); verified = sig_ctx.verify_node(&sig_node)?; @@ -528,34 +540,31 @@ pub enum UrlVerifierError { SigAlgUnimplemented { sigalg: String }, } -pub struct UrlVerifier { - keypair: openssl::pkey::PKey, +pub struct UrlVerifier +where + PublicKey: rsa::PublicKeyLike, +{ + keypair: PublicKey, } -impl UrlVerifier { +impl UrlVerifier { pub fn from_rsa_pem(public_key_pem: &[u8]) -> Result> { - let public = openssl::rsa::Rsa::public_key_from_pem(public_key_pem)?; - let keypair = openssl::pkey::PKey::from_rsa(public)?; + let keypair = rsa::PublicKeyLike::from_pem(public_key_pem)?; Ok(Self { keypair }) } pub fn from_rsa_der(public_key_der: &[u8]) -> Result> { - let public = openssl::rsa::Rsa::public_key_from_der(public_key_der)?; - let keypair = openssl::pkey::PKey::from_rsa(public)?; + let keypair = rsa::PublicKeyLike::from_der(public_key_der)?; Ok(Self { keypair }) } - pub fn from_x509_cert_pem(public_cert_pem: &str) -> Result> { - let x509 = openssl::x509::X509::from_pem(public_cert_pem.as_bytes())?; - let keypair = x509.public_key()?; - Ok(Self { keypair }) + pub fn from_x509(public_cert: &x509::Certificate) -> Result> { + Self::from_rsa_der(public_cert.public_key()) } - pub fn from_x509( - public_cert: &openssl::x509::X509, - ) -> Result> { - let keypair = public_cert.public_key()?; - Ok(Self { keypair }) + pub fn from_x509_cert_pem(public_cert_pem: &str) -> Result> { + let x509 = x509::CertificateLike::from_der(public_cert_pem.as_bytes())?; + Self::from_x509(&x509) } // Signed url should look like: @@ -674,20 +683,10 @@ impl UrlVerifier { fn verify_signature( &self, data: &[u8], - sig_alg: SigAlg, + _sig_alg: SigAlg, signature: &[u8], ) -> Result> { - let mut verifier = openssl::sign::Verifier::new( - match sig_alg { - SigAlg::RsaSha256 => openssl::hash::MessageDigest::sha256(), - _ => panic!("sig_alg is bad!"), - }, - &self.keypair, - )?; - - verifier.update(data)?; - - Ok(verifier.verify(signature)?) + Ok(self.keypair.verify_sha256(signature, data)?) } } diff --git a/src/crypto/rsa/mod.rs b/src/crypto/rsa/mod.rs new file mode 100644 index 0000000..3445972 --- /dev/null +++ b/src/crypto/rsa/mod.rs @@ -0,0 +1,41 @@ +#[cfg(feature = "openssl")] +mod openssl; +#[cfg(feature = "openssl")] +pub use self::openssl::*; + +#[cfg(feature = "rustcrypto")] +mod rustcrypto; +#[cfg(feature = "rustcrypto")] +pub use rustcrypto::*; + +pub trait PrivateKeyLike +where + Self: Sized, +{ + fn new(bit_size: usize) -> Result>; + + fn from_pem(pem: &str) -> Result>; + + fn from_der(der: &[u8]) -> Result>; + + fn to_der(&self) -> Result, Box>; + + fn sign_sha256(&self, content_to_sign: String) -> Result, Box>; +} + +pub trait PublicKeyLike +where + Self: Sized, +{ + fn from_pem(pem: &[u8]) -> Result>; + + fn from_der(der: &[u8]) -> Result>; + + fn to_der(&self) -> Result, Box>; + + fn verify_sha256( + &self, + signature: &[u8], + data: &[u8], + ) -> Result>; +} diff --git a/src/crypto/rsa/openssl.rs b/src/crypto/rsa/openssl.rs new file mode 100644 index 0000000..629cdab --- /dev/null +++ b/src/crypto/rsa/openssl.rs @@ -0,0 +1,64 @@ +use openssl::hash::MessageDigest; +use openssl::pkey::{PKey, Private, Public}; +use openssl::rsa::Rsa; +use openssl::sign::Signer; +use openssl::sign::Verifier; + +use crate::crypto::rsa::{PrivateKeyLike, PublicKeyLike}; + +pub type PrivateKey = Rsa; +pub type PublicKey = Rsa; + +impl PrivateKeyLike for PrivateKey { + fn new(bit_size: usize) -> Result> { + Ok(Self::generate(bit_size as u32)?) + } + + fn from_pem(pem: &str) -> Result> { + Ok(Self::private_key_from_pem(pem.as_bytes())?) + } + + fn from_der(der: &[u8]) -> Result> { + Ok(Self::private_key_from_der(der)?) + } + + fn to_der(&self) -> Result, Box> { + Ok(self.to_pkcs8_der()?.as_ref().to_vec()) + } + + fn sign_sha256(&self, content_to_sign: String) -> Result, Box> { + let pkey = PKey::from_rsa(self.0)?; + + let mut signer = Signer::new(MessageDigest::sha256(), pkey.as_ref())?; + + signer.update(content_to_sign.as_bytes())?; + + Ok(signer.sign_to_vec()?) + } +} + +impl PublicKeyLike for PublicKey { + fn from_pem(pem: &[u8]) -> Result> { + Ok(Rsa::public_key_from_pem(pem)?) + } + + fn from_der(der: &[u8]) -> Result> { + Ok(Rsa::public_key_from_der(der)?) + } + + fn to_der(&self) -> Result, Box> { + Ok(self.0.to_public_key_der()?.as_ref().to_vec()) + } + + fn verify_sha256( + &self, + signature: &[u8], + data: &[u8], + ) -> Result> { + let mut verifier = Verifier::new(MessageDigest::sha256(), self.0)?; + + verifier.update(data)?; + + Ok(verifier.verify(signature)?) + } +} diff --git a/src/crypto/rsa/rustcrypto.rs b/src/crypto/rsa/rustcrypto.rs new file mode 100644 index 0000000..d547be8 --- /dev/null +++ b/src/crypto/rsa/rustcrypto.rs @@ -0,0 +1,69 @@ +// use rsa::pkcs1::{TryFrom, RsaPrivateKey as FromRsaPrivateKey, RsaPublicKey as FromRsaPublicKey}; +// use rsa::pkcs8::PublicKey; +use rsa::{ + pkcs1::{DecodeRsaPrivateKey, DecodeRsaPublicKey}, + pkcs8::{DecodePrivateKey, DecodePublicKey, EncodePrivateKey, EncodePublicKey}, +}; + +use rsa::{Hash, PaddingScheme, PublicKey as FromPublicKey}; +use sha2::{Digest, Sha256}; + +use super::{PrivateKeyLike, PublicKeyLike}; + +pub use rsa::RsaPrivateKey as PrivateKey; +pub use rsa::RsaPublicKey as PublicKey; + +impl PrivateKeyLike for PrivateKey { + fn new(bit_size: usize) -> Result> { + let mut rng = rand::thread_rng(); + + Ok(PrivateKey::new(&mut rng, bit_size)?) + } + + fn from_pem(pem: &str) -> Result> { + Ok(Self::from_pkcs8_pem(pem).or_else(|_| Self::from_pkcs1_pem(pem))?) + } + + fn from_der(der: &[u8]) -> Result> { + Ok(Self::from_pkcs8_der(der).or_else(|_| Self::from_pkcs1_der(der))?) + } + + fn to_der(&self) -> Result, Box> { + Ok(self.to_pkcs8_der()?.as_ref().to_vec()) + } + + fn sign_sha256(&self, content_to_sign: String) -> Result, Box> { + let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256)); + let hashed = Sha256::digest(content_to_sign.as_bytes()); + let signature = self.sign(padding, &hashed[..])?; + + Ok(signature) + } +} + +impl PublicKeyLike for PublicKey { + fn from_pem(pem: &[u8]) -> Result> { + Ok(Self::from_public_key_pem(std::str::from_utf8(pem)?) + .or_else(|_| Self::from_pkcs1_der(pem))?) + } + + fn from_der(der: &[u8]) -> Result> { + Ok(Self::from_public_key_der(der).or_else(|_| Self::from_pkcs1_der(der))?) + } + + fn to_der(&self) -> Result, Box> { + Ok(self.to_public_key_der()?.as_ref().to_vec()) + } + + fn verify_sha256( + &self, + signature: &[u8], + data: &[u8], + ) -> Result> { + let padding = PaddingScheme::new_pkcs1v15_sign(Some(Hash::SHA2_256)); + + self.verify(padding, data, signature)?; + + Ok(true) + } +} diff --git a/src/crypto/x509/mod.rs b/src/crypto/x509/mod.rs new file mode 100644 index 0000000..e85bfc8 --- /dev/null +++ b/src/crypto/x509/mod.rs @@ -0,0 +1,28 @@ +use crate::crypto::rsa; +use crate::idp::CertificateParams; + +#[cfg(feature = "openssl")] +mod openssl; +#[cfg(feature = "openssl")] +pub use self::openssl::*; + +#[cfg(feature = "rustcrypto")] +mod rustcrypto; +#[cfg(feature = "rustcrypto")] +pub use rustcrypto::*; + +pub trait CertificateLike +where + Self: Sized, +{ + fn new( + private_key: &Key, + params: &CertificateParams, + ) -> Result>; + + fn to_vec(&self) -> Result, Box>; + + fn from_der(der: &[u8]) -> Result>; + + fn public_key(&self) -> &[u8]; +} diff --git a/src/crypto/x509/openssl.rs b/src/crypto/x509/openssl.rs new file mode 100644 index 0000000..181cd6d --- /dev/null +++ b/src/crypto/x509/openssl.rs @@ -0,0 +1,60 @@ +use openssl::asn1::Asn1Time; +use openssl::bn::{BigNum, MsbOption}; +use openssl::hash::MessageDigest; +use openssl::nid::Nid; +use openssl::x509::{X509Name as Name, X509}; + +use crate::crypto::rsa; +use crate::idp::CertificateParams; + +use crate::crypto::x509::CertificateLike; + +// #[derive(Clone)] +// pub struct Certificate<'a>(pub X509); + +impl CertificateLike for X509 { + fn new( + private_key: &Key, + params: &CertificateParams, + ) -> Result> { + let mut name = Name::builder()?; + name.append_entry_by_nid(Nid::COMMONNAME, params.common_name)?; + let name = name.build(); + + let mut iss = Name::builder()?; + iss.append_entry_by_nid(Nid::COMMONNAME, params.issuer_name)?; + let iss = iss.build(); + + let mut builder = X509::builder()?; + + let serial_number = { + let mut serial = BigNum::new()?; + serial.rand(159, MsbOption::MAYBE_ZERO, false)?; + serial.to_asn1_integer()? + }; + + builder.set_serial_number(&serial_number)?; + builder.set_version(2)?; + builder.set_subject_name(&name)?; + builder.set_issuer_name(&iss)?; + builder.set_pubkey(&private_key)?; + + let starts = Asn1Time::days_from_now(0)?; // now + builder.set_not_before(&starts)?; + + let expires = Asn1Time::days_from_now(params.days_until_expiration)?; + builder.set_not_after(&expires)?; + + builder.sign(&self.private_key.0, MessageDigest::sha256())?; + + Ok(Self(builder.build()?)) + } + + fn to_vec(&self) -> Result, Box> { + self.0.to_der() + } + + fn public_key(&self) -> &[u8] { + self.0.public_key() + } +} diff --git a/src/crypto/x509/rustcrypto.rs b/src/crypto/x509/rustcrypto.rs new file mode 100644 index 0000000..37cf9eb --- /dev/null +++ b/src/crypto/x509/rustcrypto.rs @@ -0,0 +1,53 @@ +use crate::crypto::rsa; +use x509_cert::der::{Decode, Encode}; + +use super::CertificateLike; +use crate::idp::CertificateParams; +pub use x509_cert::Certificate; + +// #[derive(Clone)] +// pub struct Certificate<'a>(pub x509_cert::Certificate<'a>); + +impl<'a> CertificateLike for Certificate<'a> { + fn new( + private_key: &rsa::PrivateKey, + params: &CertificateParams, + ) -> Result> { + todo!("Certificate creation is not yet supported for the rustcrypto backend"); + // let sn: [u8; 0] = []; + // Certificate { + // tbs_certificate: TbsCertificate { + // version: Version::V2, + // serial_number: UIntRef::new(&sn)?, + // signature: AlgorithmIdentifier, + // issuer: Name::encode_from_string(params.issuer_name)?.map(Name), + // validity: Validity, + // subject: Name::encode_from_string(params.common_name)?.map(Name), + // subject_public_key_info: SubjectPublicKeyInfo<'a>, + // issuer_unique_id: Option>, + // subject_unique_id: Option>, + // extensions: Option>, + // }, + // signature_algorithm: AlgorithmIdentifier { + + // }, + // signature: BitStringRef { + + // }, + // } + } + + fn to_vec(&self) -> Result, Box> { + Ok(Encode::to_vec(self)?) + } + + fn from_der(der: &[u8]) -> Result> { + Ok(Decode::from_der(der)?) + } + + fn public_key(&self) -> &[u8] { + self.tbs_certificate + .subject_public_key_info + .subject_public_key + } +} diff --git a/src/idp/error.rs b/src/idp/error.rs index 9006b31..6da2fc3 100644 --- a/src/idp/error.rs +++ b/src/idp/error.rs @@ -23,6 +23,7 @@ pub enum Error { error: crate::schema::authn_request::Error, }, + #[cfg(feature = "openssl")] #[snafu(display("OpenSSL Error: {}", stack))] OpenSSLError { stack: openssl::error::ErrorStack, @@ -32,14 +33,30 @@ pub enum Error { VerificationError { error: crate::crypto::Error, }, + + Unknown, } +#[cfg(feature = "openssl")] impl From for Error { fn from(error: openssl::error::ErrorStack) -> Self { Error::OpenSSLError { stack: error } } } +impl From> for Error { + fn from(error: Box) -> Self { + Error::Unknown + } +} + +#[cfg(feature = "rustcrypto")] +impl From for Error { + fn from(error: rsa::errors::Error) -> Self { + Error::Unknown + } +} + impl From for Error { fn from(error: crate::crypto::Error) -> Self { Error::VerificationError { error } diff --git a/src/idp/mod.rs b/src/idp/mod.rs index 4bab384..55f24d2 100644 --- a/src/idp/mod.rs +++ b/src/idp/mod.rs @@ -1,4 +1,5 @@ pub mod error; + use self::error::Error; pub mod response_builder; @@ -8,19 +9,20 @@ pub mod verified_request; #[cfg(test)] mod tests; -use openssl::bn::{BigNum, MsbOption}; -use openssl::nid::Nid; -use openssl::pkey::Private; -use openssl::{asn1::Asn1Time, pkey, rsa::Rsa, x509}; use std::str::FromStr; -use crate::crypto::{self}; +use crate::crypto::rsa::PrivateKeyLike; +use crate::crypto::x509::CertificateLike; +use crate::crypto::{self, rsa, x509}; use crate::idp::response_builder::{build_response_template, ResponseAttribute}; use crate::schema::Response; -pub struct IdentityProvider { - private_key: pkey::PKey, +pub struct IdentityProvider +where + PrivateKey: rsa::PrivateKeyLike, +{ + private_key: PrivateKey, } pub enum KeyType { @@ -45,59 +47,26 @@ pub struct CertificateParams<'a> { pub days_until_expiration: u32, } -impl IdentityProvider { +impl IdentityProvider { pub fn generate_new(key_type: KeyType) -> Result { - let rsa = Rsa::generate(key_type.bit_length())?; - let private_key = pkey::PKey::from_rsa(rsa)?; + let private_key = + rsa::PrivateKeyLike::new(usize::try_from(key_type.bit_length()).unwrap())?; Ok(IdentityProvider { private_key }) } pub fn from_private_key_der(der_bytes: &[u8]) -> Result { - let rsa = Rsa::private_key_from_der(der_bytes)?; - let private_key = pkey::PKey::from_rsa(rsa)?; + let private_key = rsa::PrivateKey::from_der(der_bytes)?; Ok(IdentityProvider { private_key }) } pub fn export_private_key_der(&self) -> Result, Error> { - let rsa: Rsa = self.private_key.rsa()?; - Ok(rsa.private_key_to_der()?) + Ok(self.private_key.to_der()?) } pub fn create_certificate(&self, params: &CertificateParams) -> Result, Error> { - let mut name = x509::X509Name::builder()?; - name.append_entry_by_nid(Nid::COMMONNAME, params.common_name)?; - let name = name.build(); - - let mut iss = x509::X509Name::builder()?; - iss.append_entry_by_nid(Nid::COMMONNAME, params.issuer_name)?; - let iss = iss.build(); - - let mut builder = x509::X509::builder()?; - - let serial_number = { - let mut serial = BigNum::new()?; - serial.rand(159, MsbOption::MAYBE_ZERO, false)?; - serial.to_asn1_integer()? - }; - - builder.set_serial_number(&serial_number)?; - builder.set_version(2)?; - builder.set_subject_name(&name)?; - builder.set_issuer_name(&iss)?; - builder.set_pubkey(&self.private_key)?; - - let starts = Asn1Time::days_from_now(0)?; // now - builder.set_not_before(&starts)?; - - let expires = Asn1Time::days_from_now(params.days_until_expiration)?; - builder.set_not_after(&expires)?; - - builder.sign(&self.private_key, openssl::hash::MessageDigest::sha256())?; - - let certificate: x509::X509 = builder.build(); - Ok(certificate.to_der()?) + Ok(x509::Certificate::new(&self.private_key, params)?.to_vec()?) } pub fn sign_authn_response( diff --git a/src/metadata/entity_descriptor.rs b/src/metadata/entity_descriptor.rs index 69273f1..74e0c9c 100644 --- a/src/metadata/entity_descriptor.rs +++ b/src/metadata/entity_descriptor.rs @@ -130,7 +130,9 @@ mod test { let output_xml = entity_descriptor .to_xml() .expect("Failed to convert EntityDescriptor to xml"); - let reparsed_entity_descriptor: EntityDescriptor =output_xml.parse().expect("Failed to parse EntityDescriptor"); + let reparsed_entity_descriptor: EntityDescriptor = output_xml + .parse() + .expect("Failed to parse EntityDescriptor"); assert_eq!(reparsed_entity_descriptor, entity_descriptor); } @@ -147,7 +149,9 @@ mod test { let output_xml = entity_descriptor .to_xml() .expect("Failed to convert EntityDescriptor to xml"); - let reparsed_entity_descriptor: EntityDescriptor =output_xml.parse().expect("Failed to parse EntityDescriptor"); + let reparsed_entity_descriptor: EntityDescriptor = output_xml + .parse() + .expect("Failed to parse EntityDescriptor"); assert_eq!(reparsed_entity_descriptor, entity_descriptor); } diff --git a/src/schema/authn_request.rs b/src/schema/authn_request.rs index 91ab615..387d8a4 100644 --- a/src/schema/authn_request.rs +++ b/src/schema/authn_request.rs @@ -199,13 +199,12 @@ impl AuthnRequest { } #[cfg(feature = "xmlsec")] - pub fn to_signed_xml(&self, + pub fn to_signed_xml( + &self, private_key_der: &[u8], ) -> Result> { crypto::sign_xml(self.to_xml()?, private_key_der) - .map_err(|crypto_error| - Box::new(crypto_error) as Box - ) + .map_err(|crypto_error| Box::new(crypto_error) as Box) } } @@ -232,19 +231,17 @@ mod test { "/test_vectors/authn_request_sign_template.xml" )); - let signed_authn_request = - authn_request_sign_template - .parse::()? - .add_key_info(public_cert) - .to_signed_xml(private_key)?; + let signed_authn_request = authn_request_sign_template + .parse::()? + .add_key_info(public_cert) + .to_signed_xml(private_key)?; - assert!( - crate::crypto::verify_signed_xml( - &signed_authn_request, - &public_cert[..], - Some("ID"), - ).is_ok() - ); + assert!(crate::crypto::verify_signed_xml( + &signed_authn_request, + &public_cert[..], + Some("ID"), + ) + .is_ok()); Ok(()) } @@ -266,16 +263,13 @@ mod test { "/test_vectors/authn_request_sign_template.xml" )); - let signed_authn_redirect_url = - authn_request_sign_template - .parse::()? - .signed_redirect("", private_key)? - .unwrap(); + let signed_authn_redirect_url = authn_request_sign_template + .parse::()? + .signed_redirect("", private_key)? + .unwrap(); let url_verifier = UrlVerifier::from_rsa_pem(public_key)?; - assert!( - url_verifier.verify_signed_request_url(&signed_authn_redirect_url)? - ); + assert!(url_verifier.verify_signed_request_url(&signed_authn_redirect_url)?); Ok(()) } @@ -297,22 +291,20 @@ mod test { "/test_vectors/authn_request_sign_template.xml" )); - let signed_authn_redirect_url = - authn_request_sign_template - .parse::()? - .signed_redirect("some_relay_state_here", private_key)? - .unwrap(); + let signed_authn_redirect_url = authn_request_sign_template + .parse::()? + .signed_redirect("some_relay_state_here", private_key)? + .unwrap(); let url_verifier = UrlVerifier::from_rsa_der(public_key)?; - assert!( - url_verifier.verify_signed_request_url(&signed_authn_redirect_url)? - ); + assert!(url_verifier.verify_signed_request_url(&signed_authn_redirect_url)?); Ok(()) } #[test] - pub fn test_redirect_signature_with_relaystate_using_x509_cert() -> Result<(), Box> { + pub fn test_redirect_signature_with_relaystate_using_x509_cert( + ) -> Result<(), Box> { let private_key = include_bytes!(concat!( env!("CARGO_MANIFEST_DIR"), "/test_vectors/private.der" @@ -328,16 +320,13 @@ mod test { "/test_vectors/authn_request_sign_template.xml" )); - let signed_authn_redirect_url = - authn_request_sign_template - .parse::()? - .signed_redirect("some_relay_state_here", private_key)? - .unwrap(); + let signed_authn_redirect_url = authn_request_sign_template + .parse::()? + .signed_redirect("some_relay_state_here", private_key)? + .unwrap(); let url_verifier = UrlVerifier::from_x509_cert_pem(public_cert)?; - assert!( - url_verifier.verify_signed_request_url(&signed_authn_redirect_url)? - ); + assert!(url_verifier.verify_signed_request_url(&signed_authn_redirect_url)?); Ok(()) } diff --git a/src/schema/response.rs b/src/schema/response.rs index fd01bcf..9066696 100644 --- a/src/schema/response.rs +++ b/src/schema/response.rs @@ -118,36 +118,53 @@ mod test { env!("CARGO_MANIFEST_DIR"), "/test_vectors/response.xml", )); - let expected_response: Response = response_xml.parse().expect("failed to parse response.xml"); - let serialized_response = expected_response.to_xml().expect("failed to convert response to xml"); - let actual_response: Response = serialized_response.parse().expect("failed to re-parse response"); + let expected_response: Response = + response_xml.parse().expect("failed to parse response.xml"); + let serialized_response = expected_response + .to_xml() + .expect("failed to convert response to xml"); + let actual_response: Response = serialized_response + .parse() + .expect("failed to re-parse response"); assert_eq!(expected_response, actual_response); } #[test] fn test_deserialize_serialize_response_with_signed_assertion() { - let response_xml = include_str!(concat!( + let response_xml = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/test_vectors/response_signed_assertion.xml", )); - let expected_response: Response = response_xml.parse().expect("failed to parse response_signed_assertion.xml"); - let serialized_response = expected_response.to_xml().expect("failed to convert response to xml"); - let actual_response: Response = serialized_response.parse().expect("failed to re-parse response"); + let expected_response: Response = response_xml + .parse() + .expect("failed to parse response_signed_assertion.xml"); + let serialized_response = expected_response + .to_xml() + .expect("failed to convert response to xml"); + let actual_response: Response = serialized_response + .parse() + .expect("failed to re-parse response"); assert_eq!(expected_response, actual_response); } #[test] fn test_deserialize_serialize_signed_response() { - let response_xml = include_str!(concat!( + let response_xml = include_str!(concat!( env!("CARGO_MANIFEST_DIR"), "/test_vectors/response_signed.xml", )); - let expected_response: Response = response_xml.parse().expect("failed to parse response_signed.xml"); - let serialized_response = expected_response.to_xml().expect("failed to convert response to xml"); - let actual_response: Response = serialized_response.parse().expect("failed to re-parse response"); + let expected_response: Response = response_xml + .parse() + .expect("failed to parse response_signed.xml"); + let serialized_response = expected_response + .to_xml() + .expect("failed to convert response to xml"); + let actual_response: Response = serialized_response + .parse() + .expect("failed to re-parse response"); assert_eq!(expected_response, actual_response); } -} \ No newline at end of file +} diff --git a/src/service_provider/mod.rs b/src/service_provider/mod.rs index 62c1353..f7234ef 100644 --- a/src/service_provider/mod.rs +++ b/src/service_provider/mod.rs @@ -1,4 +1,5 @@ -use crate::crypto; +use crate::crypto::rsa::PrivateKeyLike; +use crate::crypto::{self, rsa, x509}; use crate::metadata::{Endpoint, IndexedEndpoint, KeyDescriptor, NameIdFormat, SpSsoDescriptor}; use crate::schema::{Assertion, Response}; use crate::{ @@ -9,12 +10,12 @@ use crate::{ use chrono::prelude::*; use chrono::Duration; use flate2::{write::DeflateEncoder, Compression}; -use openssl::pkey::Private; -use openssl::{rsa, x509}; use snafu::Snafu; use std::fmt::Debug; use std::io::Write; use url::Url; +#[cfg(feature = "rustcrypto")] +pub use x509_cert::der::{Decode, Encode}; #[cfg(test)] mod tests; @@ -112,11 +113,14 @@ pub enum Error { #[derive(Builder, Clone)] #[builder(default, setter(into))] -pub struct ServiceProvider { +pub struct ServiceProvider +where + ServiceProvider: Default, +{ pub entity_id: Option, - pub key: Option>, - pub certificate: Option, - pub intermediates: Option>, + pub key: Option, + pub certificate: Option, + pub intermediates: Option>, pub metadata_url: Option, pub acs_url: Option, pub slo_url: Option, @@ -130,7 +134,7 @@ pub struct ServiceProvider { pub max_clock_skew: Duration, } -impl Default for ServiceProvider { +impl Default for ServiceProvider> { fn default() -> Self { ServiceProvider { entity_id: None, @@ -152,7 +156,7 @@ impl Default for ServiceProvider { } } -impl ServiceProvider { +impl ServiceProvider> { pub fn metadata(&self) -> Result> { let valid_duration = if let Some(duration) = self.metadata_valid_duration { Some(duration) @@ -170,10 +174,10 @@ impl ServiceProvider { let mut key_descriptors = vec![]; if let Some(cert) = &self.certificate { - let mut cert_bytes: Vec = cert.to_der()?; + let mut cert_bytes: Vec = cert.to_vec()?; if let Some(intermediates) = &self.intermediates { for intermediate in intermediates { - cert_bytes.append(&mut intermediate.to_der()?); + cert_bytes.append(&mut intermediate.to_vec()?); } } key_descriptors.push(KeyDescriptor { @@ -284,7 +288,7 @@ impl ServiceProvider { None } - pub fn idp_signing_certs(&self) -> Result>, Error> { + pub fn idp_signing_certs(&self) -> Result>, Error> { let mut result = vec![]; if let Some(idp_sso_descriptors) = &self.idp_metadata.idp_sso_descriptors { for idp_sso_descriptor in idp_sso_descriptors { @@ -319,10 +323,10 @@ impl ServiceProvider { }) } - pub fn parse_base64_response( + pub fn parse_response + Debug>( &self, encoded_resp: &str, - possible_request_ids: Option<&[&str]>, + possible_request_ids: &[AsStr], ) -> Result> { let bytes = base64::decode(encoded_resp)?; let decoded = std::str::from_utf8(&bytes)?; @@ -330,10 +334,10 @@ impl ServiceProvider { Ok(assertion) } - pub fn parse_xml_response( + pub fn parse_xml_response + Debug>( &self, response_xml: &str, - possible_request_ids: Option<&[&str]>, + possible_request_ids: &[AsStr], ) -> Result { let reduced_xml = if let Some(sign_certs) = self.idp_signing_certs()? { reduce_xml_to_signed(response_xml, &sign_certs) @@ -348,11 +352,9 @@ impl ServiceProvider { let mut request_id_valid = false; if self.allow_idp_initiated { request_id_valid = true; - } else if let (Some(in_response_to), Some(possible_request_ids)) = - (&response.in_response_to, possible_request_ids) - { + } else if let Some(in_response_to) = &response.in_response_to { for req_id in possible_request_ids { - if req_id == in_response_to { + if req_id.as_ref() == in_response_to { request_id_valid = true; } } @@ -360,9 +362,8 @@ impl ServiceProvider { if !request_id_valid { return Err(Error::ResponseInResponseToInvalid { possible_ids: possible_request_ids - .into_iter() - .flatten() - .map(|e| e.to_string()) + .iter() + .map(|e| e.as_ref().to_string()) .collect(), }); } @@ -400,10 +401,10 @@ impl ServiceProvider { } } - fn validate_assertion( + fn validate_assertion + Debug>( &self, assertion: &Assertion, - _possible_request_ids: Option<&[&str]>, + _possible_request_ids: &[AsStr], ) -> Result<(), Error> { if assertion.issue_instant + self.max_issue_delay < Utc::now() { return Err(Error::AssertionExpired { @@ -500,7 +501,7 @@ impl ServiceProvider { } } -fn parse_certificates(key_descriptor: &KeyDescriptor) -> Result, Error> { +fn parse_certificates(key_descriptor: &KeyDescriptor) -> Result, Error> { key_descriptor .key_info .x509_data @@ -511,7 +512,7 @@ fn parse_certificates(key_descriptor: &KeyDescriptor) -> Result, .map(|cert| { crypto::decode_x509_cert(cert) .ok() - .and_then(|decoded| openssl::x509::X509::from_der(&decoded).ok()) + .and_then(|decoded| x509::Certificate::from_der(&decoded).ok()) .ok_or_else(|| Error::FailedToParseCert { cert: cert.to_string(), }) @@ -596,23 +597,17 @@ impl AuthnRequest { // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // // then add the "Signature" query parameter afterwards. - let string_to_sign: String = unsigned_url + let query_string: String = unsigned_url .query() .ok_or(Error::UnexpectedError)? .to_string(); - // Use openssl's bindings to sign - let pkey = openssl::rsa::Rsa::private_key_from_der(private_key_der)?; - let pkey = openssl::pkey::PKey::from_rsa(pkey)?; - - let mut signer = - openssl::sign::Signer::new(openssl::hash::MessageDigest::sha256(), pkey.as_ref())?; - - signer.update(string_to_sign.as_bytes())?; + let private_key = rsa::PrivateKey::from_der(private_key_der)?; - unsigned_url - .query_pairs_mut() - .append_pair("Signature", &base64::encode(signer.sign_to_vec()?)); + unsigned_url.query_pairs_mut().append_pair( + "Signature", + &base64::encode(private_key.sign_sha256(query_string)?), + ); // Past this point, it's a signed url :) Ok(Some(unsigned_url)) diff --git a/src/signature.rs b/src/signature.rs index 3cf4d5e..dfb4d8c 100644 --- a/src/signature.rs +++ b/src/signature.rs @@ -64,9 +64,7 @@ impl Signature { key_info: Some(vec![KeyInfo { id: None, x509_data: Some(X509Data { - certificates: vec![ - crate::crypto::mime_encode_x509_cert(x509_cert_der) - ], + certificates: vec![crate::crypto::mime_encode_x509_cert(x509_cert_der)], }), }]), } @@ -124,9 +122,7 @@ impl SignatureValue { } writer.write_event(Event::Start(root))?; if let Some(ref base64_content) = self.base64_content { - writer.write_event(Event::Text(BytesText::from_plain_str( - base64_content, - )))?; + writer.write_event(Event::Text(BytesText::from_plain_str(base64_content)))?; } writer.write_event(Event::End(BytesEnd::borrowed( SIGNATURE_VALUE_NAME.as_bytes(), @@ -332,9 +328,7 @@ impl DigestValue { let root = BytesStart::borrowed(DIGEST_VALUE_NAME.as_bytes(), DIGEST_VALUE_NAME.len()); writer.write_event(Event::Start(root))?; if let Some(ref base64_content) = self.base64_content { - writer.write_event(Event::Text(BytesText::from_plain_str( - base64_content, - )))?; + writer.write_event(Event::Text(BytesText::from_plain_str(base64_content)))?; } writer.write_event(Event::End(BytesEnd::borrowed(DIGEST_VALUE_NAME.as_bytes())))?; Ok(String::from_utf8(write_buf)?) diff --git a/src/xmlsec/error.rs b/src/xmlsec/error.rs index e7ca362..5f0c549 100644 --- a/src/xmlsec/error.rs +++ b/src/xmlsec/error.rs @@ -60,10 +60,9 @@ impl std::fmt::Display for XmlSecError { Self::NodeNotFound => write!(fmt, "Failed to find node"), Self::NotASignatureNode => write!(fmt, "Node is not a signature node"), - Self::SigningError => write!( - fmt, - "An error has ocurred while attemting to sign document" - ), + Self::SigningError => { + write!(fmt, "An error has ocurred while attemting to sign document") + } Self::VerifyError => write!(fmt, "Verification failed"), } }