Skip to content

Commit dbccc0d

Browse files
committed
bech32 0.11
1 parent 34da64e commit dbccc0d

File tree

11 files changed

+59
-70
lines changed

11 files changed

+59
-70
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ scrypt = { version = "0.11", default-features = false }
4141
rand = "0.8"
4242

4343
# - Key encoding
44-
bech32 = "0.9"
44+
bech32 = "0.11"
4545

4646
# Parsing
4747
cookie-factory = "0.3.1"

age-plugin/src/identity.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use age_core::{
66
secrecy::{ExposeSecret, SecretString},
77
};
88
use base64::{prelude::BASE64_STANDARD_NO_PAD, Engine};
9-
use bech32::FromBase32;
9+
use bech32::{primitives::decode::CheckedHrpstring, Bech32};
1010

1111
use std::collections::HashMap;
1212
use std::convert::Infallible;
@@ -265,14 +265,14 @@ pub(crate) fn run_v1<P: IdentityPluginV1>(mut plugin: P) -> io::Result<()> {
265265
.into_iter()
266266
.enumerate()
267267
.map(|(index, item)| {
268-
bech32::decode(&item)
268+
CheckedHrpstring::new::<Bech32>(&item)
269269
.ok()
270-
.and_then(|(hrp, data, variant)| {
271-
if hrp.starts_with(PLUGIN_IDENTITY_PREFIX)
272-
&& hrp.ends_with('-')
273-
&& variant == bech32::Variant::Bech32
270+
.and_then(|parsed| {
271+
let hrp = parsed.hrp();
272+
if hrp.as_str().starts_with(PLUGIN_IDENTITY_PREFIX)
273+
&& hrp.as_str().ends_with('-')
274274
{
275-
Vec::from_base32(&data).ok().map(|data| (hrp, data))
275+
Some((hrp, parsed.byte_iter().collect::<Vec<_>>()))
276276
} else {
277277
None
278278
}
@@ -284,7 +284,7 @@ pub(crate) fn run_v1<P: IdentityPluginV1>(mut plugin: P) -> io::Result<()> {
284284
.and_then(|(hrp, bytes)| {
285285
plugin.add_identity(
286286
index,
287-
&hrp[PLUGIN_IDENTITY_PREFIX.len()..hrp.len() - 1],
287+
&hrp.as_str()[PLUGIN_IDENTITY_PREFIX.len()..hrp.len() - 1],
288288
&bytes,
289289
)
290290
})

age-plugin/src/lib.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@
179179
#![deny(missing_docs)]
180180

181181
use age_core::secrecy::SecretString;
182-
use bech32::Variant;
182+
use bech32::{Bech32, Hrp};
183183
use std::io;
184184

185185
pub mod identity;
@@ -193,27 +193,23 @@ const PLUGIN_IDENTITY_PREFIX: &str = "age-plugin-";
193193
///
194194
/// A "created" time is included in the output, set to the current local time.
195195
pub fn print_new_identity(plugin_name: &str, identity: &[u8], recipient: &[u8]) {
196-
use bech32::ToBase32;
197-
198196
println!(
199197
"# created: {}",
200198
chrono::Local::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true)
201199
);
202200
println!(
203201
"# recipient: {}",
204-
bech32::encode(
205-
&format!("{}{}", PLUGIN_RECIPIENT_PREFIX, plugin_name),
206-
recipient.to_base32(),
207-
Variant::Bech32
202+
bech32::encode::<Bech32>(
203+
Hrp::parse_unchecked(&format!("{}{}", PLUGIN_RECIPIENT_PREFIX, plugin_name)),
204+
recipient,
208205
)
209206
.expect("HRP is valid")
210207
);
211208
println!(
212209
"{}",
213-
bech32::encode(
214-
&format!("{}{}-", PLUGIN_IDENTITY_PREFIX, plugin_name),
215-
identity.to_base32(),
216-
Variant::Bech32,
210+
bech32::encode::<Bech32>(
211+
Hrp::parse_unchecked(&format!("{}{}-", PLUGIN_IDENTITY_PREFIX, plugin_name)),
212+
identity,
217213
)
218214
.expect("HRP is valid")
219215
.to_uppercase()

age-plugin/src/recipient.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use age_core::{
66
secrecy::SecretString,
77
};
88
use base64::{prelude::BASE64_STANDARD_NO_PAD, Engine};
9-
use bech32::FromBase32;
9+
use bech32::{primitives::decode::CheckedHrpstring, Bech32};
1010

1111
use std::collections::HashSet;
1212
use std::convert::Infallible;
@@ -341,13 +341,12 @@ pub(crate) fn run_v1<P: RecipientPluginV1>(mut plugin: P) -> io::Result<()> {
341341
.into_iter()
342342
.enumerate()
343343
.map(|(index, item)| {
344-
let decoded = bech32::decode(&item).ok();
344+
let decoded = CheckedHrpstring::new::<Bech32>(&item).ok();
345345
decoded
346+
.map(|parsed| (parsed.hrp(), parsed))
346347
.as_ref()
347-
.and_then(|(hrp, data, variant)| match (plugin_name(hrp), variant) {
348-
(Some(plugin_name), &bech32::Variant::Bech32) => {
349-
Vec::from_base32(data).ok().map(|data| (plugin_name, data))
350-
}
348+
.and_then(|(hrp, parsed)| match plugin_name(hrp.as_str()) {
349+
Some(plugin_name) => Some((plugin_name, parsed.byte_iter().collect())),
351350
_ => None,
352351
})
353352
.ok_or_else(|| error(index))

age/src/plugin.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use age_core::{
77
secrecy::ExposeSecret,
88
};
99
use base64::{prelude::BASE64_STANDARD_NO_PAD, Engine};
10-
use bech32::Variant;
10+
use bech32::{Bech32, Hrp};
1111

1212
use std::borrow::Borrow;
1313
use std::collections::HashSet;
@@ -196,10 +196,9 @@ impl Identity {
196196
/// Panics if `plugin_name` contains invalid characters.
197197
pub fn default_for_plugin(plugin_name: &str) -> Self {
198198
if valid_plugin_name(plugin_name) {
199-
bech32::encode(
200-
&format!("{}{}-", PLUGIN_IDENTITY_PREFIX, plugin_name),
201-
[],
202-
Variant::Bech32,
199+
bech32::encode::<Bech32>(
200+
Hrp::parse_unchecked(&format!("{}{}-", PLUGIN_IDENTITY_PREFIX, plugin_name)),
201+
&[],
203202
)
204203
.expect("HRP is valid")
205204
.to_uppercase()
@@ -737,6 +736,8 @@ impl<C: Callbacks> crate::Identity for IdentityPluginV1<C> {
737736

738737
#[cfg(test)]
739738
mod tests {
739+
use bech32::{Bech32, Hrp};
740+
740741
use crate::{DecryptError, EncryptError, NoCallbacks};
741742

742743
use super::{
@@ -757,27 +758,28 @@ mod tests {
757758
#[test]
758759
fn recipient_rejects_empty_name() {
759760
let invalid_recipient =
760-
bech32::encode(PLUGIN_RECIPIENT_PREFIX, [], bech32::Variant::Bech32).unwrap();
761+
bech32::encode::<Bech32>(Hrp::parse_unchecked(PLUGIN_RECIPIENT_PREFIX), &[]).unwrap();
761762
assert!(invalid_recipient.parse::<Recipient>().is_err());
762763
}
763764

764765
#[test]
765766
fn recipient_rejects_invalid_chars() {
766-
let invalid_recipient = bech32::encode(
767-
&format!("{}{}", PLUGIN_RECIPIENT_PREFIX, INVALID_PLUGIN_NAME),
768-
[],
769-
bech32::Variant::Bech32,
767+
let invalid_recipient = bech32::encode::<Bech32>(
768+
Hrp::parse_unchecked(&format!(
769+
"{}{}",
770+
PLUGIN_RECIPIENT_PREFIX, INVALID_PLUGIN_NAME
771+
)),
772+
&[],
770773
)
771774
.unwrap();
772775
assert!(invalid_recipient.parse::<Recipient>().is_err());
773776
}
774777

775778
#[test]
776779
fn identity_rejects_empty_name() {
777-
let invalid_identity = bech32::encode(
778-
&format!("{}-", PLUGIN_IDENTITY_PREFIX),
779-
[],
780-
bech32::Variant::Bech32,
780+
let invalid_identity = bech32::encode::<Bech32>(
781+
Hrp::parse_unchecked(&format!("{}-", PLUGIN_IDENTITY_PREFIX)),
782+
&[],
781783
)
782784
.expect("HRP is valid")
783785
.to_uppercase();
@@ -786,10 +788,12 @@ mod tests {
786788

787789
#[test]
788790
fn identity_rejects_invalid_chars() {
789-
let invalid_identity = bech32::encode(
790-
&format!("{}{}-", PLUGIN_IDENTITY_PREFIX, INVALID_PLUGIN_NAME),
791-
[],
792-
bech32::Variant::Bech32,
791+
let invalid_identity = bech32::encode::<Bech32>(
792+
Hrp::parse_unchecked(&format!(
793+
"{}{}-",
794+
PLUGIN_IDENTITY_PREFIX, INVALID_PLUGIN_NAME
795+
)),
796+
&[],
793797
)
794798
.expect("HRP is valid")
795799
.to_uppercase();

age/src/util.rs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
1-
use bech32::{FromBase32, Variant};
1+
use bech32::{primitives::decode::CheckedHrpstring, Bech32};
22

33
#[cfg(all(any(feature = "armor", feature = "cli-common"), windows))]
44
pub(crate) const LINE_ENDING: &str = "\r\n";
55
#[cfg(all(any(feature = "armor", feature = "cli-common"), not(windows)))]
66
pub(crate) const LINE_ENDING: &str = "\n";
77

88
pub(crate) fn parse_bech32(s: &str) -> Option<(String, Vec<u8>)> {
9-
bech32::decode(s).ok().and_then(|(hrp, data, variant)| {
10-
if let Variant::Bech32 = variant {
11-
Vec::from_base32(&data).ok().map(|d| (hrp, d))
12-
} else {
13-
None
14-
}
15-
})
9+
CheckedHrpstring::new::<Bech32>(s)
10+
.ok()
11+
.map(|parsed| (parsed.hrp().as_str().into(), parsed.byte_iter().collect()))
1612
}
1713

1814
pub(crate) mod read {

age/src/x25519.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use age_core::{
99
secrecy::{ExposeSecret, SecretString},
1010
};
1111
use base64::{prelude::BASE64_STANDARD_NO_PAD, Engine};
12-
use bech32::{ToBase32, Variant};
12+
use bech32::{Bech32, Hrp};
1313
use rand::rngs::OsRng;
1414
use subtle::ConstantTimeEq;
1515
use x25519_dalek::{EphemeralSecret, PublicKey, StaticSecret};
@@ -65,15 +65,13 @@ impl Identity {
6565
/// Serializes this secret key as a string.
6666
pub fn to_string(&self) -> SecretString {
6767
let mut sk_bytes = self.0.to_bytes();
68-
let sk_base32 = sk_bytes.to_base32();
6968
let mut encoded =
70-
bech32::encode(SECRET_KEY_PREFIX, sk_base32, Variant::Bech32).expect("HRP is valid");
69+
bech32::encode::<Bech32>(Hrp::parse_unchecked(SECRET_KEY_PREFIX), &sk_bytes)
70+
.expect("HRP is valid");
7171
let ret = SecretString::from(encoded.to_uppercase());
7272

7373
// Clear intermediates
7474
sk_bytes.zeroize();
75-
// TODO: bech32::u5 doesn't implement Zeroize
76-
// sk_base32.zeroize();
7775
encoded.zeroize();
7876

7977
ret
@@ -177,12 +175,8 @@ impl fmt::Display for Recipient {
177175
write!(
178176
f,
179177
"{}",
180-
bech32::encode(
181-
PUBLIC_KEY_PREFIX,
182-
self.0.as_bytes().to_base32(),
183-
Variant::Bech32
184-
)
185-
.expect("HRP is valid")
178+
bech32::encode::<Bech32>(Hrp::parse_unchecked(PUBLIC_KEY_PREFIX), self.0.as_bytes(),)
179+
.expect("HRP is valid")
186180
)
187181
}
188182
}

fuzz-afl/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fuzz/Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)