From cbf127a29746a74e55ea9678766574f0163ce7b7 Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Fri, 6 Sep 2024 23:06:21 +0800 Subject: [PATCH] feat: v1.9.13, support ssh-piv-cert, but not works --- Cargo.lock | 687 ++++++++++++++++++++++++++++++++++++------ Cargo.toml | 3 +- src/cmd_sshpivcert.rs | 154 ++++++++++ src/cmd_sshpivsign.rs | 2 +- src/cmd_sshpubkey.rs | 24 +- src/main.rs | 2 + 6 files changed, 769 insertions(+), 103 deletions(-) create mode 100644 src/cmd_sshpivcert.rs diff --git a/Cargo.lock b/Cargo.lock index ac83e3a..d7bd332 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "e7a2e47a1fbe209ee101dd6d61285226744c6c8d3c21c8dc878ba6cb9f467f3a" dependencies = [ "gimli", ] @@ -26,14 +26,15 @@ dependencies = [ "cfg-if 1.0.0", "cipher 0.3.0", "cpufeatures", + "ctr", "opaque-debug", ] [[package]] name = "aho-corasick" -version = "1.1.3" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -68,6 +69,12 @@ version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "ascii-canvas" version = "3.0.0" @@ -86,9 +93,9 @@ dependencies = [ "asn1-rs-derive 0.4.0", "asn1-rs-impl 0.1.0", "displaydoc", - "nom", + "nom 7.1.3", "num-traits", - "rusticata-macros", + "rusticata-macros 4.1.0", "thiserror", "time 0.3.36", ] @@ -102,9 +109,9 @@ dependencies = [ "asn1-rs-derive 0.5.0", "asn1-rs-impl 0.2.0", "displaydoc", - "nom", + "nom 7.1.3", "num-traits", - "rusticata-macros", + "rusticata-macros 4.1.0", "thiserror", ] @@ -182,6 +189,33 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "authenticator" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "253b4c27b89127df34b7037a462305affda8ec85b32d7a0b799484796a3cdc85" +dependencies = [ + "base64 0.21.7", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "core-foundation", + "devd-rs", + "libc", + "libudev", + "log", + "memoffset 0.8.0", + "openssl", + "openssl-sys", + "rand 0.8.5", + "runloop", + "serde", + "serde_bytes", + "serde_cbor", + "serde_json", + "sha2 0.10.8", + "winapi 0.3.9", +] + [[package]] name = "autocfg" version = "1.3.0" @@ -190,19 +224,25 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "4717cfcbfaa661a0fd48f8453951837ae7e8f81e481fbb136e3202d72805a744" dependencies = [ "addr2line", "cc", "cfg-if 1.0.0", "libc", - "miniz_oxide", + "miniz_oxide 0.4.4", "object", "rustc-demangle", ] +[[package]] +name = "base16ct" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" + [[package]] name = "base16ct" version = "0.2.0" @@ -239,6 +279,19 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bcrypt-pbkdf" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12621b8e87feb183a6e5dbb315e49026b2229c4398797ee0ae2d1bc00aef41b9" +dependencies = [ + "blowfish", + "crypto-mac", + "pbkdf2 0.8.0", + "sha2 0.9.9", + "zeroize", +] + [[package]] name = "bech32" version = "0.9.1" @@ -247,11 +300,11 @@ checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" [[package]] name = "bindgen" -version = "0.68.1" +version = "0.60.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" +checksum = "062dddbc1ba4aca46de6338e2bf87771414c335f7b2f2036e8f3e9befebf88e6" dependencies = [ - "bitflags 2.6.0", + "bitflags 1.3.2", "cexpr", "clang-sys", "lazy_static", @@ -262,7 +315,6 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.72", ] [[package]] @@ -292,6 +344,18 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +[[package]] +name = "bitvec" +version = "0.19.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "blanket" version = "0.3.0" @@ -337,6 +401,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "blowfish" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe3ff3fc1de48c1ac2e3341c4df38b0d1bfb8fdf04632a187c8b75aaa319a7ab" +dependencies = [ + "byteorder", + "cipher 0.3.0", + "opaque-debug", +] + [[package]] name = "buffered-reader" version = "1.3.1" @@ -406,16 +481,16 @@ dependencies = [ [[package]] name = "card-cli" -version = "1.9.12" +version = "1.9.13" dependencies = [ - "authenticator", + "authenticator 0.3.1", "base64 0.21.7", "bech32", "chrono", "clap", "der-parser 9.0.0", "digest 0.10.7", - "ecdsa", + "ecdsa 0.16.9", "env_logger", "hex", "jwt", @@ -423,8 +498,8 @@ dependencies = [ "openpgp-card-pcsc", "openpgp-card-sequoia", "openssl", - "p256", - "p384", + "p256 0.13.2", + "p384 0.13.0", "pem", "pinentry", "rand 0.8.5", @@ -437,16 +512,17 @@ dependencies = [ "serde", "serde_json", "sha1", - "sha2", + "sha2 0.10.8", "simpledateformat", "spki 0.7.3", "ssh-agent", + "sshcerts", "tabled", "u2f", "x509", - "x509-parser", + "x509-parser 0.15.1", "yubico_manager", - "yubikey", + "yubikey 0.8.0", ] [[package]] @@ -461,7 +537,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -615,7 +691,7 @@ dependencies = [ "crossbeam-utils", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", "scopeguard", ] @@ -647,6 +723,18 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +[[package]] +name = "crypto-bigint" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" +dependencies = [ + "generic-array 0.14.7", + "rand_core 0.6.4", + "subtle", + "zeroize", +] + [[package]] name = "crypto-bigint" version = "0.5.5" @@ -679,6 +767,15 @@ dependencies = [ "subtle", ] +[[package]] +name = "ctr" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" +dependencies = [ + "cipher 0.3.0", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -709,6 +806,30 @@ dependencies = [ "zeroize", ] +[[package]] +name = "der-oid-macro" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4cccf60bb98c0fca115a581f894aed0e43fa55bf289fdac5599bec440bb4fd6" +dependencies = [ + "nom 6.2.2", + "num-bigint", + "num-traits", + "syn 1.0.109", +] + +[[package]] +name = "der-parser" +version = "5.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d7ededb7525bb4114bc209685ce7894edc2965f4914312a1ea578a645a237f0" +dependencies = [ + "der-oid-macro", + "nom 6.2.2", + "num-traits", + "rusticata-macros 3.2.0", +] + [[package]] name = "der-parser" version = "8.2.0" @@ -717,10 +838,10 @@ checksum = "dbd676fbbab537128ef0278adb5576cf363cff6aa22a7b24effe97347cfab61e" dependencies = [ "asn1-rs 0.5.2", "displaydoc", - "nom", + "nom 7.1.3", "num-bigint", "num-traits", - "rusticata-macros", + "rusticata-macros 4.1.0", ] [[package]] @@ -731,9 +852,9 @@ checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" dependencies = [ "asn1-rs 0.6.1", "displaydoc", - "nom", + "nom 7.1.3", "num-traits", - "rusticata-macros", + "rusticata-macros 4.1.0", ] [[package]] @@ -772,7 +893,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9313f104b590510b46fc01c0a324fc76505c13871454d3c48490468d04c8d395" dependencies = [ "libc", - "nom", + "nom 7.1.3", ] [[package]] @@ -834,6 +955,18 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" +[[package]] +name = "ecdsa" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" +dependencies = [ + "der 0.6.1", + "elliptic-curve 0.12.3", + "rfc6979 0.3.1", + "signature 1.6.4", +] + [[package]] name = "ecdsa" version = "0.16.9" @@ -842,9 +975,9 @@ checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" dependencies = [ "der 0.7.9", "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", + "elliptic-curve 0.13.8", + "rfc6979 0.4.0", + "signature 2.2.0", "spki 0.7.3", ] @@ -854,23 +987,45 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +[[package]] +name = "elliptic-curve" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" +dependencies = [ + "base16ct 0.1.1", + "crypto-bigint 0.4.9", + "der 0.6.1", + "digest 0.10.7", + "ff 0.12.1", + "generic-array 0.14.7", + "group 0.12.1", + "hkdf", + "pem-rfc7468 0.6.0", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "sec1 0.3.0", + "subtle", + "zeroize", +] + [[package]] name = "elliptic-curve" version = "0.13.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" dependencies = [ - "base16ct", - "crypto-bigint", + "base16ct 0.2.0", + "crypto-bigint 0.5.5", "digest 0.10.7", - "ff", + "ff 0.13.0", "generic-array 0.14.7", - "group", + "group 0.13.0", "hkdf", "pem-rfc7468 0.7.0", "pkcs8 0.10.2", "rand_core 0.6.4", - "sec1", + "sec1 0.7.3", "subtle", "zeroize", ] @@ -928,6 +1083,16 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "ff" version = "0.13.0" @@ -957,7 +1122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]] @@ -1006,6 +1171,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "funty" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7" + [[package]] name = "futures" version = "0.1.31" @@ -1147,9 +1318,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "0e4075386626662786ddb0ec9081e7c7eeb1ba31951f447ca780ef9f5d568189" [[package]] name = "glob" @@ -1157,13 +1328,24 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", + "ff 0.13.0", "rand_core 0.6.4", "subtle", ] @@ -1187,6 +1369,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "hashbrown" version = "0.14.5" @@ -1593,7 +1781,7 @@ dependencies = [ "hmac 0.12.1", "serde", "serde_json", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -1619,7 +1807,7 @@ dependencies = [ "lalrpop-util", "petgraph", "regex", - "regex-syntax", + "regex-syntax 0.8.4", "string_cache", "term", "tiny-keccak", @@ -1629,12 +1817,9 @@ dependencies = [ [[package]] name = "lalrpop-util" -version = "0.20.2" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", -] +checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" [[package]] name = "lazy_static" @@ -1651,6 +1836,19 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "lexical-core" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "cfg-if 1.0.0", + "ryu", + "static_assertions", +] + [[package]] name = "libc" version = "0.2.155" @@ -1760,9 +1958,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.7.4" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" @@ -1773,6 +1971,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memoffset" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +dependencies = [ + "autocfg", +] + [[package]] name = "memsec" version = "0.7.0" @@ -1785,12 +1992,28 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +[[package]] +name = "minicbor" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "124d887cb82f0b1469bdac3d1b65764a381eed1a54fdab0070e5772b13114521" + [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -1915,6 +2138,19 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nom" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6a7a9657c84d5814c6196b68bb4429df09c18b1573806259fba397ea4ad0d44" +dependencies = [ + "bitvec", + "funty", + "lexical-core", + "memchr", + "version_check", +] + [[package]] name = "nom" version = "7.1.3" @@ -2001,12 +2237,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.2" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" -dependencies = [ - "memchr", -] +checksum = "1a5b3dd1c072ee7963717671d1ca129f1048fda25edea6b752bfc71ac8854170" [[package]] name = "oid-registry" @@ -2039,7 +2272,7 @@ dependencies = [ "chrono", "hex-slice", "log", - "nom", + "nom 7.1.3", "thiserror", ] @@ -2114,16 +2347,38 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "p256" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.8", +] + [[package]] name = "p256" version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "primeorder", - "sha2", + "sha2 0.10.8", +] + +[[package]] +name = "p384" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc8c5bf642dde52bb9e87c0ecd8ca5a76faac2eeed98dedb7c717997e1080aa" +dependencies = [ + "ecdsa 0.14.8", + "elliptic-curve 0.12.3", + "sha2 0.10.8", ] [[package]] @@ -2132,10 +2387,10 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" dependencies = [ - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "primeorder", - "sha2", + "sha2 0.10.8", ] [[package]] @@ -2198,6 +2453,24 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pbkdf2" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d95f5254224e617595d2cc3cc73ff0a5eaf2637519e25f03388154e9378b6ffa" +dependencies = [ + "crypto-mac", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "pbkdf2" version = "0.12.2" @@ -2305,7 +2578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa5b8bc68be6a5e2ba84ee86db53f816cba1905b94fcb7c236e606221cc8fc8" dependencies = [ "log", - "nom", + "nom 7.1.3", "percent-encoding", "secrecy", "which", @@ -2385,7 +2658,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" dependencies = [ - "elliptic-curve", + "elliptic-curve 0.13.8", ] [[package]] @@ -2457,6 +2730,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8" + [[package]] name = "rand" version = "0.7.3" @@ -2528,6 +2807,18 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rcgen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" +dependencies = [ + "pem", + "ring 0.16.20", + "time 0.3.36", + "yasna", +] + [[package]] name = "redox_syscall" version = "0.1.57" @@ -2556,26 +2847,20 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "2a26af418b574bd56588335b3a3659a65725d4e636eb1016c2f9e3b38c7cc759" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] -name = "regex-automata" -version = "0.4.7" +name = "regex-syntax" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" @@ -2623,6 +2908,17 @@ dependencies = [ "winreg", ] +[[package]] +name = "rfc6979" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" +dependencies = [ + "crypto-bigint 0.4.9", + "hmac 0.12.1", + "zeroize", +] + [[package]] name = "rfc6979" version = "0.4.0" @@ -2674,6 +2970,27 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rsa" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c" +dependencies = [ + "byteorder", + "digest 0.10.7", + "num-bigint-dig", + "num-integer", + "num-iter", + "num-traits", + "pkcs1 0.4.1", + "pkcs8 0.9.0", + "rand_core 0.6.4", + "signature 1.6.4", + "smallvec 1.13.2", + "subtle", + "zeroize", +] + [[package]] name = "rsa" version = "0.8.2" @@ -2689,7 +3006,7 @@ dependencies = [ "pkcs1 0.4.1", "pkcs8 0.9.0", "rand_core 0.6.4", - "signature", + "signature 2.2.0", "subtle", "zeroize", ] @@ -2708,8 +3025,8 @@ dependencies = [ "pkcs1 0.7.5", "pkcs8 0.10.2", "rand_core 0.6.4", - "sha2", - "signature", + "sha2 0.10.8", + "signature 2.2.0", "spki 0.7.3", "subtle", "zeroize", @@ -2775,13 +3092,22 @@ dependencies = [ "semver", ] +[[package]] +name = "rusticata-macros" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbbee512c633ecabd4481c40111b6ded03ddd9ab10ba6caa5a74e14c889921ad" +dependencies = [ + "nom 6.2.2", +] + [[package]] name = "rusticata-macros" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -2842,13 +3168,27 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sec1" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" +dependencies = [ + "base16ct 0.1.1", + "der 0.6.1", + "generic-array 0.14.7", + "pkcs8 0.9.0", + "subtle", + "zeroize", +] + [[package]] name = "sec1" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ - "base16ct", + "base16ct 0.2.0", "der 0.7.9", "generic-array 0.14.7", "pkcs8 0.10.2", @@ -2926,7 +3266,7 @@ dependencies = [ "nettle", "once_cell", "regex", - "regex-syntax", + "regex-syntax 0.8.4", "sha1collisiondetection", "thiserror", "xxhash-rust", @@ -2941,6 +3281,25 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.204" @@ -3009,6 +3368,19 @@ dependencies = [ "generic-array 1.1.0", ] +[[package]] +name = "sha2" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" +dependencies = [ + "block-buffer 0.9.0", + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.9.0", + "opaque-debug", +] + [[package]] name = "sha2" version = "0.10.8" @@ -3026,6 +3398,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signature" +version = "1.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" +dependencies = [ + "digest 0.10.7", + "rand_core 0.6.4", +] + [[package]] name = "signature" version = "2.2.0" @@ -3036,6 +3418,18 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simple_asn1" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb4ea60fb301dc81dfc113df680571045d375ab7345d171c5dc7d7e13107a80" +dependencies = [ + "chrono", + "num-bigint", + "num-traits", + "thiserror", +] + [[package]] name = "simpledateformat" version = "0.1.4" @@ -3133,12 +3527,42 @@ dependencies = [ "tokio-uds", ] +[[package]] +name = "sshcerts" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "752ad8923d32fb5c117b8a9983266e294edc072401133720aa9af3959d63248d" +dependencies = [ + "aes", + "authenticator 0.4.0", + "base64 0.13.1", + "bcrypt-pbkdf", + "chrono", + "ctr", + "der-parser 5.1.2", + "minicbor", + "num-bigint", + "rcgen", + "ring 0.17.8", + "simple_asn1", + "x509", + "x509-parser 0.15.1", + "yubikey 0.7.0", + "zeroize", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + [[package]] name = "string_cache" version = "0.8.7" @@ -3281,6 +3705,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "tempfile" version = "3.10.1" @@ -4165,6 +4595,12 @@ dependencies = [ "winapi-build", ] +[[package]] +name = "wyz" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" + [[package]] name = "x509" version = "0.2.0" @@ -4184,11 +4620,29 @@ dependencies = [ "const-oid", "der 0.7.9", "sha1", - "signature", + "signature 2.2.0", "spki 0.7.3", "tls_codec", ] +[[package]] +name = "x509-parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0ecbeb7b67ce215e40e3cc7f2ff902f94a223acf44995934763467e7b1febc8" +dependencies = [ + "asn1-rs 0.5.2", + "base64 0.13.1", + "data-encoding", + "der-parser 8.2.0", + "lazy_static", + "nom 7.1.3", + "oid-registry", + "rusticata-macros 4.1.0", + "thiserror", + "time 0.3.36", +] + [[package]] name = "x509-parser" version = "0.15.1" @@ -4199,10 +4653,10 @@ dependencies = [ "data-encoding", "der-parser 8.2.0", "lazy_static", - "nom", + "nom 7.1.3", "oid-registry", "ring 0.16.20", - "rusticata-macros", + "rusticata-macros 4.1.0", "thiserror", "time 0.3.36", ] @@ -4213,6 +4667,15 @@ version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time 0.3.36", +] + [[package]] name = "yoke" version = "0.7.4" @@ -4253,33 +4716,67 @@ dependencies = [ "structure", ] +[[package]] +name = "yubikey" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10e6fa9476951a9b93d9a31aa5554b5bbac7aafdc5b23e663eb3f9b635c86053" +dependencies = [ + "base16ct 0.1.1", + "chrono", + "cookie-factory", + "der-parser 8.2.0", + "des", + "elliptic-curve 0.12.3", + "hmac 0.12.1", + "log", + "nom 7.1.3", + "num-bigint-dig", + "num-integer", + "num-traits", + "p256 0.11.1", + "p384 0.11.2", + "pbkdf2 0.11.0", + "pcsc", + "rand_core 0.6.4", + "rsa 0.7.2", + "secrecy", + "sha1", + "sha2 0.10.8", + "subtle", + "uuid", + "x509", + "x509-parser 0.14.0", + "zeroize", +] + [[package]] name = "yubikey" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d1efb43c1e3edd4cf871c8dc500d900abfa083c1f2bab10b781ea8ffcadedcb" dependencies = [ - "base16ct", + "base16ct 0.2.0", "der 0.7.9", "des", - "ecdsa", - "elliptic-curve", + "ecdsa 0.16.9", + "elliptic-curve 0.13.8", "hmac 0.12.1", "log", - "nom", + "nom 7.1.3", "num-bigint-dig", "num-integer", "num-traits", - "p256", - "p384", - "pbkdf2", + "p256 0.13.2", + "p384 0.13.0", + "pbkdf2 0.12.2", "pcsc", "rand_core 0.6.4", "rsa 0.9.6", "secrecy", "sha1", - "sha2", - "signature", + "sha2 0.10.8", + "signature 2.2.0", "subtle", "uuid", "x509-cert", diff --git a/Cargo.toml b/Cargo.toml index 1974c64..92cbaf8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "card-cli" -version = "1.9.12" +version = "1.9.13" authors = ["Hatter Jiang "] edition = "2018" @@ -44,6 +44,7 @@ pinentry = "0.5.0" rpassword = "7.3.1" secrecy = "0.8.0" der-parser = "9.0.0" +sshcerts = "0.13.2" #lazy_static = "1.4.0" #ssh-key = "0.4.0" #ctap-hid-fido2 = "2.1.3" diff --git a/src/cmd_sshpivcert.rs b/src/cmd_sshpivcert.rs new file mode 100644 index 0000000..c8de243 --- /dev/null +++ b/src/cmd_sshpivcert.rs @@ -0,0 +1,154 @@ +use clap::{App, Arg, ArgMatches, SubCommand}; +use ecdsa::elliptic_curve::pkcs8::der::Encode; +use rand::random; +use rust_util::util_clap::{Command, CommandError}; +use rust_util::XResult; +use sshcerts::ssh::{CurveKind, PublicKeyKind, SSHCertificateSigner}; +use sshcerts::utils::format_signature_for_ssh; +use sshcerts::x509::extract_ssh_pubkey_from_x509_certificate; +use sshcerts::{CertType, Certificate, PublicKey}; +use std::sync::Mutex; +use std::time::SystemTime; +use yubikey::piv::{sign_data, AlgorithmId, SlotId}; +use yubikey::{Key, YubiKey}; + +use crate::digest::{sha256_bytes, sha384_bytes}; +use crate::pivutil::slot_equals; +use crate::{pinutil, pivutil, util}; + +pub struct CommandImpl; + + +// https://github.com/RustCrypto/SSH +// https://github.com/obelisk/sshcerts/ +impl Command for CommandImpl { + fn name(&self) -> &str { "ssh-piv-cert" } + + fn subcommand<'a>(&self) -> App<'a, 'a> { + SubCommand::with_name(self.name()).about("SSH PIV sign cert subcommand") + .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN")) + .arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e")) + .arg(Arg::with_name("key-id").short("k").long("key-id").takes_value(true).help("SSH user CA key id")) + .arg(Arg::with_name("principal").short("P").long("principal").takes_value(true).help("SSH user CA principal")) + .arg(Arg::with_name("pub").long("pub").required(true).takes_value(true).help("SSH public key file")) + } + + fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { + let ssh_pub = util::read_file_or_stdin(sub_arg_matches.value_of("pub").unwrap())?; + let ssh_pub_str = String::from_utf8(ssh_pub).expect("Read SSh pub file failed: {}"); + + let slot = opt_value_result!(sub_arg_matches.value_of("slot"), "--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"); + let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); + let slot_id = pivutil::get_slot_id(slot)?; + + let pin_opt = sub_arg_matches.value_of("pin"); + let pin_opt = pinutil::get_pin(pin_opt); + let pin_opt = pin_opt.as_deref(); + + let cert_der = find_cert(&mut yk, slot_id)?; + + let ca_ssh_pub_key = opt_result!(extract_ssh_pubkey_from_x509_certificate(&cert_der), "Extract SSH public key failed: {}"); + let tobe_signed_ssh_pub_key = opt_result!(PublicKey::from_string(&ssh_pub_str), "Parse tobe signed SSH public key failed: {}"); + + let ca_ssh_pub_algorithm_id = get_ssh_key_type(&ca_ssh_pub_key)?; + let ssh_yubikey_signer = SshYubikeySinger::new( + yk, + pin_opt.map(ToString::to_string), + slot_id, + ca_ssh_pub_key.clone(), + ca_ssh_pub_algorithm_id, + ); + + let serial: u64 = random(); + let key_id = sub_arg_matches.value_of("key-id").unwrap_or("default_key_id"); + let principals = sub_arg_matches.values_of("principal") + .map(|ps| ps.map(|p| p.to_string()).collect::>()) + .unwrap_or_else(|| vec!["default_principal".to_string()]); + debugging!("Serial: {}", serial); + debugging!("Key ID: {}", key_id); + debugging!("Principals: {:?}", principals); + + let now_secs = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_secs(); + + let user_cert_result = Certificate::builder(&tobe_signed_ssh_pub_key, CertType::User, &ca_ssh_pub_key) + .unwrap() + .serial(serial) + .key_id(key_id) + .set_principals(&principals) + .valid_after(now_secs - 100) + .valid_before(now_secs + 60000) + .set_extensions(Certificate::standard_extensions()) + .sign(&ssh_yubikey_signer); + + let user_cert = opt_result!(user_cert_result, "Sign SSH user CA failed: {}"); + println!("{}", user_cert.to_string()); + + Ok(None) + } +} + +fn find_cert(yk: &mut YubiKey, slot_id: SlotId) -> XResult> { + match Key::list(yk) { + Err(e) => warning!("List keys failed: {}", e), + Ok(keys) => { + for k in &keys { + let slot_str = format!("{:x}", Into::::into(k.slot())); + if slot_equals(&slot_id, &slot_str) { + let cert_der = k.certificate().cert.to_der()?; + return Ok(cert_der); + } + } + } + } + simple_error!("Cannot find slot: {}", slot_id) +} + +pub fn get_ssh_key_type(public_key: &PublicKey) -> XResult { + match &public_key.kind { + PublicKeyKind::Ecdsa(x) => match x.curve.kind { + CurveKind::Nistp256 => Ok(AlgorithmId::EccP256), + CurveKind::Nistp384 => Ok(AlgorithmId::EccP384), + CurveKind::Nistp521 => simple_error!("NIST P521 is not supported."), + }, + PublicKeyKind::Rsa(_) => simple_error!("RSA is not supported."), + PublicKeyKind::Ed25519(_) => simple_error!("Ed25519 is not supported."), + } +} + +struct SshYubikeySinger { + yubikey: Mutex, + pin_opt: Option, + ca_ssh_pub_slot_id: SlotId, + ca_ssh_pub_key: PublicKey, + ca_ssh_pub_algorithm_id: AlgorithmId, +} + +impl SshYubikeySinger { + fn new(yubikey: YubiKey, pin_opt: Option, ca_ssh_pub_slot_id: SlotId, ca_ssh_pub_key: PublicKey, ca_ssh_pub_algorithm_id: AlgorithmId) -> Self { + Self { + yubikey: Mutex::new(yubikey), + pin_opt, + ca_ssh_pub_slot_id, + ca_ssh_pub_key, + ca_ssh_pub_algorithm_id, + } + } +} + +impl SSHCertificateSigner for SshYubikeySinger { + fn sign(&self, buffer: &[u8]) -> Option> { + let digest = match self.ca_ssh_pub_algorithm_id { + AlgorithmId::Rsa1024 | AlgorithmId::Rsa2048 => { panic!("Should not reach here.") } + AlgorithmId::EccP256 => sha256_bytes(buffer), + AlgorithmId::EccP384 => sha384_bytes(buffer), + }; + let mut yubikey = self.yubikey.lock().unwrap(); + if let Some(pin) = &self.pin_opt { + yubikey.verify_pin(pin.as_bytes()).expect("Verify PIN failed: {}"); + } + + let signature = sign_data(&mut yubikey, &digest, self.ca_ssh_pub_algorithm_id, self.ca_ssh_pub_slot_id).expect("SSH user CA sign failed: {}"); + + format_signature_for_ssh(&self.ca_ssh_pub_key, &signature.to_vec()) + } +} diff --git a/src/cmd_sshpivsign.rs b/src/cmd_sshpivsign.rs index e4903b1..b95b501 100644 --- a/src/cmd_sshpivsign.rs +++ b/src/cmd_sshpivsign.rs @@ -16,7 +16,7 @@ impl Command for CommandImpl { fn name(&self) -> &str { "ssh-piv-sign" } fn subcommand<'a>(&self) -> App<'a, 'a> { - SubCommand::with_name(self.name()).about("SSH parse sign subcommand") + SubCommand::with_name(self.name()).about("SSH piv sign subcommand") .arg(Arg::with_name("pin").short("p").long("pin").takes_value(true).help("PIV card user PIN")) .arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e")) .arg(Arg::with_name("namespace").short("n").long("namespace").takes_value(true).help("Namespace")) diff --git a/src/cmd_sshpubkey.rs b/src/cmd_sshpubkey.rs index 1dfe048..4970351 100644 --- a/src/cmd_sshpubkey.rs +++ b/src/cmd_sshpubkey.rs @@ -1,3 +1,7 @@ +use crate::digest::sha256_bytes; +use crate::pivutil; +use crate::pivutil::{get_algorithm_id_by_certificate, slot_equals, ToStr}; +use crate::sshutil::SshVecWriter; use base64::engine::general_purpose::STANDARD; use base64::Engine; use clap::{App, Arg, ArgMatches, SubCommand}; @@ -5,10 +9,6 @@ use rust_util::util_clap::{Command, CommandError}; use yubikey::piv::AlgorithmId; use yubikey::{Key, YubiKey}; -use crate::pivutil; -use crate::pivutil::{get_algorithm_id_by_certificate, slot_equals, ToStr}; -use crate::sshutil::SshVecWriter; - pub struct CommandImpl; impl Command for CommandImpl { @@ -17,10 +17,12 @@ impl Command for CommandImpl { fn subcommand<'a>(&self) -> App<'a, 'a> { SubCommand::with_name(self.name()).about("SSH public key subcommand") .arg(Arg::with_name("slot").short("s").long("slot").takes_value(true).help("PIV slot, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e")) + .arg(Arg::with_name("ca").long("ca").help("SSH cert-authority")) } fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError { let slot = opt_value_result!(sub_arg_matches.value_of("slot"), "--slot must assigned, e.g. 82, 83 ... 95, 9a, 9c, 9d, 9e"); + let ca = sub_arg_matches.is_present("ca"); let mut yk = opt_result!(YubiKey::open(), "YubiKey not found: {}"); let slot_id = pivutil::get_slot_id(slot)?; @@ -59,7 +61,6 @@ impl Command for CommandImpl { information!("SSH algorithm: {}", ssh_algorithm); information!("ECDSA public key: {}", hex::encode(&ec_key_point)); - println!(); // ECDSA SSH public key format: // string ecdsa-sha2-[identifier] @@ -77,7 +78,18 @@ impl Command for CommandImpl { ecc_key_blob.write_string(&ec_key_point); ssh_pub_key.write_bytes(&ecc_key_blob); - println!("ecdsa-sha2-{} {} Yubikey-PIV-{}", ssh_algorithm, STANDARD.encode(&ssh_pub_key), slot_id); + let ssh_pub_key_sha256 = sha256_bytes(&ssh_pub_key); + information!("SSH key SHA256: {} (base64)", STANDARD.encode(&ssh_pub_key_sha256)); + information!("SSH key SHA256: {} (hex)", hex::encode(&ssh_pub_key_sha256)); + println!(); + + println!( + "{}ecdsa-sha2-{} {} Yubikey-PIV-{}", + if ca { "cert-authority " } else { "" }, + ssh_algorithm, + STANDARD.encode(&ssh_pub_key), + slot_id + ); Ok(None) } diff --git a/src/main.rs b/src/main.rs index 98afd09..c9d6b5c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,6 +42,7 @@ mod cmd_challconfig; mod cmd_sshagent; mod cmd_sshparsesign; mod cmd_sshpivsign; +mod cmd_sshpivcert; mod cmd_sshpubkey; mod cmd_pgpageaddress; mod cmd_signjwt; @@ -104,6 +105,7 @@ fn inner_main() -> CommandError { Box::new(cmd_sshagent::CommandImpl), Box::new(cmd_sshparsesign::CommandImpl), Box::new(cmd_sshpivsign::CommandImpl), + Box::new(cmd_sshpivcert::CommandImpl), Box::new(cmd_sshpubkey::CommandImpl), Box::new(cmd_pgpageaddress::CommandImpl), Box::new(cmd_signjwt::CommandImpl),