Skip to content

Commit

Permalink
Add optional der feature (#61)
Browse files Browse the repository at this point in the history
Adds support for decoding/encoding `UInt` as an ASN.1 DER `INTEGER`.
  • Loading branch information
tarcieri authored Jan 18, 2022
1 parent 085a885 commit 171f674
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 1 deletion.
3 changes: 2 additions & 1 deletion .github/workflows/crypto-bigint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ jobs:
override: true
- run: cargo build --target ${{ matrix.target }} --release --no-default-features
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features der
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features generic-array
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features rand_core
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features rlp
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features zeroize
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,generic-array,rand_core,rlp,zeroize
- run: cargo build --target ${{ matrix.target }} --release --no-default-features --features alloc,der,generic-array,rand_core,rlp,zeroize

test:
runs-on: ubuntu-latest
Expand Down
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ rust-version = "1.57"
subtle = { version = "2.4", default-features = false }

# optional dependencies
der = { version = "=0.6.0-pre", optional = true, default-features = false }
generic-array = { version = "0.14", optional = true }
rand_core = { version = "0.6", optional = true }
rlp = { version = "0.5", optional = true, default-features = false }
Expand All @@ -41,3 +42,6 @@ rand = ["rand_core/std"]
[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docsrs"]

[patch.crates-io]
der = { git = "https://github.com/RustCrypto/formats.git" }
3 changes: 3 additions & 0 deletions src/uint/encoding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
mod decoder;

#[cfg(all(feature = "der", feature = "generic-array"))]
mod der;

#[cfg(feature = "rlp")]
mod rlp;

Expand Down
63 changes: 63 additions & 0 deletions src/uint/encoding/der.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
//! Support for decoding/encoding [`UInt`] as an ASN.1 DER `INTEGER`.
use crate::{generic_array::GenericArray, ArrayEncoding, UInt};
use ::der::{
asn1::{Any, UIntBytes},
EncodeValue, Encoder, FixedTag, Length, Tag,
};

#[cfg(feature = "der")]
#[cfg_attr(docsrs, doc(cfg(feature = "der")))]
impl<'a, const LIMBS: usize> TryFrom<Any<'a>> for UInt<LIMBS>
where
UInt<LIMBS>: ArrayEncoding,
{
type Error = der::Error;

fn try_from(any: Any<'a>) -> der::Result<UInt<LIMBS>> {
UIntBytes::try_from(any)?.try_into()
}
}

#[cfg(feature = "der")]
#[cfg_attr(docsrs, doc(cfg(feature = "der")))]
impl<'a, const LIMBS: usize> TryFrom<UIntBytes<'a>> for UInt<LIMBS>
where
UInt<LIMBS>: ArrayEncoding,
{
type Error = der::Error;

fn try_from(bytes: UIntBytes<'a>) -> der::Result<UInt<LIMBS>> {
let mut array = GenericArray::default();
let offset = array.len().saturating_sub(bytes.len().try_into()?);
array[offset..].copy_from_slice(bytes.as_bytes());
Ok(UInt::from_be_byte_array(array))
}
}

#[cfg(feature = "der")]
#[cfg_attr(docsrs, doc(cfg(feature = "der")))]
impl<const LIMBS: usize> EncodeValue for UInt<LIMBS>
where
UInt<LIMBS>: ArrayEncoding,
{
fn value_len(&self) -> der::Result<Length> {
// TODO(tarcieri): more efficient length calculation
let array = self.to_be_byte_array();
UIntBytes::new(&array)?.value_len()
}

fn encode_value(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
let array = self.to_be_byte_array();
UIntBytes::new(&array)?.encode_value(encoder)
}
}

#[cfg(feature = "der")]
#[cfg_attr(docsrs, doc(cfg(feature = "der")))]
impl<const LIMBS: usize> FixedTag for UInt<LIMBS>
where
UInt<LIMBS>: ArrayEncoding,
{
const TAG: Tag = Tag::Integer;
}

0 comments on commit 171f674

Please sign in to comment.