MVP hardening: review fixes, CI/release workflows, and dependency updates #1
@@ -0,0 +1,43 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test (${{ matrix.os }})
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, macos-latest]
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust toolchain
|
||||
# dtolnay/rust-toolchain has no tagged releases; pinned to master @ 2026-06-20.
|
||||
# When pinned to a SHA the channel must be given explicitly via `toolchain`.
|
||||
uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537
|
||||
with:
|
||||
toolchain: "1.96.0" # latest stable as of 2026-06-24
|
||||
components: rustfmt, clippy
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Format check
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Clippy
|
||||
run: cargo clippy --workspace --all-targets --locked -- -D warnings
|
||||
|
||||
- name: Run unit tests
|
||||
run: cargo test --workspace --locked
|
||||
@@ -0,0 +1,94 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "Release tag, e.g. v0.1.0"
|
||||
required: true
|
||||
type: string
|
||||
prerelease:
|
||||
description: "Mark this release as a pre-release"
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build ${{ matrix.asset }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: windows-latest
|
||||
target: x86_64-pc-windows-msvc
|
||||
bin: drmlibre.exe
|
||||
asset: drmlibre-windows-x86_64.exe
|
||||
- os: macos-latest
|
||||
target: aarch64-apple-darwin
|
||||
bin: drmlibre
|
||||
asset: drmlibre-macos-aarch64
|
||||
- os: macos-latest
|
||||
target: x86_64-apple-darwin
|
||||
bin: drmlibre
|
||||
asset: drmlibre-macos-x86_64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
||||
|
||||
- name: Install Rust toolchain
|
||||
# dtolnay/rust-toolchain has no tagged releases; pinned to master @ 2026-06-20.
|
||||
# When pinned to a SHA the channel must be given explicitly via `toolchain`.
|
||||
uses: dtolnay/rust-toolchain@67ef31d5b988238dd797d409d6f9574278e20537
|
||||
with:
|
||||
toolchain: "1.96.0" # latest stable as of 2026-06-24
|
||||
targets: ${{ matrix.target }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
|
||||
|
||||
- name: Build release binary
|
||||
run: cargo build --release --locked --target ${{ matrix.target }} --bin drmlibre
|
||||
|
||||
- name: Stage artifact
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p dist
|
||||
cp "target/${{ matrix.target }}/release/${{ matrix.bin }}" "dist/${{ matrix.asset }}"
|
||||
|
||||
- name: Upload build artifact
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: dist/${{ matrix.asset }}
|
||||
if-no-files-found: error
|
||||
|
||||
release:
|
||||
name: Publish GitHub Release
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
|
||||
- name: Publish to GitHub Releases
|
||||
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
|
||||
with:
|
||||
tag_name: ${{ inputs.tag }}
|
||||
name: ${{ inputs.tag }}
|
||||
prerelease: ${{ inputs.prerelease }}
|
||||
generate_release_notes: true
|
||||
fail_on_unmatched_files: true
|
||||
files: dist/*
|
||||
Generated
+219
-272
@@ -10,12 +10,12 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
|
||||
[[package]]
|
||||
name = "aes"
|
||||
version = "0.8.4"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
||||
checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpubits",
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
@@ -64,7 +64,7 @@ version = "1.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -75,16 +75,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"once_cell_polyfill",
|
||||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||
dependencies = [
|
||||
"derive_arbitrary",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -113,20 +104,20 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -137,9 +128,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||
|
||||
[[package]]
|
||||
name = "cbc"
|
||||
version = "0.1.2"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
|
||||
checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896"
|
||||
dependencies = [
|
||||
"cipher",
|
||||
]
|
||||
@@ -151,12 +142,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
name = "chacha20"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c"
|
||||
dependencies = [
|
||||
"crypto-common 0.2.2",
|
||||
"inout",
|
||||
]
|
||||
|
||||
@@ -213,10 +215,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.2.17"
|
||||
name = "const-oid"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||
|
||||
[[package]]
|
||||
name = "cpubits"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae"
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
@@ -230,12 +244,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.1.7"
|
||||
@@ -246,48 +254,45 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "der"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"const-oid 0.9.6",
|
||||
"pem-rfc7468",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_arbitrary"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"const-oid",
|
||||
"crypto-common",
|
||||
"const-oid 0.9.6",
|
||||
"crypto-common 0.1.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.6"
|
||||
name = "digest"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f"
|
||||
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"block-buffer",
|
||||
"const-oid 0.10.2",
|
||||
"crypto-common 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -311,7 +316,8 @@ dependencies = [
|
||||
"hex",
|
||||
"md-5",
|
||||
"quick-xml",
|
||||
"rand",
|
||||
"rand 0.10.1",
|
||||
"rand_core 0.6.4",
|
||||
"rsa",
|
||||
"serde",
|
||||
"sha1",
|
||||
@@ -338,7 +344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -355,6 +361,7 @@ checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
|
||||
dependencies = [
|
||||
"crc32fast",
|
||||
"miniz_oxide",
|
||||
"zlib-rs",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -387,6 +394,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -407,6 +415,15 @@ version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.14.0"
|
||||
@@ -419,12 +436,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.4"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -477,12 +494,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"digest",
|
||||
"digest 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -507,7 +524,7 @@ version = "0.50.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -521,7 +538,7 @@ dependencies = [
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand",
|
||||
"rand 0.8.6",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -624,9 +641,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.5"
|
||||
version = "0.40.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "331e97a1af0bf59823e6eadffe373d7b27f485be8748f71471c662c1f269b7fb"
|
||||
checksum = "2474bd2e5029e7ccb6abb2ba48cf2383a333851dedf495901544281590c7da7f"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -652,9 +669,19 @@ version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||
dependencies = [
|
||||
"chacha20",
|
||||
"getrandom 0.4.3",
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -664,7 +691,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -676,6 +703,12 @@ dependencies = [
|
||||
"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 = "regex-automata"
|
||||
version = "0.4.14"
|
||||
@@ -699,14 +732,14 @@ version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"digest",
|
||||
"const-oid 0.9.6",
|
||||
"digest 0.10.7",
|
||||
"num-bigint-dig",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core",
|
||||
"rand_core 0.6.4",
|
||||
"signature",
|
||||
"spki",
|
||||
"subtle",
|
||||
@@ -723,7 +756,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -758,33 +791,33 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "0.6.9"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.10.6"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"digest 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.10.9"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"digest 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -802,8 +835,8 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
|
||||
dependencies = [
|
||||
"digest",
|
||||
"rand_core",
|
||||
"digest 0.10.7",
|
||||
"rand_core 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -867,7 +900,7 @@ dependencies = [
|
||||
"getrandom 0.4.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -901,44 +934,42 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.23"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_write",
|
||||
"toml_parser",
|
||||
"toml_writer",
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_write"
|
||||
version = "0.1.2"
|
||||
name = "toml_datetime"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
@@ -1001,6 +1032,12 @@ dependencies = [
|
||||
"tracing-log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-path"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e"
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
@@ -1039,32 +1076,54 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.58.0"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-collections",
|
||||
"windows-core",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.58.0"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-link",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1073,9 +1132,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
version = "0.59.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1089,31 +1148,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
"windows-core",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1126,143 +1185,28 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.15"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1"
|
||||
|
||||
[[package]]
|
||||
name = "winreg"
|
||||
version = "0.52.0"
|
||||
version = "0.56.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
|
||||
checksum = "7d6f32a0ff4a9f6f01231eb2059cc85479330739333e0e58cadf03b6af2cca10"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-sys 0.48.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1293,21 +1237,24 @@ checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "2.4.2"
|
||||
version = "8.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50"
|
||||
checksum = "2d04a6b5381502aa6087c94c669499eb1602eb9c5e8198e534de571f7154809b"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"crc32fast",
|
||||
"crossbeam-utils",
|
||||
"displaydoc",
|
||||
"flate2",
|
||||
"indexmap",
|
||||
"memchr",
|
||||
"thiserror",
|
||||
"typed-path",
|
||||
"zopfli",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zlib-rs"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "977347db8caa080403f6b6b7c1cda9479a8e869316f7e13a59b19076a40f94e3"
|
||||
|
||||
[[package]]
|
||||
name = "zopfli"
|
||||
version = "0.8.3"
|
||||
|
||||
+11
-11
@@ -24,23 +24,23 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
|
||||
# Crypto (RustCrypto — pure Rust, statically linked)
|
||||
rsa = "0.9"
|
||||
aes = "0.8"
|
||||
cbc = "0.1"
|
||||
ctr = "0.9"
|
||||
sha1 = "0.10"
|
||||
sha2 = "0.10"
|
||||
md-5 = "0.10"
|
||||
hmac = "0.12"
|
||||
pbkdf2 = { version = "0.12", default-features = false }
|
||||
aes = "0.9"
|
||||
cbc = "0.2"
|
||||
ctr = "0.10"
|
||||
sha1 = "0.11"
|
||||
sha2 = "0.11"
|
||||
md-5 = "0.11"
|
||||
hmac = "0.13"
|
||||
pbkdf2 = { version = "0.13", default-features = false }
|
||||
|
||||
# Config / serialization
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
toml = "0.8"
|
||||
toml = "1"
|
||||
|
||||
# Containers / encoding
|
||||
zip = { version = "2", default-features = false, features = ["deflate"] }
|
||||
zip = { version = "8", default-features = false, features = ["deflate"] }
|
||||
flate2 = "1"
|
||||
quick-xml = "0.37"
|
||||
quick-xml = "0.40"
|
||||
base64 = "0.22"
|
||||
hex = "0.4"
|
||||
|
||||
|
||||
@@ -124,7 +124,18 @@ fn process_one(
|
||||
let tmp = temp_sibling(output);
|
||||
let _ = std::fs::remove_file(&tmp);
|
||||
|
||||
match decrypt(input, &tmp, keys, opts) {
|
||||
// Contain any panic in the engine so one malformed file can't abort a whole
|
||||
// multi-file run; turn it into a per-file error instead.
|
||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
||||
decrypt(input, &tmp, keys, opts)
|
||||
}))
|
||||
.unwrap_or_else(|_| {
|
||||
Err(Error::Decrypt(
|
||||
"internal error while processing this file (skipped)".into(),
|
||||
))
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(Outcome::Decrypted) => {
|
||||
std::fs::rename(&tmp, output)?;
|
||||
Ok(())
|
||||
|
||||
@@ -29,14 +29,19 @@ md-5.workspace = true
|
||||
|
||||
# Local key extraction from installed Adobe Digital Editions / Kindle (Windows).
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows = { version = "0.58", features = [
|
||||
windows = { version = "0.62", features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security_Cryptography",
|
||||
"Win32_Storage_FileSystem",
|
||||
"Win32_System_Memory",
|
||||
] }
|
||||
winreg = "0.52"
|
||||
winreg = "0.56"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3"
|
||||
rand = "0.8"
|
||||
rand = "0.10"
|
||||
# Escape hatch: the latest `rsa` (0.9) still requires an `rand_core` 0.6 RNG for
|
||||
# key generation, while `rand` 0.10 provides `rand_core` 0.10. We depend on
|
||||
# `rand_core` 0.6 directly (package-renamed to avoid the name clash) so the
|
||||
# test-only `RandCompat` shim can re-implement its traits over a modern RNG.
|
||||
rand_core_06 = { package = "rand_core", version = "0.6" }
|
||||
|
||||
@@ -113,7 +113,10 @@ fn handle_open(
|
||||
fn attr_value(e: &quick_xml::events::BytesStart, local: &str) -> Option<String> {
|
||||
for attr in e.attributes().flatten() {
|
||||
if local_eq(local_name(attr.key.as_ref()), local) {
|
||||
return attr.unescape_value().ok().map(|v| v.into_owned());
|
||||
return attr
|
||||
.normalized_value(quick_xml::XmlVersion::Implicit1_0)
|
||||
.ok()
|
||||
.map(|v| v.into_owned());
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
@@ -146,7 +146,9 @@ pub fn decrypt_epub(input: &Path, output: &Path, key: UserKey, opts: &Options) -
|
||||
/// raw-inflate. Mirrors `ineptepub.py::Decryptor.decrypt`.
|
||||
fn decrypt_content(bookkey: &[u8], data: &[u8], decompress: bool) -> Result<Vec<u8>> {
|
||||
let pt = crypto::aes128_cbc_decrypt_nopad(bookkey, &[0u8; 16], data)?;
|
||||
if pt.len() < 16 {
|
||||
// The first 16 bytes are a throwaway pad block, so there must be at least
|
||||
// one more block after them before we can read the trailing pad length.
|
||||
if pt.len() <= 16 {
|
||||
return Err(Error::Decrypt("ciphertext too short".into()));
|
||||
}
|
||||
let pt = &pt[16..];
|
||||
@@ -267,9 +269,43 @@ mod tests {
|
||||
Some(buf)
|
||||
}
|
||||
|
||||
/// Test-only escape hatch for the `rand_core` version skew: `rsa` 0.9 still
|
||||
/// requires an `rand_core` 0.6 RNG for key generation, while `rand` 0.10
|
||||
/// exposes `rand_core` 0.10. `RandCompat` wraps a modern RNG and
|
||||
/// re-implements `rand_core` 0.6's `RngCore`/`CryptoRng` over it, delegating
|
||||
/// to the new (infallible) methods. Implementing both satisfies `rand_core`
|
||||
/// 0.6's blanket `CryptoRngCore` impl — exactly what `rsa` keygen wants.
|
||||
///
|
||||
/// The `CryptoRng` bound is preserved (we only wrap RNGs the new crate still
|
||||
/// marks cryptographically secure), so this is a pure trait-version shim that
|
||||
/// does not weaken the randomness.
|
||||
struct RandCompat<R>(R);
|
||||
|
||||
impl<R: rand::Rng> rand_core_06::RngCore for RandCompat<R> {
|
||||
fn next_u32(&mut self) -> u32 {
|
||||
rand::Rng::next_u32(&mut self.0)
|
||||
}
|
||||
fn next_u64(&mut self) -> u64 {
|
||||
rand::Rng::next_u64(&mut self.0)
|
||||
}
|
||||
fn fill_bytes(&mut self, dest: &mut [u8]) {
|
||||
rand::Rng::fill_bytes(&mut self.0, dest)
|
||||
}
|
||||
fn try_fill_bytes(
|
||||
&mut self,
|
||||
dest: &mut [u8],
|
||||
) -> std::result::Result<(), rand_core_06::Error> {
|
||||
// `fill_bytes` is infallible in rand_core 0.10.
|
||||
rand::Rng::fill_bytes(&mut self.0, dest);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: rand::CryptoRng> rand_core_06::CryptoRng for RandCompat<R> {}
|
||||
|
||||
fn make_rsa() -> (Vec<u8>, rsa::RsaPublicKey) {
|
||||
use rsa::pkcs8::EncodePrivateKey;
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut rng = RandCompat(rand::rng());
|
||||
let priv_key = rsa::RsaPrivateKey::new(&mut rng, 1024).unwrap();
|
||||
let der = priv_key.to_pkcs8_der().unwrap().as_bytes().to_vec();
|
||||
let pub_key = rsa::RsaPublicKey::from(&priv_key);
|
||||
@@ -284,7 +320,7 @@ mod tests {
|
||||
|
||||
let (der, pub_key) = make_rsa();
|
||||
let bookkey = [0x5Au8; 16];
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut rng = RandCompat(rand::rng());
|
||||
let enc_key = pub_key
|
||||
.encrypt(&mut rng, rsa::Pkcs1v15Encrypt, &bookkey)
|
||||
.unwrap();
|
||||
@@ -321,7 +357,7 @@ mod tests {
|
||||
let (_der, pub_key) = make_rsa();
|
||||
let (other_der, _other_pub) = make_rsa();
|
||||
let bookkey = [0x5Au8; 16];
|
||||
let mut rng = rand::thread_rng();
|
||||
let mut rng = RandCompat(rand::rng());
|
||||
let enc_key = pub_key
|
||||
.encrypt(&mut rng, rsa::Pkcs1v15Encrypt, &bookkey)
|
||||
.unwrap();
|
||||
@@ -333,6 +369,15 @@ mod tests {
|
||||
assert!(decrypt_epub(&input, &output, UserKey::Rsa(&other_der), &opts).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn decrypt_content_rejects_single_block_without_panic() {
|
||||
// A one-block ciphertext decrypts to 16 bytes; after dropping the 16-byte
|
||||
// pad block nothing is left, so this must error rather than panic.
|
||||
let bookkey = [0u8; 16];
|
||||
let ct = [0xABu8; 16];
|
||||
assert!(decrypt_content(&bookkey, &ct, false).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn drm_free_epub_reports_already_free() {
|
||||
let dir = tempfile::tempdir().unwrap();
|
||||
|
||||
@@ -207,7 +207,7 @@ fn parse_opf(xml: &[u8]) -> (Option<String>, Vec<Identifier>) {
|
||||
}
|
||||
Ok(Event::Text(t)) => {
|
||||
if let Some(ident) = cur.as_mut() {
|
||||
if let Ok(s) = t.unescape() {
|
||||
if let Ok(s) = t.xml10_content() {
|
||||
ident.text.push_str(&s);
|
||||
}
|
||||
}
|
||||
@@ -228,7 +228,10 @@ fn parse_opf(xml: &[u8]) -> (Option<String>, Vec<Identifier>) {
|
||||
fn attr_value(e: &quick_xml::events::BytesStart, local: &str) -> Option<String> {
|
||||
for attr in e.attributes().flatten() {
|
||||
if local_eq(local_name(attr.key.as_ref()), local) {
|
||||
return attr.unescape_value().ok().map(|v| v.into_owned());
|
||||
return attr
|
||||
.normalized_value(quick_xml::XmlVersion::Implicit1_0)
|
||||
.ok()
|
||||
.map(|v| v.into_owned());
|
||||
}
|
||||
}
|
||||
None
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
use aes::Aes128;
|
||||
use cbc::cipher::block_padding::NoPadding;
|
||||
use cbc::cipher::{BlockDecryptMut, BlockEncryptMut, KeyIvInit};
|
||||
use cbc::cipher::{BlockModeDecrypt, BlockModeEncrypt, KeyIvInit};
|
||||
use sha2::Digest;
|
||||
|
||||
use crate::error::{Error, Result};
|
||||
@@ -42,7 +42,7 @@ pub fn aes128_cbc_decrypt_nopad(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Ve
|
||||
let dec = cbc::Decryptor::<Aes128>::new_from_slices(key, iv)
|
||||
.map_err(|_| Error::Decrypt("bad AES key/iv length".into()))?;
|
||||
let pt = dec
|
||||
.decrypt_padded_mut::<NoPadding>(&mut buf)
|
||||
.decrypt_padded::<NoPadding>(&mut buf)
|
||||
.map_err(|e| Error::Decrypt(format!("AES-CBC decrypt failed: {e}")))?;
|
||||
let len = pt.len();
|
||||
buf.truncate(len);
|
||||
@@ -62,7 +62,7 @@ pub fn aes128_cbc_encrypt_nopad(key: &[u8], iv: &[u8], data: &[u8]) -> Result<Ve
|
||||
let enc = cbc::Encryptor::<Aes128>::new_from_slices(key, iv)
|
||||
.map_err(|_| Error::Decrypt("bad AES key/iv length".into()))?;
|
||||
let ct = enc
|
||||
.encrypt_padded_mut::<NoPadding>(&mut buf, len)
|
||||
.encrypt_padded::<NoPadding>(&mut buf, len)
|
||||
.map_err(|e| Error::Decrypt(format!("AES-CBC encrypt failed: {e}")))?;
|
||||
Ok(ct.to_vec())
|
||||
}
|
||||
@@ -147,7 +147,7 @@ mod tests {
|
||||
fn aes_cbc_roundtrip_nopad() {
|
||||
use aes::Aes128;
|
||||
use cbc::cipher::block_padding::NoPadding;
|
||||
use cbc::cipher::{BlockEncryptMut, KeyIvInit};
|
||||
use cbc::cipher::{BlockModeEncrypt, KeyIvInit};
|
||||
|
||||
let key = [0x11u8; 16];
|
||||
let iv = [0x22u8; 16];
|
||||
@@ -155,7 +155,7 @@ mod tests {
|
||||
let mut buf = pt.to_vec();
|
||||
let ct = cbc::Encryptor::<Aes128>::new_from_slices(&key, &iv)
|
||||
.unwrap()
|
||||
.encrypt_padded_mut::<NoPadding>(&mut buf, 32)
|
||||
.encrypt_padded::<NoPadding>(&mut buf, 32)
|
||||
.unwrap()
|
||||
.to_vec();
|
||||
let back = aes128_cbc_decrypt_nopad(&key, &iv, &ct).unwrap();
|
||||
|
||||
@@ -213,7 +213,7 @@ fn crypt_unprotect(data: &[u8], entropy: &[u8]) -> Result<Vec<u8>> {
|
||||
},
|
||||
)?;
|
||||
let result = std::slice::from_raw_parts(out.pbData, out.cbData as usize).to_vec();
|
||||
let _ = LocalFree(HLOCAL(out.pbData as *mut core::ffi::c_void));
|
||||
let _ = LocalFree(Some(HLOCAL(out.pbData as *mut core::ffi::c_void)));
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,6 +186,20 @@ impl MobiBook {
|
||||
)));
|
||||
}
|
||||
|
||||
// Guard the section table against a corrupt header before we index it:
|
||||
// we need at least sections 0 and 1, and every text record (1..=records)
|
||||
// must have a corresponding section.
|
||||
if self.section_offsets.len() < 2 {
|
||||
return Err(Error::Decrypt(
|
||||
"MOBI has too few sections to decrypt".into(),
|
||||
));
|
||||
}
|
||||
if self.records >= self.section_offsets.len() {
|
||||
return Err(Error::Decrypt(
|
||||
"MOBI record count exceeds section count (corrupt)".into(),
|
||||
));
|
||||
}
|
||||
|
||||
// Normalize the supplied PIDs to 8-character form (mobidedrm goodpids).
|
||||
let goodpids = normalize_pids(pidlist);
|
||||
|
||||
@@ -235,7 +249,7 @@ impl MobiBook {
|
||||
for i in 1..=self.records {
|
||||
let (start, end) = self.section_bounds(i);
|
||||
let sec = &self.data[start..end];
|
||||
let extra = trailing_size(sec, self.extra_data_flags);
|
||||
let extra = trailing_size(sec, self.extra_data_flags).min(sec.len());
|
||||
let body = &sec[..sec.len() - extra];
|
||||
out.extend_from_slice(&pc1(&found_key, body, true)?);
|
||||
if extra > 0 {
|
||||
@@ -270,8 +284,9 @@ impl MobiBook {
|
||||
fn normalize_pids(pidlist: &[String]) -> Vec<String> {
|
||||
let mut good = Vec::new();
|
||||
for pid in pidlist {
|
||||
match pid.len() {
|
||||
10 => good.push(pid[..8].to_string()),
|
||||
// Count/slice by characters, not bytes: a non-ASCII --pid must not panic.
|
||||
match pid.chars().count() {
|
||||
10 => good.push(pid.chars().take(8).collect()), // drop the 2-char checksum
|
||||
8 => good.push(pid.clone()),
|
||||
_ => tracing::debug!("ignoring PID {pid} with wrong length"),
|
||||
}
|
||||
@@ -342,12 +357,16 @@ fn trailing_size(ptr: &[u8], flags: u16) -> usize {
|
||||
let mut testflags = flags >> 1;
|
||||
while testflags != 0 {
|
||||
if testflags & 1 != 0 {
|
||||
num += entry(ptr, ptr.len() - num);
|
||||
// `num` may already exceed the record on corrupt input; saturate so
|
||||
// the size param can't underflow.
|
||||
num += entry(ptr, ptr.len().saturating_sub(num));
|
||||
}
|
||||
testflags >>= 1;
|
||||
}
|
||||
if flags & 1 != 0 {
|
||||
num += (ptr[ptr.len() - num - 1] & 0x3) as usize + 1;
|
||||
if let Some(&b) = ptr.len().checked_sub(num + 1).and_then(|i| ptr.get(i)) {
|
||||
num += (b & 0x3) as usize + 1;
|
||||
}
|
||||
}
|
||||
num
|
||||
}
|
||||
@@ -483,4 +502,53 @@ mod tests {
|
||||
let out = book.process(&[]).unwrap();
|
||||
assert_eq!(out, data);
|
||||
}
|
||||
|
||||
/// A single-section BOOKMOBI (num_sections = 1) claiming encryption.
|
||||
fn build_one_section_mobi(crypto_type: u16) -> Vec<u8> {
|
||||
let mut sec0 = vec![0u8; 0x100];
|
||||
sec0[0..2].copy_from_slice(&1u16.to_be_bytes()); // compression
|
||||
sec0[0xC..0xE].copy_from_slice(&crypto_type.to_be_bytes());
|
||||
sec0[0x14..0x18].copy_from_slice(&0xC8u32.to_be_bytes()); // mobi_length
|
||||
sec0[0x68..0x6C].copy_from_slice(&6u32.to_be_bytes()); // mobi_version
|
||||
|
||||
let num_sections = 1u16;
|
||||
let header_len = 78 + num_sections as usize * 8; // 86
|
||||
let mut data = vec![0u8; header_len];
|
||||
data[0x3C..0x44].copy_from_slice(b"BOOKMOBI");
|
||||
data[76..78].copy_from_slice(&num_sections.to_be_bytes());
|
||||
data[78..82].copy_from_slice(&(header_len as u32).to_be_bytes());
|
||||
data.extend_from_slice(&sec0);
|
||||
data
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_section_mobi_errors_not_panics() {
|
||||
let data = build_one_section_mobi(2);
|
||||
let book = MobiBook::from_bytes(data).unwrap();
|
||||
assert!(book.process(&[]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn corrupt_record_count_errors_not_panics() {
|
||||
let bookkey = [0xC3u8; 16];
|
||||
let mut data = build_encrypted_mobi(&bookkey, "12345678", b"hi");
|
||||
// Patch the record count (sec0 + 8; sec0 starts at 94) to exceed sections.
|
||||
data[94 + 8..94 + 10].copy_from_slice(&0xFFFFu16.to_be_bytes());
|
||||
let book = MobiBook::from_bytes(data).unwrap();
|
||||
assert!(book.process(&["12345678".to_string()]).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn trailing_size_does_not_underflow_on_corrupt_input() {
|
||||
// Encoded sizes far exceed the record length; must return, not panic.
|
||||
let _ = trailing_size(&[0x7F, 0x7F], 0b110); // two size entries
|
||||
let _ = trailing_size(&[0x7F], 0b11); // size entry + multibyte flag
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn normalize_pids_handles_non_ascii() {
|
||||
// A 10-byte PID whose 8th byte is mid-character must not panic.
|
||||
let pids = vec!["XXXXXXXéX".to_string()];
|
||||
assert!(normalize_pids(&pids).is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ pub fn first_element_text(xml: &[u8], local_name: &str) -> Option<String> {
|
||||
}
|
||||
}
|
||||
Ok(Event::Text(e)) if inside => {
|
||||
if let Ok(t) = e.unescape() {
|
||||
if let Ok(t) = e.xml10_content() {
|
||||
text.push_str(&t);
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,10 @@ pub fn first_element_attr(xml: &[u8], local_name_wanted: &str, attr: &str) -> Op
|
||||
{
|
||||
for a in e.attributes().flatten() {
|
||||
if local_eq(local_name(a.key.as_ref()), attr) {
|
||||
return a.unescape_value().ok().map(|v| v.into_owned());
|
||||
return a
|
||||
.normalized_value(quick_xml::XmlVersion::Implicit1_0)
|
||||
.ok()
|
||||
.map(|v| v.into_owned());
|
||||
}
|
||||
}
|
||||
return None;
|
||||
|
||||
Reference in New Issue
Block a user