Prepare 0.1.0 for crates.io publish
Add dual MIT/Apache-2.0 license files and a crates.io README. Bump dependencies to current: rand 0.8->0.10, aes-gcm 0.10->0.11, base64 0.22->0.23. Add keywords, categories, readme, rust-version fields to Cargo.toml. Migrate encryption.rs and test_vectors.rs to the new rand/aes-gcm/base64 APIs.
This commit is contained in:
1 parent
110146870a
commit
31d1991394
7 files changed
+516
-78
No files matched your search
Generated
+135
-50
@@ -4,30 +4,30 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "aead"
|
||||
version = "0.5.2"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||
checksum = "1973cfbc1a2daf9cf550e74e1f088c28e7f7d8c1e1418fb6c9dc5184b7e84c99"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
"crypto-common 0.2.2",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.4"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||
checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"cpubits",
|
||||
"cpufeatures 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aes-gcm"
|
||||
version = "0.10.3"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
|
||||
checksum = "fdf011db2e21ce0d575593d749db5554b47fed37aff429e4dc50bc91ac93a028"
|
||||
dependencies = [
|
||||
"aead",
|
||||
"aes",
|
||||
@@ -47,7 +47,7 @@ dependencies = [
|
||||
"ed25519-bip32",
|
||||
"hex",
|
||||
"hmac",
|
||||
"rand",
|
||||
"rand 0.10.2",
|
||||
"secp256k1",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -64,9 +64,9 @@ checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.22.1"
|
||||
version = "0.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5"
|
||||
|
||||
[[package]]
|
||||
name = "bip39"
|
||||
@@ -75,8 +75,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90dbd31c98227229239363921e60fcf5e558e43ec69094d46fc4996f08d1d5bc"
|
||||
dependencies = [
|
||||
"bitcoin_hashes",
|
||||
"rand",
|
||||
"rand_core",
|
||||
"rand 0.8.7",
|
||||
"rand_core 0.6.4",
|
||||
"serde",
|
||||
"unicode-normalization",
|
||||
"zeroize",
|
||||
@@ -100,6 +100,15 @@ dependencies = [
|
||||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.4.0"
|
||||
@@ -118,14 +127,27 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"block-buffer 0.12.1",
|
||||
"crypto-common 0.2.2",
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmov"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a"
|
||||
|
||||
[[package]]
|
||||
name = "cpubits"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
@@ -135,6 +157,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
@@ -142,10 +173,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"hybrid-array",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptoxide"
|
||||
version = "0.6.2"
|
||||
@@ -154,21 +195,30 @@ checksum = "93f80e26fec88f5ae9450cd5f4e59f5c6421abafc919ea68a3edd521f9580c9b"
|
||||
|
||||
[[package]]
|
||||
name = "ctr"
|
||||
version = "0.9.2"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
|
||||
checksum = "baaca1c4b237092596f64d571e9db6ce4109c4ef9742e27590f1709594461f21"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctutils"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
|
||||
dependencies = [
|
||||
"cmov",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
"block-buffer 0.10.4",
|
||||
"crypto-common 0.1.7",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
@@ -209,12 +259,23 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.5.1"
|
||||
name = "getrandom"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
|
||||
checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ghash"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2eecf2d5dc9b66b732b97707a0210906b1d30523eb773193ab777c0c84b3e8d5"
|
||||
dependencies = [
|
||||
"opaque-debug",
|
||||
"polyval",
|
||||
]
|
||||
|
||||
@@ -243,12 +304,21 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
name = "hybrid-array"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -269,21 +339,14 @@ version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381"
|
||||
|
||||
[[package]]
|
||||
name = "polyval"
|
||||
version = "0.6.2"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
|
||||
checksum = "f0fa31d631f2b2cb2a544d0aa321ce847a94764d701ca2becc411138b93d49cd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"opaque-debug",
|
||||
"cpubits",
|
||||
"cpufeatures 0.3.0",
|
||||
"universal-hash",
|
||||
]
|
||||
|
||||
@@ -314,6 +377,12 @@ dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
version = "6.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.7"
|
||||
@@ -322,7 +391,17 @@ checksum = "22f6172bdec972074665ed81ed53b71da00bfc44b65a753cfde883ec4c702a1a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||
dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -332,7 +411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -341,9 +420,15 @@ version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69"
|
||||
|
||||
[[package]]
|
||||
name = "secp256k1"
|
||||
version = "0.29.1"
|
||||
@@ -412,7 +497,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"cpufeatures 0.2.17",
|
||||
"digest",
|
||||
]
|
||||
|
||||
@@ -508,12 +593,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "universal-hash"
|
||||
version = "0.5.1"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea"
|
||||
checksum = "f4987bdc12753382e0bec4a65c50738ffaabc998b9cdd1f952fb5f39b0048a96"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"subtle",
|
||||
"crypto-common 0.2.2",
|
||||
"ctutils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+7
-3
@@ -2,9 +2,13 @@
|
||||
name = "alkvault"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
rust-version = "1.85"
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Local key vault: BIP39 mnemonic generation, SLIP-0010 Ed25519 HD key derivation, AES-256-GCM encryption for securing provider keys, credentials, and identity material"
|
||||
repository = "https://git.alk.dev/alkdev/alkvault"
|
||||
readme = "README.md"
|
||||
keywords = ["vault", "bip39", "ed25519", "slip-0010", "encryption"]
|
||||
categories = ["cryptography", "authentication"]
|
||||
|
||||
[lib]
|
||||
name = "alkvault"
|
||||
@@ -16,15 +20,15 @@ secp256k1 = ["dep:secp256k1"]
|
||||
[dependencies]
|
||||
bip39 = { version = "2", features = ["rand", "zeroize"] }
|
||||
ed25519-bip32 = "0.4"
|
||||
aes-gcm = "0.10"
|
||||
aes-gcm = "0.11"
|
||||
sha2 = "0.10"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
thiserror = "2"
|
||||
zeroize = { version = "1", features = ["derive"] }
|
||||
hmac = "0.12"
|
||||
rand = "0.8"
|
||||
base64 = "0.22"
|
||||
rand = { version = "0.10", default-features = false, features = ["sys_rng"] }
|
||||
base64 = "0.23"
|
||||
secp256k1 = { version = "0.29", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name), or refer to, the Work.
|
||||
(Note: Derivative Works shall not include works that remain separable from,
|
||||
or merely link (or bind by name) to the interfaces of, the Work and
|
||||
Derivative Works thereof.)
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to the Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by the Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2025-2026 Alk Development
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025-2026 Alk Development
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,130 @@
|
||||
# alkvault
|
||||
|
||||
Local key vault: BIP39 mnemonic generation, SLIP-0010 Ed25519 HD key
|
||||
derivation, and AES-256-GCM encryption for securing provider keys,
|
||||
credentials, and identity material.
|
||||
|
||||
`alkvault` is a standalone crate with **zero network dependencies**. It
|
||||
holds the master seed — the root of trust for all derived keys and
|
||||
encrypted credentials — and provides the cryptographic primitives and a
|
||||
runtime API for managing it. Nothing important goes in env vars.
|
||||
|
||||
## What it is
|
||||
|
||||
A local key vault built on the principle that **secrets are derived, not
|
||||
stored**. From a single BIP39 mnemonic, the vault deterministically
|
||||
derives Ed25519 identity keys, SSH host keys, and AES-256-GCM encryption
|
||||
keys on demand. External credentials (API keys, OAuth tokens) that can't
|
||||
be derived are encrypted with a seed-derived key and stored as
|
||||
`EncryptedData` blobs.
|
||||
|
||||
The vault is **local-only by construction** — direct method calls on
|
||||
`VaultServiceHandle`, no actor, no message enum, no wire format, no
|
||||
remote dispatch. The master seed and derived private keys never cross a
|
||||
process boundary.
|
||||
|
||||
## Usage
|
||||
|
||||
```rust
|
||||
use alkvault::derivation::PATHS;
|
||||
use alkvault::{VaultServiceHandle, KeyType};
|
||||
|
||||
// Generate a new mnemonic and unlock the vault.
|
||||
let vault = VaultServiceHandle::new();
|
||||
let phrase = vault.unlock_new(24)?; // 24-word BIP39 mnemonic
|
||||
// Store `phrase` securely — it is the root of trust.
|
||||
|
||||
// Derive an Ed25519 identity keypair at m/74'/0'/0'/0'.
|
||||
let identity = vault.derive_ed25519(PATHS::IDENTITY)?;
|
||||
assert_eq!(identity.key_type, KeyType::Ed25519);
|
||||
assert_eq!(identity.private_key.len(), 32);
|
||||
|
||||
// Encrypt an external credential with a seed-derived AES-256-GCM key.
|
||||
let plaintext = "sk-proj-abc123xyz789";
|
||||
let encrypted = vault.encrypt(plaintext, 2)?;
|
||||
let decrypted = vault.decrypt(&encrypted)?;
|
||||
assert_eq!(decrypted, plaintext);
|
||||
|
||||
// Lock the vault — purges the seed and all cached derived keys.
|
||||
vault.lock();
|
||||
# Ok::<(), Box<dyn std::error::Error>>(())
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
| Feature | Default | Description |
|
||||
|---------|---------|-------------|
|
||||
| `secp256k1` | off | BIP-0032 secp256k1 HD key derivation for Ethereum signing keys (`m/44'/60'/0'/0/0`) |
|
||||
|
||||
Without `secp256k1`, `derive_ethereum_key` returns
|
||||
`UnsupportedKeyType`. The `secp256k1` crate is a heavy dependency (C
|
||||
library for curve operations); feature-gating it keeps the default build
|
||||
lightweight.
|
||||
|
||||
## Derivation paths
|
||||
|
||||
`alkvault` reserves the `74'` coin type (unallocated per SLIP-0044).
|
||||
|
||||
| Path | Purpose | Key type |
|
||||
|------|---------|----------|
|
||||
| `m/74'/0'/0'/0'` | Primary identity keypair | Ed25519 |
|
||||
| `m/74'/0'/0'/{n}'` | Worker/device identity | Ed25519 |
|
||||
| `m/74'/0'/1'/0'` | SSH host key | Ed25519 |
|
||||
| `m/74'/2'/0'/0'` | Encryption key (v2) | AES-256-GCM |
|
||||
| `m/74'/2'/0'/{n}'` | Encryption key (v{n+2}) | AES-256-GCM |
|
||||
| `m/44'/60'/0'/0/0` | Ethereum signing key | secp256k1 (feature-gated) |
|
||||
|
||||
Key rotation re-encrypts `EncryptedData` from one version to another via
|
||||
version-indexed derivation paths — same seed, different keys, no new
|
||||
mnemonic needed.
|
||||
|
||||
## Security model
|
||||
|
||||
- **Seed never persisted.** The BIP39 mnemonic is entered at startup or
|
||||
via `unlock` and held only in `Zeroize`-protected RAM. `lock()` purges
|
||||
the seed and all cached derived keys.
|
||||
- **Zeroize everything sensitive.** `Mnemonic`, `Seed`,
|
||||
`ExtendedPrivKey`, `EncryptionKey`, `DerivedKey`, and `CachedKey` all
|
||||
implement `Zeroize` and `ZeroizeOnDrop`. Secret material does not
|
||||
linger in freed heap memory.
|
||||
- **OsRng for nonces.** AES-GCM IVs use the operating system's CSPRNG
|
||||
(`SysRng`), never a thread-local RNG. IV reuse under the same key is
|
||||
catastrophic for GCM.
|
||||
- **`DerivedKey` redaction.** `DerivedKey` serializes `private_key` as
|
||||
`"[REDACTED]"` in all formats (defense-in-depth for logging accidents)
|
||||
and rejects redacted payloads on deserialization. `Debug` impls also
|
||||
redact.
|
||||
- **Move-only, not `Clone`.** `DerivedKey` and `EncryptionKey` are
|
||||
move-only — no accidental duplication of secret material.
|
||||
- **No `unwrap()` outside tests.** Vault operations propagate errors.
|
||||
A poisoned lock is recovered with `unwrap_or_else(|e| e.into_inner())`,
|
||||
not panicked.
|
||||
|
||||
## Crate independence
|
||||
|
||||
`alkvault` does **not** depend on any application or networking crate.
|
||||
It defines its own types (`VaultServiceError`, `DerivedKey`,
|
||||
`EncryptedData`, etc.) and is usable in contexts where networking doesn't
|
||||
exist — CLI tools, test harnesses, key-derivation utilities, and future
|
||||
WASM targets.
|
||||
|
||||
## Documentation
|
||||
|
||||
Architecture documentation lives under [`docs/architecture/`](docs/architecture/):
|
||||
|
||||
- [Mnemonic and key derivation](docs/architecture/mnemonic-derivation.md) — BIP39, SLIP-0010, BIP-0032, derivation paths
|
||||
- [Encryption](docs/architecture/encryption.md) — AES-256-GCM, `EncryptedData`, key versioning
|
||||
- [Service](docs/architecture/service.md) — `VaultServiceHandle` lifecycle, cache, error model
|
||||
- [Protocol](docs/architecture/protocol.md) — `DerivedKey` redaction, `KeyType`, serialization
|
||||
- [Architecture decisions (ADRs)](docs/architecture/decisions/) — standalone crate, local-only dispatch, HD derivation, key rotation
|
||||
|
||||
## License
|
||||
|
||||
Licensed under either of
|
||||
|
||||
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||
- MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||
|
||||
at your option.
|
||||
|
||||
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
|
||||
+27
-21
@@ -40,7 +40,9 @@ use aes_gcm::{
|
||||
aead::{Aead, KeyInit},
|
||||
Aes256Gcm, Nonce,
|
||||
};
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
use base64::prelude::*;
|
||||
use rand::rngs::SysRng;
|
||||
use rand::TryRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt;
|
||||
use zeroize::Zeroize;
|
||||
@@ -156,27 +158,29 @@ pub(crate) fn encrypt(
|
||||
plaintext: &str,
|
||||
key: &EncryptionKey,
|
||||
) -> Result<EncryptedData, EncryptionError> {
|
||||
let cipher = Aes256Gcm::new_from_slice(key.key_bytes())
|
||||
.map_err(|e| EncryptionError::Encryption(format!("invalid key length: {e}")))?;
|
||||
let cipher = Aes256Gcm::new(key.key_bytes().into());
|
||||
|
||||
// Generate random IV (12 bytes for AES-GCM) using OsRng CSPRNG
|
||||
// Generate random IV (12 bytes for AES-GCM) using the system CSPRNG
|
||||
let mut iv_bytes = [0u8; 12];
|
||||
OsRng.fill_bytes(&mut iv_bytes);
|
||||
let nonce = Nonce::from_slice(&iv_bytes);
|
||||
SysRng
|
||||
.try_fill_bytes(&mut iv_bytes)
|
||||
.map_err(|e| EncryptionError::Encryption(format!("rng failure: {e}")))?;
|
||||
|
||||
// TODO(Phase B): Use salt in HKDF-based key derivation
|
||||
let mut salt_bytes = [0u8; 32];
|
||||
OsRng.fill_bytes(&mut salt_bytes);
|
||||
SysRng
|
||||
.try_fill_bytes(&mut salt_bytes)
|
||||
.map_err(|e| EncryptionError::Encryption(format!("rng failure: {e}")))?;
|
||||
|
||||
let ciphertext = cipher
|
||||
.encrypt(nonce, plaintext.as_bytes())
|
||||
.encrypt(&Nonce::from(iv_bytes), plaintext.as_bytes())
|
||||
.map_err(|e| EncryptionError::Encryption(e.to_string()))?;
|
||||
|
||||
Ok(EncryptedData {
|
||||
key_version: key.key_version,
|
||||
salt: base64::Engine::encode(&base64::engine::general_purpose::STANDARD, salt_bytes),
|
||||
iv: base64::Engine::encode(&base64::engine::general_purpose::STANDARD, iv_bytes),
|
||||
data: base64::Engine::encode(&base64::engine::general_purpose::STANDARD, &ciphertext),
|
||||
salt: BASE64_STANDARD.encode(salt_bytes),
|
||||
iv: BASE64_STANDARD.encode(iv_bytes),
|
||||
data: BASE64_STANDARD.encode(&ciphertext),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -194,20 +198,22 @@ pub(crate) fn decrypt(
|
||||
encrypted: &EncryptedData,
|
||||
key: &EncryptionKey,
|
||||
) -> Result<String, EncryptionError> {
|
||||
let cipher = Aes256Gcm::new_from_slice(key.key_bytes())
|
||||
.map_err(|e| EncryptionError::Decryption(format!("invalid key length: {e}")))?;
|
||||
let cipher = Aes256Gcm::new(key.key_bytes().into());
|
||||
|
||||
let iv_bytes =
|
||||
base64::Engine::decode(&base64::engine::general_purpose::STANDARD, &encrypted.iv)
|
||||
.map_err(|e| EncryptionError::Decoding(e.to_string()))?;
|
||||
let nonce = Nonce::from_slice(&iv_bytes);
|
||||
let iv_bytes = BASE64_STANDARD
|
||||
.decode(&encrypted.iv)
|
||||
.map_err(|e| EncryptionError::Decoding(e.to_string()))?;
|
||||
let nonce: Nonce<_> = iv_bytes
|
||||
.as_slice()
|
||||
.try_into()
|
||||
.map_err(|_| EncryptionError::Decoding("invalid IV length".to_string()))?;
|
||||
|
||||
let ciphertext =
|
||||
base64::Engine::decode(&base64::engine::general_purpose::STANDARD, &encrypted.data)
|
||||
.map_err(|e| EncryptionError::Decoding(e.to_string()))?;
|
||||
let ciphertext = BASE64_STANDARD
|
||||
.decode(&encrypted.data)
|
||||
.map_err(|e| EncryptionError::Decoding(e.to_string()))?;
|
||||
|
||||
let plaintext = cipher
|
||||
.decrypt(nonce, ciphertext.as_ref())
|
||||
.decrypt(&nonce, ciphertext.as_ref())
|
||||
.map_err(|e| EncryptionError::Decryption(e.to_string()))?;
|
||||
|
||||
String::from_utf8(plaintext).map_err(|e| EncryptionError::Decryption(e.to_string()))
|
||||
|
||||
@@ -282,21 +282,21 @@ fn test_aes256gcm_known_key_encrypt_decrypt() {
|
||||
0x1e, 0x1f,
|
||||
];
|
||||
|
||||
let cipher = Aes256Gcm::new_from_slice(&key_bytes).unwrap();
|
||||
let cipher = Aes256Gcm::new((&key_bytes).into());
|
||||
|
||||
// Known 12-byte nonce
|
||||
let nonce_bytes: [u8; 12] = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||
];
|
||||
let nonce = Nonce::from_slice(&nonce_bytes);
|
||||
let nonce = Nonce::from(nonce_bytes);
|
||||
|
||||
let plaintext = b"hello, alkvault!";
|
||||
|
||||
// Encrypt with known key and nonce
|
||||
let ciphertext = cipher.encrypt(nonce, plaintext.as_ref()).unwrap();
|
||||
let ciphertext = cipher.encrypt(&nonce, plaintext.as_ref()).unwrap();
|
||||
|
||||
// Decrypt with same key and nonce
|
||||
let decrypted = cipher.decrypt(nonce, ciphertext.as_ref()).unwrap();
|
||||
let decrypted = cipher.decrypt(&nonce, ciphertext.as_ref()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
decrypted, plaintext,
|
||||
|
||||
Reference in new issue
Block a user