mirror of
https://gitlab.gnome.org/World/Authenticator
synced 2024-07-05 00:58:53 +00:00
add encrypted import of aegis files
This commit is contained in:
parent
5b658dd295
commit
0cf7ad7654
203
Cargo.lock
generated
203
Cargo.lock
generated
|
@ -23,6 +23,15 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aead"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aes"
|
name = "aes"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
@ -31,7 +40,19 @@ checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-soft",
|
"aes-soft",
|
||||||
"aesni",
|
"aesni",
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes"
|
||||||
|
version = "0.7.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cipher 0.3.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -40,11 +61,25 @@ version = "0.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
|
checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aead",
|
"aead 0.3.2",
|
||||||
"aes",
|
"aes 0.6.0",
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
"ctr",
|
"ctr 0.6.0",
|
||||||
"ghash",
|
"ghash 0.3.1",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aes-gcm"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df5f85a83a7d8b0442b6aa7b504b8212c1733da07b98aae43d4bc21b2cb3cdf6"
|
||||||
|
dependencies = [
|
||||||
|
"aead 0.4.3",
|
||||||
|
"aes 0.7.5",
|
||||||
|
"cipher 0.3.0",
|
||||||
|
"ctr 0.8.0",
|
||||||
|
"ghash 0.4.4",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -54,7 +89,7 @@ version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
|
checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -64,7 +99,7 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
|
checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -297,9 +332,11 @@ dependencies = [
|
||||||
name = "authenticator"
|
name = "authenticator"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aes-gcm 0.9.4",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ashpd",
|
"ashpd",
|
||||||
"async-std",
|
"async-std",
|
||||||
|
"base64",
|
||||||
"binascii",
|
"binascii",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
|
@ -321,6 +358,7 @@ dependencies = [
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"ring",
|
"ring",
|
||||||
"rust-argon2",
|
"rust-argon2",
|
||||||
|
"scrypt",
|
||||||
"search-provider",
|
"search-provider",
|
||||||
"secret-service",
|
"secret-service",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -423,6 +461,15 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1d36a02058e76b040de25a4464ba1c80935655595b661505c8b39b664828b95"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-modes"
|
name = "block-modes"
|
||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
|
@ -430,7 +477,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
|
checksum = "57a0e8073e8baa88212fb5823574c02ebccb395136ba9a164ab89379ec6072f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-padding",
|
"block-padding",
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -585,6 +632,15 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cipher"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clang-sys"
|
name = "clang-sys"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
|
@ -644,13 +700,13 @@ version = "0.14.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
|
checksum = "03a5d7b21829bc7b4bf4754a978a241ae54ea55a40f92bb20216e54096f4b951"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes-gcm",
|
"aes-gcm 0.8.0",
|
||||||
"base64",
|
"base64",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"hmac",
|
"hmac 0.10.1",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"sha2",
|
"sha2 0.9.9",
|
||||||
"time",
|
"time",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
@ -729,6 +785,15 @@ dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "683d6b536309245c849479fba3da410962a43ed8e51c26b729208ec0ac2798d0"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-mac"
|
name = "crypto-mac"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
|
@ -755,7 +820,16 @@ version = "0.6.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
|
checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cipher",
|
"cipher 0.2.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
|
@ -862,6 +936,18 @@ dependencies = [
|
||||||
"generic-array",
|
"generic-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b697d66081d42af4fba142d56918a3cb21dc8eb63372c6b85d14f44fb9c5979b"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer 0.10.0",
|
||||||
|
"crypto-common",
|
||||||
|
"generic-array",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "discard"
|
name = "discard"
|
||||||
version = "1.0.4"
|
version = "1.0.4"
|
||||||
|
@ -1332,7 +1418,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
|
checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
"polyval",
|
"polyval 0.4.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ghash"
|
||||||
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
|
||||||
|
dependencies = [
|
||||||
|
"opaque-debug",
|
||||||
|
"polyval 0.5.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1716,6 +1812,9 @@ name = "hex"
|
||||||
version = "0.4.3"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hkdf"
|
name = "hkdf"
|
||||||
|
@ -1723,8 +1822,8 @@ version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"digest",
|
"digest 0.9.0",
|
||||||
"hmac",
|
"hmac 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1734,7 +1833,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
|
checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crypto-mac",
|
"crypto-mac",
|
||||||
"digest",
|
"digest 0.9.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ddca131f3e7f2ce2df364b57949a9d47915cfbd35e46cfee355ccebbf794d6a2"
|
||||||
|
dependencies = [
|
||||||
|
"digest 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2493,6 +2601,15 @@ version = "1.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4628cc3cf953b82edcd3c1388c5715401420ce5524fedbab426bd5aba017434"
|
||||||
|
dependencies = [
|
||||||
|
"digest 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "peeking_take_while"
|
name = "peeking_take_while"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -2617,6 +2734,18 @@ dependencies = [
|
||||||
"universal-hash",
|
"universal-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "polyval"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"opaque-debug",
|
||||||
|
"universal-hash",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.16"
|
version = "0.2.16"
|
||||||
|
@ -2946,6 +3075,15 @@ version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "salsa20"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686"
|
||||||
|
dependencies = [
|
||||||
|
"cipher 0.3.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "schannel"
|
name = "schannel"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
|
@ -2983,6 +3121,18 @@ version = "1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scrypt"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e73d6d7c6311ebdbd9184ad6c4447b2f36337e327bda107d3ba9e3c374f9d325"
|
||||||
|
dependencies = [
|
||||||
|
"hmac 0.12.0",
|
||||||
|
"pbkdf2",
|
||||||
|
"salsa20",
|
||||||
|
"sha2 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "search-provider"
|
name = "search-provider"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -3002,14 +3152,14 @@ version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec"
|
checksum = "2400fb1bf2a87b303ada204946294f932ade4929477e9e2bf66d7b49a66656ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aes",
|
"aes 0.6.0",
|
||||||
"block-modes",
|
"block-modes",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"num",
|
"num",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"serde",
|
"serde",
|
||||||
"sha2",
|
"sha2 0.9.9",
|
||||||
"zbus 1.9.1",
|
"zbus 1.9.1",
|
||||||
"zbus_macros 1.9.1",
|
"zbus_macros 1.9.1",
|
||||||
"zvariant 2.10.0",
|
"zvariant 2.10.0",
|
||||||
|
@ -3135,13 +3285,24 @@ version = "0.9.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
|
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer 0.9.0",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"digest",
|
"digest 0.9.0",
|
||||||
"opaque-debug",
|
"opaque-debug",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "99c3bd8169c58782adad9290a9af5939994036b76187f7b4f0e6de91dbbfc0ec"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shlex"
|
name = "shlex"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
|
|
@ -18,7 +18,7 @@ gst4gtk = { package = "gst-plugin-gtk4", version = "0.1"}
|
||||||
gtk = {package = "gtk4", version = "0.4"}
|
gtk = {package = "gtk4", version = "0.4"}
|
||||||
gtk-macros = "0.3"
|
gtk-macros = "0.3"
|
||||||
search-provider = "0.3"
|
search-provider = "0.3"
|
||||||
hex = "0.4"
|
hex = { version = "0.4.3", features = [ "serde" ] }
|
||||||
image = "0.23"
|
image = "0.23"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
once_cell = "1.9"
|
once_cell = "1.9"
|
||||||
|
@ -37,3 +37,6 @@ unicase = "2.6"
|
||||||
url = "2.2"
|
url = "2.2"
|
||||||
zbar-rust = "0.0"
|
zbar-rust = "0.0"
|
||||||
svg_metadata = "0.4"
|
svg_metadata = "0.4"
|
||||||
|
scrypt = { version = "0.8.1", default-features = false }
|
||||||
|
aes-gcm = "0.9.4"
|
||||||
|
base64 = "0.13.0"
|
||||||
|
|
|
@ -5,46 +5,88 @@
|
||||||
|
|
||||||
use super::{Backupable, Restorable, RestorableItem};
|
use super::{Backupable, Restorable, RestorableItem};
|
||||||
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
|
use crate::models::{Account, Algorithm, OTPMethod, Provider, ProvidersModel};
|
||||||
|
use aes_gcm::aead::Aead;
|
||||||
|
use aes_gcm::NewAead;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use gettextrs::gettext;
|
use gettextrs::gettext;
|
||||||
use gtk::{glib::Cast, prelude::*};
|
use gtk::{glib::Cast, prelude::*};
|
||||||
use serde::{Deserialize, Serialize};
|
use hex;
|
||||||
use log;
|
use log;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
/// Root of the Aegis JSON Backup Format
|
/// Root of the Aegis JSON Backup Format
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct Aegis {
|
#[serde(untagged)]
|
||||||
pub version: u32,
|
pub enum Aegis {
|
||||||
pub header: std::collections::HashMap<String, serde_json::Value>,
|
/// Plaintext version of the JSON format.
|
||||||
pub db: AegisDatabase,
|
Plaintext {
|
||||||
|
version: u32,
|
||||||
|
header: std::collections::HashMap<String, serde_json::Value>,
|
||||||
|
db: Database,
|
||||||
|
},
|
||||||
|
/// Encrypted version of the JSON format. `db` is simply a base64 encoded string with encrypted AegisDatabase.
|
||||||
|
Encrypted {
|
||||||
|
version: u32,
|
||||||
|
header: HeaderEncrypted,
|
||||||
|
db: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Header of the Aegis JSON File
|
/// Header of the Encrypted Aegis JSON File
|
||||||
///
|
///
|
||||||
/// Contains all necessary information for encrypting / decrypting the vault (db field).
|
/// Contains all necessary information for encrypting / decrypting the vault (db field).
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct AegisHeader {
|
pub struct HeaderEncrypted {
|
||||||
pub slots: Vec<std::collections::HashMap<String, serde_json::Value>>,
|
pub slots: Vec<HeaderSlot>,
|
||||||
pub params: std::collections::HashMap<String, serde_json::Value>
|
pub params: HeaderParam,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Header Slots
|
||||||
|
///
|
||||||
|
/// Containts information to decrypt the master key.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type")]
|
||||||
|
pub enum HeaderSlot {
|
||||||
|
// We are not interested in this field. Thus, we omit the other information.
|
||||||
|
#[serde(rename = "2")]
|
||||||
|
Biometric,
|
||||||
|
#[serde(rename = "1")]
|
||||||
|
Password(HeaderSlotPassword),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct HeaderSlotPassword {
|
||||||
|
pub uuid: String,
|
||||||
|
#[serde(with = "hex::serde")]
|
||||||
|
pub key: [u8; 32],
|
||||||
|
// First tuple entry is the nonce, the second is the tag.
|
||||||
|
pub key_params: HeaderParam,
|
||||||
|
pub n: u32,
|
||||||
|
pub r: u32,
|
||||||
|
pub p: u32,
|
||||||
|
#[serde(with = "hex::serde")]
|
||||||
|
pub salt: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parameters to Database Encryption
|
||||||
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub struct HeaderParam {
|
||||||
|
#[serde(with = "hex::serde")]
|
||||||
|
pub nonce: [u8; 12],
|
||||||
|
#[serde(with = "hex::serde")]
|
||||||
|
pub tag: [u8; 16],
|
||||||
|
}
|
||||||
|
|
||||||
/// Contains All OTP Entries
|
/// Contains All OTP Entries
|
||||||
///
|
|
||||||
/// This database can be either encrypted or in plaintext format.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(untagged)]
|
pub struct Database {
|
||||||
pub enum AegisDatabase {
|
pub version: u32,
|
||||||
Encrypted(String),
|
pub entries: Vec<Item>,
|
||||||
Plaintext {
|
|
||||||
version: u32,
|
|
||||||
entries: Vec<AegisItem>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An OTP Entry
|
/// An OTP Entry
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct AegisItem {
|
pub struct Item {
|
||||||
#[serde(rename = "type")]
|
#[serde(rename = "type")]
|
||||||
pub method: OTPMethod,
|
pub method: OTPMethod,
|
||||||
// UUID is omitted
|
// UUID is omitted
|
||||||
|
@ -58,15 +100,15 @@ pub struct AegisItem {
|
||||||
// Icon:
|
// Icon:
|
||||||
// TODO: Aegis encodes icons as JPEG's encoded in Base64 with padding. Does authenticator support
|
// TODO: Aegis encodes icons as JPEG's encoded in Base64 with padding. Does authenticator support
|
||||||
// this?
|
// this?
|
||||||
// TODO tags are not importet/exported right now.
|
// TODO tags are not imported/exported right now.
|
||||||
#[serde(rename = "icon")]
|
#[serde(rename = "icon")]
|
||||||
pub thumbnail: Option<String>,
|
pub thumbnail: Option<String>,
|
||||||
pub info: AegisDetail,
|
pub info: Detail,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// OTP Entry Details
|
/// OTP Entry Details
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct AegisDetail {
|
pub struct Detail {
|
||||||
pub secret: String,
|
pub secret: String,
|
||||||
#[serde(rename = "algo")]
|
#[serde(rename = "algo")]
|
||||||
pub algorithm: Algorithm,
|
pub algorithm: Algorithm,
|
||||||
|
@ -76,35 +118,139 @@ pub struct AegisDetail {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Aegis {
|
impl Aegis {
|
||||||
fn restore_from_slice(data: &[u8]) -> Result<Vec<AegisItem>> {
|
fn restore_from_slice(data: &[u8], password: Option<&str>) -> Result<Vec<Item>> {
|
||||||
// TODO check whether file / database is encrypted by aegis
|
// TODO check whether file / database is encrypted by aegis
|
||||||
let aegis_root: Aegis = serde_json::de::from_slice(data)?;
|
let aegis_root: Aegis = serde_json::de::from_slice(data)?;
|
||||||
|
|
||||||
// Check for correct aegis file version and correct database version.
|
// Check whether file is encrypted or in plaintext
|
||||||
// Additionally, we check whether the file is encrypted. We can't open / decrypt them yet,
|
match aegis_root {
|
||||||
// because there is no UI possibility to enter the password.
|
Aegis::Plaintext { version, db, .. } => {
|
||||||
log::info!("Found aegis database version {}", aegis_root.version);
|
log::info!(
|
||||||
if aegis_root.version != 1 {
|
"Found unencrypted aegis vault with version {} and database version {}.",
|
||||||
anyhow::bail!(
|
version,
|
||||||
"Aegis file version expected to be 1. Found {} instead.",
|
db.version
|
||||||
aegis_root.version
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
match aegis_root.db {
|
// Check for correct aegis vault version and correct database version.
|
||||||
AegisDatabase::Encrypted(_) => anyhow::bail!(
|
if version != 1 {
|
||||||
"Aegis file is encrypted. Authenticator supports only plaintext files."
|
anyhow::bail!(
|
||||||
),
|
"Aegis vault version expected to be 1. Found {} instead.",
|
||||||
AegisDatabase::Plaintext { version, entries } if version == 2 => Ok(entries),
|
version
|
||||||
AegisDatabase::Plaintext { version, .. } => anyhow::bail!(
|
);
|
||||||
"Aegis file version expected to be 2. Found {} instead.",
|
// There is no version 0. So this should be okay ...
|
||||||
version
|
} else if db.version > 2 {
|
||||||
),
|
anyhow::bail!(
|
||||||
|
"Aegis database version expected to be 1 or 2. Found {} instead.",
|
||||||
|
db.version
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Ok(db.entries)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Aegis::Encrypted {
|
||||||
|
version,
|
||||||
|
header,
|
||||||
|
db,
|
||||||
|
} => {
|
||||||
|
log::info!("Found encrypted aegis vault with version {}.", version);
|
||||||
|
|
||||||
|
// Check for correct aegis vault version and whether a password was supplied.
|
||||||
|
if version != 1 {
|
||||||
|
anyhow::bail!(
|
||||||
|
"Aegis vault version expected to be 1. Found {} instead.",
|
||||||
|
version
|
||||||
|
);
|
||||||
|
} else if password.is_none() {
|
||||||
|
anyhow::bail!("Found encrypted aegis database but no password given.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ciphertext is stored in base64, we have to decode it.
|
||||||
|
let mut ciphertext =
|
||||||
|
base64::decode(db).expect("Cannot decode (base64) encrypted database");
|
||||||
|
|
||||||
|
// Add the encryption tag
|
||||||
|
ciphertext.append(&mut header.params.tag.into());
|
||||||
|
|
||||||
|
// Find slots with type password and derive the corresponding key. This key is used
|
||||||
|
// to decrypt the master key which in turn can be used to decrypt the database.
|
||||||
|
let master_keys: Vec<Vec<u8>> = header
|
||||||
|
.slots
|
||||||
|
.iter()
|
||||||
|
.map(|slot| match slot {
|
||||||
|
HeaderSlot::Password(slot) => slot,
|
||||||
|
_ => unreachable!("All biometric slots are filtered by serde."),
|
||||||
|
})
|
||||||
|
.map(|slot| {
|
||||||
|
log::info!("Found possible master key with UUID {}.", slot.uuid);
|
||||||
|
|
||||||
|
// Create parameters for scrypt function and derive decryption key for master key
|
||||||
|
let params = scrypt::Params::new(
|
||||||
|
// TODO log2 for u64 is not stable yet. Change this in the future.
|
||||||
|
(slot.n as f64).log2() as u8, // Defaults to 15 by aegis
|
||||||
|
slot.r, // Defaults to 8 by aegis
|
||||||
|
slot.p, // Defaults to 1 by aegis
|
||||||
|
)
|
||||||
|
.expect("Invalid scrypt params in header");
|
||||||
|
let mut temp_key: [u8; 32] = [0u8; 32];
|
||||||
|
scrypt::scrypt(
|
||||||
|
password.unwrap().as_bytes(),
|
||||||
|
&slot.salt,
|
||||||
|
¶ms,
|
||||||
|
&mut temp_key,
|
||||||
|
)
|
||||||
|
.expect("Scrypt key derivation failed");
|
||||||
|
|
||||||
|
// Now, try to decrypt the master key.
|
||||||
|
let cipher = aes_gcm::Aes256Gcm::new(aes_gcm::Key::from_slice(&temp_key));
|
||||||
|
let mut ciphertext: Vec<u8> = slot.key.to_vec();
|
||||||
|
ciphertext.append(&mut slot.key_params.tag.to_vec());
|
||||||
|
let master_key = cipher
|
||||||
|
.decrypt(
|
||||||
|
aes_gcm::Nonce::from_slice(&slot.key_params.nonce),
|
||||||
|
ciphertext.as_ref(),
|
||||||
|
)
|
||||||
|
.expect("failed decrypting master key");
|
||||||
|
|
||||||
|
master_key
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Choose the first valid master key. I don't think there are aegis installations with two valid password slots.
|
||||||
|
log::info!(
|
||||||
|
"Found {} valid password slots / master keys. Using only the first one.",
|
||||||
|
master_keys.len()
|
||||||
|
);
|
||||||
|
let master_key = &master_keys[0];
|
||||||
|
|
||||||
|
// Try to decrypt the database with this master key
|
||||||
|
let cipher = aes_gcm::Aes256Gcm::new(aes_gcm::Key::from_slice(master_key));
|
||||||
|
let plaintext = cipher
|
||||||
|
.decrypt(
|
||||||
|
aes_gcm::Nonce::from_slice(&header.params.nonce),
|
||||||
|
ciphertext.as_ref(),
|
||||||
|
)
|
||||||
|
.expect("failed decrypting database");
|
||||||
|
|
||||||
|
// Now, we have the decrypted string. Trying to load it with JSON.
|
||||||
|
let db: Database = serde_json::de::from_slice(&plaintext).unwrap();
|
||||||
|
|
||||||
|
// Check version of the database
|
||||||
|
log::info!("Found aegis database with version {}.", db.version);
|
||||||
|
if version > 2 {
|
||||||
|
anyhow::bail!(
|
||||||
|
"Aegis database version expected to be 1 or 2. Found {} instead.",
|
||||||
|
db.version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return items
|
||||||
|
Ok(db.entries)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RestorableItem for AegisItem {
|
impl RestorableItem for Item {
|
||||||
fn account(&self) -> String {
|
fn account(&self) -> String {
|
||||||
self.label.clone()
|
self.label.clone()
|
||||||
}
|
}
|
||||||
|
@ -164,15 +310,17 @@ impl Backupable for Aegis {
|
||||||
for j in 0..accounts.n_items() {
|
for j in 0..accounts.n_items() {
|
||||||
let account = accounts.item(j).unwrap().downcast::<Account>().unwrap();
|
let account = accounts.item(j).unwrap().downcast::<Account>().unwrap();
|
||||||
|
|
||||||
let aegis_detail = AegisDetail {
|
let aegis_detail = Detail {
|
||||||
secret: account.token(),
|
secret: account.token(),
|
||||||
algorithm: provider.algorithm(),
|
algorithm: provider.algorithm(),
|
||||||
digits: provider.digits(),
|
digits: provider.digits(),
|
||||||
|
// TODO should be none for hotp
|
||||||
period: Some(provider.period()),
|
period: Some(provider.period()),
|
||||||
|
// TODO should be none for totp
|
||||||
counter: Some(account.counter()),
|
counter: Some(account.counter()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let aegis_item = AegisItem {
|
let aegis_item = Item {
|
||||||
method: provider.method(),
|
method: provider.method(),
|
||||||
label: account.name(),
|
label: account.name(),
|
||||||
issuer: provider.name(),
|
issuer: provider.name(),
|
||||||
|
@ -186,11 +334,15 @@ impl Backupable for Aegis {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create structure around items
|
// Create structure around items
|
||||||
let aegis_db = AegisDatabase::Plaintext {
|
let aegis_db = Database {
|
||||||
version: 2,
|
version: 2,
|
||||||
entries: items,
|
entries: items,
|
||||||
};
|
};
|
||||||
let aegis_root = Aegis {
|
// let aegis_header = AegisHeader {
|
||||||
|
// slots: vec![],
|
||||||
|
// params: std::collections::HashMap::new(),
|
||||||
|
// };
|
||||||
|
let aegis_root = Aegis::Plaintext {
|
||||||
version: 1,
|
version: 1,
|
||||||
header: std::collections::HashMap::from([
|
header: std::collections::HashMap::from([
|
||||||
(String::from("slots"), serde_json::Value::Null),
|
(String::from("slots"), serde_json::Value::Null),
|
||||||
|
@ -215,7 +367,7 @@ impl Backupable for Aegis {
|
||||||
|
|
||||||
impl Restorable for Aegis {
|
impl Restorable for Aegis {
|
||||||
const ENCRYPTABLE: bool = true;
|
const ENCRYPTABLE: bool = true;
|
||||||
type Item = AegisItem;
|
type Item = Item;
|
||||||
|
|
||||||
fn identifier() -> String {
|
fn identifier() -> String {
|
||||||
"Aegis".to_string()
|
"Aegis".to_string()
|
||||||
|
@ -230,9 +382,9 @@ impl Restorable for Aegis {
|
||||||
gettext("From a JSON file containing plain-text or encrypted fields.")
|
gettext("From a JSON file containing plain-text or encrypted fields.")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn restore(from: >k::gio::File, _key: Option<&str>) -> Result<Vec<Self::Item>> {
|
fn restore(from: >k::gio::File, key: Option<&str>) -> Result<Vec<Self::Item>> {
|
||||||
let (data, _) = from.load_contents(gtk::gio::Cancellable::NONE)?;
|
let (data, _) = from.load_contents(gtk::gio::Cancellable::NONE)?;
|
||||||
Aegis::restore_from_slice(&data)
|
Aegis::restore_from_slice(&data, key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +446,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
let aegis_items = Aegis::restore_from_slice(&aegis_data.as_bytes())
|
let aegis_items = Aegis::restore_from_slice(&aegis_data.as_bytes(), None)
|
||||||
.expect("Restoring from json should work");
|
.expect("Restoring from json should work");
|
||||||
|
|
||||||
assert_eq!(aegis_items[0].account(), "Bob");
|
assert_eq!(aegis_items[0].account(), "Bob");
|
||||||
|
@ -326,8 +478,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic]
|
fn restore_encrypted_file() {
|
||||||
fn detect_encrypted_file() {
|
|
||||||
// See https://github.com/beemdevelopment/Aegis/blob/master/app/src/test/resources/com/beemdevelopment/aegis/importers/aegis_encrypted.json
|
// See https://github.com/beemdevelopment/Aegis/blob/master/app/src/test/resources/com/beemdevelopment/aegis/importers/aegis_encrypted.json
|
||||||
// for this example file.
|
// for this example file.
|
||||||
let aegis_data = r#"{
|
let aegis_data = r#"{
|
||||||
|
@ -357,8 +508,35 @@ mod tests {
|
||||||
"db": "RtGfUrZ01nzRnvHjPJGyWjfa6shQ7NYwa491CgAWNBM8OeGZVIHhnDAVlVWNlSoq2V097p5Yq5m+SFl5g9nBBBQBNePQnj6CCvu1NfNtoA6R3hyp77gd+e+O2MRnOGH1Z1laV2Tl6p3q8IUHWgAJ36LbUxiCXmfh7bWm198uA4bgLwrEmo04MrqeYXggLuXrJrp6dUJQFD72dgoPbHijlSycY5GLel3ZbAXRsUHszd+xdywpj7\/TYa4OYFel0M0QcCpsKA1LRQz365X9OXPJdTsmVyR4dJ6x5RIVeh39lAYKUf7T4w7BLC8taST5m4J\/VXDueKbvg8R13bNWF0aRHUgeuI9BNzMZINJlzKFKNRknTaJ\/1kEUU0sLkgcaVkX\/DVTGG+pWi5MHijicrK0i4LHN3CUwV2\/\/ZNJCGXM5ErsKMOnJfma52gMdifPiXU317Klvc5oOZFYGnhbhJ2WtPIuqjdvnfuLat2JxA7Xx3LqquRWGL2113yjzVzGBDCVY6iIdedBEgH8CGD826\/3R3m6dR5sfSggQ2SbtQA\/DZNhLSNSU+bfNScVQvUWfR2Lf7Q\/4FR\/xATAQJ9IIBeL+w2ErLUPjURocFXup5YOBHxFdDjZ2FqhbAq4h3Zn\/BJ57xUcYEA+YtP5uOP2lQwUh\/0vFWizDVotzraO8tZiBZBsODyb69eJrXNwFbIjeUczY6wrJs1+676IilbCsmtoYvWEpUZF4hIi7TYAD+nyXX\/olrkog9omWZk8R7hJ9KRDfckXEc\/XSzWhk3Kmfa7pRNh9wYZsaR7VPZGZebQMuUKfRRci2qMsZOJvQsDBJvVze0xW9SqiySDgGyRX\/DwzuaZEGZZriaLf6ox7LwY2Qi6QpYOYbAaEaXAesCR1DPxFfGKsUHVjF8hKA6ZBXDXdqM3Y+14naIOH9S7UzYn32botoVLOykSjnW6z6M0ZPkz3dwowMJiVQcyD7p+9p4J6f1S81pFS7DP+jF+PTyC3c3q\/dwFhNdoG6iV9eQEAxjUi6MpzvFRsk9RsLcQqYgzJGmRjYeXlKH8k8tTu1A4puo6w3Daz8hZz9NafMgMsuqY0oKVLgdNqFz8yVMsxYfBW\/oW56SuQyyVWyxXjXmbk1vpYCTL5kXvIZWoTmBRRDb0ay5S\/dlD6z\/WR45\/C4AwcCE9m4Yf3zisRNa7AqWLVgkmJxFdfJxjiuPtUIK79s+lIJkyRENEqkvm809qIxDhkQzY8zcCt4oXCEbJUfSG4awBs1VvilJIwe6qi0bNtqXtAb5TctgxTh29A9oGlsRG4o8sHqA1mtjp5QiLWp5Hh6rOH95W6+fnBiOW+Iw0evBTduroWvx37HBTktJz79zGe0l3c0Y6VmiFvB7knmT2CrgP7woRkxGbXxdE9zMPQJM9ursD538MVDdD\/0tdkxHxilt47f1DPo2CKUWU8Q1KMm1zLXfVO8BbGUWIv4YeDKHfMUL\/HcStv5VJY+LbnOEjzGT4e1\/avSQmqBL4G9XNkYmyMhC8tlLQcmMMH4bNfPOO3vi5Pb5E7XveSgxlOHs4F0+nqxnFOAu8494MEtx6u5+B7d8LI\/DhEO5zTDwE+THiKej6vCsFxTZ519rm67HycOwRR4LKrwfDeUEK3X1PzryOD5zcv3PMcSBgZ8EWvTfZ9ygKP8BmRQRpydTbSt8Hj5fTUuajADCP0Ggw+6G7n+5FhExJNd+o9D8d4KgLPOe08M8InW7pLB389TWtSo4v3VNjcmmJNQ26wlPkhO\/xBU1URFR0fXU3eCO+w++IMt\/fOSqSpNF9bWElfWHIQ23ntxVke\/hR9j\/GG3tHGxYS5pL42sJF\/Re\/UlUJTGSQP6up2xVYs6gncQ0zACDOPjLQmQzYhz\/hr8S6EjYfK++yLZmRTjEI7xT9u\/B5YLyOQCYVTaF\/pDEegjsehXM3qJBfsA+XY7F9TRsmM\/MSVaPDkdIJ7zvL9xtaF6bXdZoZ6po3ml8uu41pSkNmMKgyEy5E0UQUTWMPLC8drUoQ\/KWQnVIN6HUXGBjYy6aax\/LYZaBcbZi97FHK0h+wsx3WN\/uQozNkQjwGYE8fwYxRYh1RaFi5PkiCM505ib7e82Yuts0l+cBb6nG1IruDplg9BD\/G9w4vVDePEikhcPyY\/p7AZ4i7u\/bL2YKlbE3HyJa+7dkbWJgGidtRZgu+Fdl2T\/rrRJ4+lVaKPVKGKT7ItZdIeitIYUdRxCzrOf1ItZCC8BWa4PElDAjj2yDNmMYRpXJBe3gQHWs\/H5SZgFuwsfCu23uzNRQYib8SuwIJQDvPiXo7m4oIySO8VyvemcExlbXSlbZbvwVxYavTVfcUpAXI6qlsg2jjk+JZahfKrWNC5COZPdVjdAXCoiKU+HBPmEFCwQv\/7zlSBEiI2piyqd+MPwnP63RdGO+oXYid6hn4Nm8kcOhtRyvYm95p66jzGlEugsfxJCED7MTh3XShqa2tt4lFG25icllzTvIJboRkz5oIB4dZVS9+q2TgGUoX7UCpobD8WkHo\/y0cpTuZr8vzXqx2fObxzPNoVgxJmp9E06G2bhMVHPpT17xbfq\/KhJJn7k1S0sfXPG+SmYlX4U7zNSe1M7JXtLf3uVOLz7Ccjp3yvcdq8nRmVym3Zwsz+vv57FA2A0dy3Db97ypJa9HGaxnnYIZHHzep0gJCeeIKE9L32zGCoUg+cPu9B2lPEgIr64iGiuvKSRwNQpOBktM6qqjQntE0Me6mh426irFQ\/3tcfH9a4lZEwwuU1X+lUBUWQp3n5Ej4BSJEs8E6H0EjBvyk69q3qjy5yi7ROVRis6y6S1v4er77RHQUf3phK5354VJHrp9pR926t5qngH5RVF4eljwtXDs3MkejADJ6stBHa\/w7FcbUClO8U+S4Bidxb3mZCiZkUVTpbzvBfYAiQvAfdkMa49o3a5DXKsbXyUPrmr6fWRfM1fS0Ehp0lUv6BDj0yR13CLMpKDU4GfDrl8UEvwh7gwtBRkuaBFzyMtd3NeE7kIGf9vFs6MEl2dmMDFSDid7MdVSDVTlhaAtp+zsRejKW3OQr5n051FzkUsIFGty9AWOkwjZCbstHYCOtyJnsnXP1i9lRDFBgPpFgmDD+bzzg0g9AOAxzqTiLF7bb1jejfe5qVr5V9+7zLpwRLiYaLkNOmpsqvNMuYVwdqTp6nyoougdgBlvve3EG0k09sFKi2Ep9lq+QkS7zGre2jJDrqgdC08+V4PXHYkP3V3Zjgn1x6RfQ2PE+2zvk1GGEgzcNww3byoYw0Ra5qS5yftMy\/2WahbA8fjUYvtmksFH8VjN3yasZt3sdQLWtv8qXxZscy+pCyjTdyxW+ddFnrWuqMIV3jbGMvngq6dL\/n5+DumjbA1gmBJVOpmyEsc1iwHDS36cNnyi1htGFO\/6\/Va4YPYK7dG6LY387UoBUU9Q9ijrBrSGpzPWYmXBLZ8e1MMPfHIN1WsaTgYO9leg3MAJTjQFTFrQ5dguYpWhlm2sWJT45jrda4uWqduB+aQLzYRWhEDBFzPV3ZgIe0SB+7h04Vm0Pu\/LDRvqaolpZ86CEm+zgjBOKeEGFwzTXxH\/5pBoca1bZ6wvsbVZxJNBeH8\/w=="
|
"db": "RtGfUrZ01nzRnvHjPJGyWjfa6shQ7NYwa491CgAWNBM8OeGZVIHhnDAVlVWNlSoq2V097p5Yq5m+SFl5g9nBBBQBNePQnj6CCvu1NfNtoA6R3hyp77gd+e+O2MRnOGH1Z1laV2Tl6p3q8IUHWgAJ36LbUxiCXmfh7bWm198uA4bgLwrEmo04MrqeYXggLuXrJrp6dUJQFD72dgoPbHijlSycY5GLel3ZbAXRsUHszd+xdywpj7\/TYa4OYFel0M0QcCpsKA1LRQz365X9OXPJdTsmVyR4dJ6x5RIVeh39lAYKUf7T4w7BLC8taST5m4J\/VXDueKbvg8R13bNWF0aRHUgeuI9BNzMZINJlzKFKNRknTaJ\/1kEUU0sLkgcaVkX\/DVTGG+pWi5MHijicrK0i4LHN3CUwV2\/\/ZNJCGXM5ErsKMOnJfma52gMdifPiXU317Klvc5oOZFYGnhbhJ2WtPIuqjdvnfuLat2JxA7Xx3LqquRWGL2113yjzVzGBDCVY6iIdedBEgH8CGD826\/3R3m6dR5sfSggQ2SbtQA\/DZNhLSNSU+bfNScVQvUWfR2Lf7Q\/4FR\/xATAQJ9IIBeL+w2ErLUPjURocFXup5YOBHxFdDjZ2FqhbAq4h3Zn\/BJ57xUcYEA+YtP5uOP2lQwUh\/0vFWizDVotzraO8tZiBZBsODyb69eJrXNwFbIjeUczY6wrJs1+676IilbCsmtoYvWEpUZF4hIi7TYAD+nyXX\/olrkog9omWZk8R7hJ9KRDfckXEc\/XSzWhk3Kmfa7pRNh9wYZsaR7VPZGZebQMuUKfRRci2qMsZOJvQsDBJvVze0xW9SqiySDgGyRX\/DwzuaZEGZZriaLf6ox7LwY2Qi6QpYOYbAaEaXAesCR1DPxFfGKsUHVjF8hKA6ZBXDXdqM3Y+14naIOH9S7UzYn32botoVLOykSjnW6z6M0ZPkz3dwowMJiVQcyD7p+9p4J6f1S81pFS7DP+jF+PTyC3c3q\/dwFhNdoG6iV9eQEAxjUi6MpzvFRsk9RsLcQqYgzJGmRjYeXlKH8k8tTu1A4puo6w3Daz8hZz9NafMgMsuqY0oKVLgdNqFz8yVMsxYfBW\/oW56SuQyyVWyxXjXmbk1vpYCTL5kXvIZWoTmBRRDb0ay5S\/dlD6z\/WR45\/C4AwcCE9m4Yf3zisRNa7AqWLVgkmJxFdfJxjiuPtUIK79s+lIJkyRENEqkvm809qIxDhkQzY8zcCt4oXCEbJUfSG4awBs1VvilJIwe6qi0bNtqXtAb5TctgxTh29A9oGlsRG4o8sHqA1mtjp5QiLWp5Hh6rOH95W6+fnBiOW+Iw0evBTduroWvx37HBTktJz79zGe0l3c0Y6VmiFvB7knmT2CrgP7woRkxGbXxdE9zMPQJM9ursD538MVDdD\/0tdkxHxilt47f1DPo2CKUWU8Q1KMm1zLXfVO8BbGUWIv4YeDKHfMUL\/HcStv5VJY+LbnOEjzGT4e1\/avSQmqBL4G9XNkYmyMhC8tlLQcmMMH4bNfPOO3vi5Pb5E7XveSgxlOHs4F0+nqxnFOAu8494MEtx6u5+B7d8LI\/DhEO5zTDwE+THiKej6vCsFxTZ519rm67HycOwRR4LKrwfDeUEK3X1PzryOD5zcv3PMcSBgZ8EWvTfZ9ygKP8BmRQRpydTbSt8Hj5fTUuajADCP0Ggw+6G7n+5FhExJNd+o9D8d4KgLPOe08M8InW7pLB389TWtSo4v3VNjcmmJNQ26wlPkhO\/xBU1URFR0fXU3eCO+w++IMt\/fOSqSpNF9bWElfWHIQ23ntxVke\/hR9j\/GG3tHGxYS5pL42sJF\/Re\/UlUJTGSQP6up2xVYs6gncQ0zACDOPjLQmQzYhz\/hr8S6EjYfK++yLZmRTjEI7xT9u\/B5YLyOQCYVTaF\/pDEegjsehXM3qJBfsA+XY7F9TRsmM\/MSVaPDkdIJ7zvL9xtaF6bXdZoZ6po3ml8uu41pSkNmMKgyEy5E0UQUTWMPLC8drUoQ\/KWQnVIN6HUXGBjYy6aax\/LYZaBcbZi97FHK0h+wsx3WN\/uQozNkQjwGYE8fwYxRYh1RaFi5PkiCM505ib7e82Yuts0l+cBb6nG1IruDplg9BD\/G9w4vVDePEikhcPyY\/p7AZ4i7u\/bL2YKlbE3HyJa+7dkbWJgGidtRZgu+Fdl2T\/rrRJ4+lVaKPVKGKT7ItZdIeitIYUdRxCzrOf1ItZCC8BWa4PElDAjj2yDNmMYRpXJBe3gQHWs\/H5SZgFuwsfCu23uzNRQYib8SuwIJQDvPiXo7m4oIySO8VyvemcExlbXSlbZbvwVxYavTVfcUpAXI6qlsg2jjk+JZahfKrWNC5COZPdVjdAXCoiKU+HBPmEFCwQv\/7zlSBEiI2piyqd+MPwnP63RdGO+oXYid6hn4Nm8kcOhtRyvYm95p66jzGlEugsfxJCED7MTh3XShqa2tt4lFG25icllzTvIJboRkz5oIB4dZVS9+q2TgGUoX7UCpobD8WkHo\/y0cpTuZr8vzXqx2fObxzPNoVgxJmp9E06G2bhMVHPpT17xbfq\/KhJJn7k1S0sfXPG+SmYlX4U7zNSe1M7JXtLf3uVOLz7Ccjp3yvcdq8nRmVym3Zwsz+vv57FA2A0dy3Db97ypJa9HGaxnnYIZHHzep0gJCeeIKE9L32zGCoUg+cPu9B2lPEgIr64iGiuvKSRwNQpOBktM6qqjQntE0Me6mh426irFQ\/3tcfH9a4lZEwwuU1X+lUBUWQp3n5Ej4BSJEs8E6H0EjBvyk69q3qjy5yi7ROVRis6y6S1v4er77RHQUf3phK5354VJHrp9pR926t5qngH5RVF4eljwtXDs3MkejADJ6stBHa\/w7FcbUClO8U+S4Bidxb3mZCiZkUVTpbzvBfYAiQvAfdkMa49o3a5DXKsbXyUPrmr6fWRfM1fS0Ehp0lUv6BDj0yR13CLMpKDU4GfDrl8UEvwh7gwtBRkuaBFzyMtd3NeE7kIGf9vFs6MEl2dmMDFSDid7MdVSDVTlhaAtp+zsRejKW3OQr5n051FzkUsIFGty9AWOkwjZCbstHYCOtyJnsnXP1i9lRDFBgPpFgmDD+bzzg0g9AOAxzqTiLF7bb1jejfe5qVr5V9+7zLpwRLiYaLkNOmpsqvNMuYVwdqTp6nyoougdgBlvve3EG0k09sFKi2Ep9lq+QkS7zGre2jJDrqgdC08+V4PXHYkP3V3Zjgn1x6RfQ2PE+2zvk1GGEgzcNww3byoYw0Ra5qS5yftMy\/2WahbA8fjUYvtmksFH8VjN3yasZt3sdQLWtv8qXxZscy+pCyjTdyxW+ddFnrWuqMIV3jbGMvngq6dL\/n5+DumjbA1gmBJVOpmyEsc1iwHDS36cNnyi1htGFO\/6\/Va4YPYK7dG6LY387UoBUU9Q9ijrBrSGpzPWYmXBLZ8e1MMPfHIN1WsaTgYO9leg3MAJTjQFTFrQ5dguYpWhlm2sWJT45jrda4uWqduB+aQLzYRWhEDBFzPV3ZgIe0SB+7h04Vm0Pu\/LDRvqaolpZ86CEm+zgjBOKeEGFwzTXxH\/5pBoca1bZ6wvsbVZxJNBeH8\/w=="
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
Aegis::restore_from_slice(&aegis_data.as_bytes())
|
let aegis_items = Aegis::restore_from_slice(&aegis_data.as_bytes(), Some("test"))
|
||||||
.expect("Reading encrypted file should fail.");
|
.expect("Restoring from encrypted json should work");
|
||||||
|
|
||||||
|
assert_eq!(aegis_items[0].account(), "Mason");
|
||||||
|
assert_eq!(aegis_items[0].issuer(), "Deno");
|
||||||
|
assert_eq!(aegis_items[0].secret(), "4SJHB4GSD43FZBAI7C2HLRJGPQ");
|
||||||
|
assert_eq!(aegis_items[0].period(), Some(30));
|
||||||
|
assert_eq!(aegis_items[0].algorithm(), Algorithm::SHA1);
|
||||||
|
assert_eq!(aegis_items[0].digits(), Some(6));
|
||||||
|
assert_eq!(aegis_items[0].counter(), None);
|
||||||
|
assert_eq!(aegis_items[0].method(), OTPMethod::TOTP);
|
||||||
|
|
||||||
|
assert_eq!(aegis_items[3].account(), "James");
|
||||||
|
assert_eq!(aegis_items[3].issuer(), "Issuu");
|
||||||
|
assert_eq!(aegis_items[3].secret(), "YOOMIXWS5GN6RTBPUFFWKTW5M4");
|
||||||
|
assert_eq!(aegis_items[3].period(), None);
|
||||||
|
assert_eq!(aegis_items[3].algorithm(), Algorithm::SHA1);
|
||||||
|
assert_eq!(aegis_items[3].digits(), Some(6));
|
||||||
|
assert_eq!(aegis_items[3].counter(), Some(1));
|
||||||
|
assert_eq!(aegis_items[3].method(), OTPMethod::HOTP);
|
||||||
|
|
||||||
|
assert_eq!(aegis_items[6].account(), "Sophia");
|
||||||
|
assert_eq!(aegis_items[6].issuer(), "Boeing");
|
||||||
|
assert_eq!(aegis_items[6].secret(), "JRZCL47CMXVOQMNPZR2F7J4RGI");
|
||||||
|
assert_eq!(aegis_items[6].period(), Some(30));
|
||||||
|
assert_eq!(aegis_items[6].algorithm(), Algorithm::SHA1);
|
||||||
|
assert_eq!(aegis_items[6].digits(), Some(5));
|
||||||
|
assert_eq!(aegis_items[6].counter(), None);
|
||||||
|
assert_eq!(aegis_items[6].method(), OTPMethod::Steam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: add tests for importing
|
// TODO: add tests for importing
|
||||||
|
|
Loading…
Reference in New Issue
Block a user