Skip to content

Commit

Permalink
feat: C509 AlgorithmIdentifier for subjectPublicKeyAlgorithm and …
Browse files Browse the repository at this point in the history
…`issuerSignatureAlgorithm` (#610)

* feat: setup c509 lib

* fix: update toml file

* feat: add earthfile

* fix: remove blank line

* docs: Add CatalystDataGatewayRepository docs (#388)

* test: Fix tests after cat-gateway update.

* docs: Add `CatalystDataGatewayRepository` usage examples.

* docs: Move docs from README to code comment.

* test: Update `CatalystDataGatewayRepository` tests.

* test: Use Fake instead of Mock.

* chore: Fix Markdown errors.

* chore: Explicit use of `HttpStatus` codes.

* adds one more worker and compression for catgateway logs (#400)

* feat: Collect flutter code coverage (#404)

* test: Fix tests after cat-gateway update.

* docs: Add `CatalystDataGatewayRepository` usage examples.

* docs: Move docs from README to code comment.

* test: Update `CatalystDataGatewayRepository` tests.

* test: Use Fake instead of Mock.

* chore: Fix Markdown errors.

* chore: Explicit use of `HttpStatus` codes.

* chore(deps-dev): bump vite in /utilities/wallet-tester (#397)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 5.1.6 to 5.1.7.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v5.1.7/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v5.1.7/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Apisit Ritreungroj <38898766+apskhem@users.noreply.github.com>

* feat: Get slot number by provided date-time endpoint (#387)

* fix CardanoStakeAddress error handling

* refactor, add sync_state_get endpoint

* refactor types

* refactor

* add block_hash validation

* wip

* wip

* wip

* wip

* add check_network fn

* fix

* fix schematisis test

* try

* wip

* try

* try

* try

* try

* wip

* try

* try

* fix

* update Network

* add test_utxo test

* try

* fix

* try

* fix

* wip

* fix

* fix docket-compose.yml file

* try

* try

* fix

* try

* try

* try

* try

* wip

* fix

* wip

* try

* try

* wip

* try

* try

* revert

* wip

* wip

* wip

* fix

* fix

* fix

* remove mithril_snapshot loader

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* add stake addr bech32 encode utils function

* wip

* wip

* update indexing of the utxo data

* fix spelling

* wip

* wip

* finish utxo test

* fix deny

* fix check

* fix

* fix

* update earthly builder versions

* wip

* ignore test_utxo.py in CI

* dont ignore tests

* add date_time_to_slot_number_get endpoint

* add sql queries

* fix

* update slot info, fix follower indexing block time issue

* add previous slot info field

* fix

* refactor

* fix sync_state_get

* wip

* fix check

* try

* fix

* finish slot_info test, fix queries

* fix

* cleanup

* wip

* wip

* wip

* feat: RBAC Documentation Drafting (#332)

* chore: wip

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* Update 0005-flutter-app.md

* docs(docs): Use latest docs builders and fix concepts page

* docs(cips): Start drafting the CIPS for milestone 2

* docs(cips): More text for RBAC metadata draft

* docs(cips): WIP updates to draft cip for role registration

* docs(cips): define draft specification for a ULID cbor tag

* docs(cips): Further WIP edits to RBAC

* docs(cips): fix ulid spec binary encoding reference

* docs(cips): Add a tag to the epoch time.

* docs(cips): Add CBOR tag cip for ED25519-BIP32 Keys, Derivation paths and Signatures

* docs(cips): Properly define the field tags to use where known, and clean up Stake Address specification.

* docs(cips): Fix nonce so its reliable without needing blockchain data

* docs(cips): updates

* docs(docs): Add CDDL definition for POC x509 envelope metadata

* fix(vscode): update vscode extension recommendations

* docs(cips): rbac x509 envelope fix

* docs(cips): wip updates to high level docs

* docs(cips): Add overview of cardano transaction processign and data

* docs(cips): update cardano block to be complete for clarity

* docs(cips): fix layout engine

* docs(cips): wip cddl for envelope metadata

* docs(cips): Add cddl specs and diagrams for x509 rbac registration work

* docs(cips): Add full transaction/metadata relationship diagram

* refactor(cips): reorganize documentation ready for drafting descriptive prose about the formats and uses

* docs(cips): add cip draft for catalyst roles using the x509-rbac standard

* docs(cips): Add c509 cddl with restrictions and enhancements for plutus usage

* docs(cips): Metadata envelope specification draft complete

* Update docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/x509-role-registration-metadata/x509-roles.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/x509-role-registration-metadata/x509-roles.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/x509-envelope-metadata/x509-envelope.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/x509-envelope-metadata/x509-envelope.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/x509-envelope-metadata/x509-envelope.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* Update docs/src/catalyst-standards/draft-cips/c509-plutus-restricted-certificate/c509-cert-plutus-restricted.cddl

Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* docs(cips): Fix time and algorithm comments

* build(frontend): Relax flutter/dart version requirements to last minor release

* docs(cips): wip

* fix(cips): rename draft x509 envelope CIP so its easier to identify

* docs(cips): WIP updates to x509 roles

* fix(cips): rename RBAC definition CIP draft so its easier to identify

* docs(cips): x509 certificate registration format fully defined

* docs(cips): Document the restricted plutus subset.

* docs(cips): Add document detailing how CIP-30 is used to sign the transaction

* fix(cips): remove trailing spaces

* fix(cips): Fix line lengths

* fix(cips): Correct spelling

* fix(cips): spelling

* fix(frontend): revert changes to flutter/dart versions

* fix(frontend): more flutter/dart version corrections

* fix(frontend): Revert flutter files to same as main branch

* fix(frontend): revert more flutter .yml files to those in main

* fix(cips): Fix links between files

* docs(cips): Add catalyst specific role registration documentation

* docs(spelling): fix spelling

---------

Co-authored-by: minikin <djminikin@gmail.com>
Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* ci: configure static analysis & code formatting check

* style: formatting

* fix: revert browser installation scripts

* style: format code

* ci: optimize directions include in repo-catalyst-voices-all artifact to include only needed ones

* refactor: remove empty tests

* ci: add melos script to generate test reports

* ci: melos script to generate test report

* style: revert previously generated files formatting

* style: format files

* ci: update melos to exclude generated code form code coverage

* ci: cleanup build script

* ci: generate multiple junit test reports and save them at /test_reports

* ci: depend on melos analyze instead of custom command

* docs: improve melos docs

* ci: remove unused melos scripts

* ci: format files in test & integration_test directories

* ci: break code to make sure CI will report failure for demonstration purposes

* style: fix lint issues

* ci: change WORKDIR after creating the user to make sure it will be owned by that user

* ci: restore root user

* Revert "Merge branch 'main' into feat/collect-flutter-code-coverage"

This reverts commit d0f66b2, reversing
changes made to 39ce401.

* style: format code

* ci: revert test-unit target name

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Lucio Baglione <coire1@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Apisit Ritreungroj <38898766+apskhem@users.noreply.github.com>
Co-authored-by: Alex Pozhylenkov <leshiy12345678@gmail.com>
Co-authored-by: Steven Johnson <stevenj@users.noreply.github.com>
Co-authored-by: minikin <djminikin@gmail.com>
Co-authored-by: bkioshn <35752733+bkioshn@users.noreply.github.com>

* refactor: update schema_validation check (#414)

* update schema_validation check

* wip

* fix

* fix: update wasm testing

* fix: remove clippy toml

* fix: update cargo toml

* fix: spelling

* fix: revert test report

* chore: add comment

* chore: update message

* fix: update cargo.toml

* chore: fix format

* fix: linter

* fix: update cargo toml

* fix: update cargo toml

* fix: update project dic

* fix: remove wasm-pack install

* feat: add config

* fix: earthly  for c509

* feat: add regex dependency

* feat: implement c509 type name

* fix: clean up lib.rs

* fix: add c509 cert module

* feat: add x690 der

* feat: wip TLV extract value

* chore: add comment on TLV length

* fix (wip): update der parser

* fix (wip): update der parser

* fix (wip): update der parser

* fix (wip): update der parser

* fix (wip): dependencies

* feat(wip): add c509 enum

* feat(wip): add cbor encode helper

* feat(wip): add c509 cert helper

* fix(wip): modify lib

* feat(wip): add subject public key encoder

* fix: add thiserror

* fix: cbor encode biguint and type name

* fix: cbor encode time

* fix: cleanup

* fix: add oid crate

* feat: add extensions

* feat: add alt name

* chore: remove fixme

* fix: clean up c509 enum

* fix: rewrite cbor encoder

* fix: move c509 crate folder

* feat: add gitignore

* fix: cargo toml

* fix: cbor encoder

* fix: remove der encoding

* feat: add eid encoder

* fix: ssp encoder

* feat: create genc509cert function

* feat: add sigalgo registry

* fix: altname type visibility

* fix: altname encoder

* feat: add extension encoding func

* fix: lib.rs

* fix: gen c509 function

* fix: cbor encoder

* fix: alt name

* fix: extensions

* docs: update c509 docs

* fix: name

* chore: remove unnecessary comments

* fix: macro definitions location

* fix: earthly version and cspell

* fix: update rust config file to match cat-ci stdcfg

* fix: macro definitions location

* feat: add oid encode/decode

* fix: naming and test

* fix: naming

* fix: implement encode and decode trait

* fix: test

* feat: add OID PEN encode and decode

* fix: merge

* fix: merge

* wip

* fix: pen decode and encode

* fix: rewrite PEN encode and decode

* chore: add comments

* fix: update c509 extensions

* fix: add once cell

* fix: oid registry and oid extension implementation

* fix (wip): extension value encoding

* fix: value encode and test

* fix: add decode extension

* fix: extension decode value

* fix: delete files

* fix(wip): handle extensions

* fix: disable extensions encode and decode

* fix: cargo toml and add num-derive

* fix(wip): refactor tables

* feat(wip): add encode decode general name

* fix: name and type

* fix(wip): decode and encode generalnames

* fix(wip): gn value encode decode

* fix: remove unused crate

* fix: gns encode and decode

* fix: remove unused table

* fix: oid lifetime to static

* fix: create extensions mod

* fix: general name visibility

* feat: add alt name

* feat: add alternative name encode and decode

* fix: minor fixes + cleanup

* chore: use super in test

* fix: remove unused ctx type C

* fix(wip): extensions

* feat: add strum crate

* fix: tables

* fix: extensions

* fix: general name

* fix: table

* fix: alt name

* fix: extensions

* fix: refactor

* feat(wip): add eid

* chore: spelling

* chore: spelling

* chore: revert back to main

* chore: restore file in main

* fix: update rust stdconfig and earthfile

* fix: earthfile

* fix: earthfile

* fix: earthfile

* fix: wrong earthfile

* fix: doc link

* Update catalyst-gateway-crates/c509-certificate/src/c509_extensions/mod.rs

Co-authored-by: Apisit Ritreungroj <38898766+apskhem@users.noreply.github.com>

* Update catalyst-gateway-crates/c509-certificate/src/c509_extensions/mod.rs

Co-authored-by: Apisit Ritreungroj <38898766+apskhem@users.noreply.github.com>

* bump cat-ci

* bump deny.toml

* fix fmt

* fix machete

* fix

* fix: minor fix and update doc

* chore: code format

* bump cat-ci

* update build

* fix: doc

* test: new cliipy ci fix

* test: new cliipy ci fix fix cargo toml

* fix: orphan module

* fix: remove EID

* fix: comment out wasm pack build

* fix: add chaining

* fix: linter

* fix: PR comment

* fix: move code section

* chore: fix name and comment

* fix: format

* test: add zero extensions

* fix: format

* fix: gn type naming

* chore: remove unused file

* test: add test case for multiples gn type

* fix: dns gn decode special case

* fix: format

* fix: data tables

* fix: alt name test case

* fix: cspell

* fix: table functions

* fix: format

* chore: fix test comment

* feat: implement algorithm identifier

* fix: add test case for algo iden

* fix: comment and syntax

* fix: spelling and naming

* fix: cspell

* fix: data table struct

* fix: getter func

* fix: getter func

* fix: getter func

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Lucio Baglione <coire1@gmail.com>
Co-authored-by: Stefano Cunego <93382903+kukkok3@users.noreply.github.com>
Co-authored-by: Dominik Toton <166132265+dtscalac@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Apisit Ritreungroj <38898766+apskhem@users.noreply.github.com>
Co-authored-by: Alex Pozhylenkov <leshiy12345678@gmail.com>
Co-authored-by: Steven Johnson <stevenj@users.noreply.github.com>
Co-authored-by: minikin <djminikin@gmail.com>
Co-authored-by: Steven Johnson <sakurainds@gmail.com>
  • Loading branch information
10 people authored Jul 12, 2024
1 parent e1a9492 commit 2f3ccb2
Show file tree
Hide file tree
Showing 6 changed files with 534 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
//! C509 Algorithm Identifier
//! This module handle the `AlgorithmIdentifier` type where OID does not fall into the
//! table.
//!
//! ```cddl
//! AlgorithmIdentifier = int / ~oid / [ algorithm: ~oid, parameters: bytes ]
//! ```
//!
//! For more information about `AlgorithmIdentifier`,
//! visit [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/)
use asn1_rs::Oid;
use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder};

use crate::c509_oid::C509oid;

/// A struct represents the `AlgorithmIdentifier` type.
#[derive(Debug, Clone, PartialEq)]
pub struct AlgorithmIdentifier {
/// A `C509oid`
oid: C509oid,
/// An optional parameter string
param: Option<String>,
}

impl AlgorithmIdentifier {
/// Create new instance of `AlgorithmIdentifier`.
#[must_use]
pub fn new(oid: Oid<'static>, param: Option<String>) -> Self {
Self {
oid: C509oid::new(oid),
param,
}
}

/// Get the OID.
pub(crate) fn get_oid(&self) -> Oid<'static> {
self.oid.clone().get_oid()
}

/// Get the parameter.
pub(crate) fn get_param(&self) -> &Option<String> {
&self.param
}
}

impl Encode<()> for AlgorithmIdentifier {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
match &self.param {
// [ algorithm: ~oid, parameters: bytes ]
Some(p) => {
e.array(2)?;
self.oid.encode(e, ctx)?;
e.bytes(p.as_bytes())?;
},
// ~oid
None => {
self.oid.encode(e, ctx)?;
},
}
Ok(())
}
}

impl Decode<'_, ()> for AlgorithmIdentifier {
fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result<Self, minicbor::decode::Error> {
// [ algorithm: ~oid, parameters: bytes ]
if d.datatype()? == minicbor::data::Type::Array {
let len = d.array()?.ok_or(minicbor::decode::Error::message(
"Failed to get array length",
))?;
if len != 2 {
return Err(minicbor::decode::Error::message("Array length must be 2"));
}
let c509_oid = C509oid::decode(d, ctx)?;
let param =
String::from_utf8(d.bytes()?.to_vec()).map_err(minicbor::decode::Error::message)?;
Ok(AlgorithmIdentifier::new(c509_oid.get_oid(), Some(param)))
// ~oid
} else {
let oid = C509oid::decode(d, ctx)?;
Ok(AlgorithmIdentifier::new(oid.get_oid(), None))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//! Signature algorithm data provides a necessary information for encoding and decoding of
//! C509 `issuerSignatureAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/)
//! Section 9.10 C509 Signature Algorithms Registry for more information.
// cspell: words RSASSA XMSS

use anyhow::Error;
use asn1_rs::{oid, Oid};
use once_cell::sync::Lazy;

use crate::tables::IntegerToOidTable;

/// Type of algorithm data
/// INT | OID | Name
type AlgorithmDataTuple = (i16, Oid<'static>, &'static str);

/// Signature algorithm data table.
#[rustfmt::skip]
const SIG_ALGO_DATA: [AlgorithmDataTuple; 24] = [
// Int | OID | Name
(-256, oid!(1.2.840.113549.1.1.5), "RSASSA-PKCS1-v1_5 with SHA-1"),
(-255, oid!(1.2.840.10045.4.1), "ECDSA with SHA-1"),
(0, oid!(1.2.840.10045.4.3.2), "ECDSA with SHA-256"),
(1, oid!(1.2.840.10045.4.3.3), "ECDSA with SHA-384"),
(2, oid!(1.2.840.10045.4.3.4), "ECDSA with SHA-512"),
(3, oid!(1.3.6.1.5.5.7.6.32), "ECDSA with SHAKE128"),
(4, oid!(1.3.6.1.5.5.7.6.33), "ECDSA with SHAKE256"),
(12, oid!(1.3.101.112), "Ed25519"),
(13, oid!(1.3.101.113), "Ed448"),
(14, oid!(1.3.6.1.5.5.7.6.26), "SHA-256 with HMAC-SHA256"),
(15, oid!(1.3.6.1.5.5.7.6.27), "SHA-384 with HMAC-SHA384"),
(16, oid!(1.3.6.1.5.5.7.6.28), "SHA-512 with HMAC-SHA512"),
(23, oid!(1.2.840.113549.1.1.11), "RSASSA-PKCS1-v1_5 with SHA-256"),
(24, oid!(1.2.840.113549.1.1.12), "RSASSA-PKCS1-v1_5 with SHA-384"),
(25, oid!(1.2.840.113549.1.1.13), "RSASSA-PKCS1-v1_5 with SHA-512"),
(26, oid!(1.2.840.113549.1.1.10), "RSASSA-PSS with SHA-256"),
(27, oid!(1.2.840.113549.1.1.10), "RSASSA-PSS with SHA-384"),
(28, oid!(1.2.840.113549.1.1.10), "RSASSA-PSS with SHA-512"),
(29, oid!(1.3.6.1.5.5.7.6.30), "RSASSA-PSS with SHAKE128"),
(30, oid!(1.3.6.1.5.5.7.6.3), "RSASSA-PSS with SHAKE256"),
(42, oid!(1.2.840.113549.1.9.16.3.17), "HSS / LMS"),
(43, oid!(0.4.0.127.0.15.1.1.13.0), "XMSS"),
(44, oid!(0.4.0.127.0.15.1.1.14.0), "XMSS^MT"),
(45, oid!(1.2.156.10197.1.501), "SM2 with SM3"),
];

/// A struct of data that contains lookup table of integer to OID in
/// bidirectional way for `IssuerSignatureAlgorithm`.
pub(crate) struct IssuerSigAlgoData(IntegerToOidTable);

impl IssuerSigAlgoData {
/// Get the `IntegerToOidTable`
pub(crate) fn get_int_to_oid_table(&self) -> &IntegerToOidTable {
&self.0
}
}

/// Define static lookup for issuer signature algorithm table
static ISSUER_SIG_ALGO_TABLE: Lazy<IssuerSigAlgoData> = Lazy::new(|| {
let mut int_to_oid_table = IntegerToOidTable::new();

for data in SIG_ALGO_DATA {
int_to_oid_table.add(data.0, data.1);
}

IssuerSigAlgoData(int_to_oid_table)
});

/// Static reference to the `IssuerSigAlgoData` lookup table.
pub(crate) static ISSUER_SIG_ALGO_LOOKUP: &Lazy<IssuerSigAlgoData> = &ISSUER_SIG_ALGO_TABLE;

/// Get the OID from the int value.
pub(crate) fn get_oid_from_int(i: i16) -> Result<Oid<'static>, Error> {
ISSUER_SIG_ALGO_TABLE
.get_int_to_oid_table()
.get_map()
.get_by_left(&i)
.ok_or(Error::msg(format!(
"OID not found in the signature algorithms registry table given int {i}"
)))
.cloned()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
//! C509 Issuer Signature Algorithm as a part of `TBSCertificate` used in C509
//! Certificate.
//!
//! ```cddl
//! issuerSignatureAlgorithm: AlgorithmIdentifier
//! ```
mod data;
use asn1_rs::Oid;
use data::{get_oid_from_int, ISSUER_SIG_ALGO_LOOKUP};
use minicbor::{encode::Write, Decode, Decoder, Encode, Encoder};

use crate::{c509_algo_identifier::AlgorithmIdentifier, c509_oid::C509oidRegistered};

/// A struct represents the `IssuerSignatureAlgorithm`
#[derive(Debug, Clone, PartialEq)]
pub struct IssuerSignatureAlgorithm {
/// The registered OID of the `IssuerSignatureAlgorithm`.
registered_oid: C509oidRegistered,
/// An `AlgorithmIdentifier` type
algo_identifier: AlgorithmIdentifier,
}

impl IssuerSignatureAlgorithm {
/// Create new instance of `IssuerSignatureAlgorithm` where it registered with
/// Issuer Signature Algorithm lookup table.
pub fn new(oid: Oid<'static>, param: Option<String>) -> Self {
Self {
registered_oid: C509oidRegistered::new(
oid.clone(),
ISSUER_SIG_ALGO_LOOKUP.get_int_to_oid_table(),
),
algo_identifier: AlgorithmIdentifier::new(oid, param),
}
}
}

impl Encode<()> for IssuerSignatureAlgorithm {
fn encode<W: Write>(
&self, e: &mut Encoder<W>, ctx: &mut (),
) -> Result<(), minicbor::encode::Error<W::Error>> {
if let Some(&i) = self
.registered_oid
.get_table()
.get_map()
.get_by_right(&self.registered_oid.get_c509_oid().get_oid())
{
e.i16(i)?;
} else {
AlgorithmIdentifier::encode(&self.algo_identifier, e, ctx)?;
}
Ok(())
}
}

impl Decode<'_, ()> for IssuerSignatureAlgorithm {
fn decode(d: &mut Decoder<'_>, ctx: &mut ()) -> Result<Self, minicbor::decode::Error> {
match d.datatype()? {
// Check i16 for -256 and -256
minicbor::data::Type::U8 | minicbor::data::Type::I16 => {
let i = d.i16()?;
let oid = get_oid_from_int(i).map_err(minicbor::decode::Error::message)?;
Ok(Self::new(oid, None))
},
_ => {
let algo_identifier = AlgorithmIdentifier::decode(d, ctx)?;
Ok(IssuerSignatureAlgorithm::new(
algo_identifier.get_oid(),
algo_identifier.get_param().clone(),
))
},
}
}
}

// ------------------Test----------------------

#[cfg(test)]
mod test_issuer_signature_algorithm {
use asn1_rs::oid;

use super::*;

#[test]
fn test_registered_oid() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);

let isa = IssuerSignatureAlgorithm::new(oid!(1.3.101 .112), None);
isa.encode(&mut encoder, &mut ())
.expect("Failed to encode IssuerSignatureAlgorithm");

// Ed25519 - int 12: 0x0c
assert_eq!(hex::encode(buffer.clone()), "0c");

let mut decoder = Decoder::new(&buffer);
let decoded_isa = IssuerSignatureAlgorithm::decode(&mut decoder, &mut ())
.expect("Failed to decode IssuerSignatureAlgorithm");
assert_eq!(decoded_isa, isa);
}

#[test]
fn test_unregistered_oid() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);

let isa = IssuerSignatureAlgorithm::new(oid!(2.16.840 .1 .101 .3 .4 .2 .1), None);
isa.encode(&mut encoder, &mut ())
.expect("Failed to encode IssuerSignatureAlgorithm");

// 2.16.840 .1 .101 .3 .4 .2 .1: 0x49608648016503040201
assert_eq!(hex::encode(buffer.clone()), "49608648016503040201");

let mut decoder = Decoder::new(&buffer);
let decoded_isa = IssuerSignatureAlgorithm::decode(&mut decoder, &mut ())
.expect("Failed to decode IssuerSignatureAlgorithm");
assert_eq!(decoded_isa, isa);
}

#[test]
fn test_unregistered_oid_with_param() {
let mut buffer = Vec::new();
let mut encoder = Encoder::new(&mut buffer);

let isa = IssuerSignatureAlgorithm::new(
oid!(2.16.840 .1 .101 .3 .4 .2 .1),
Some("example".to_string()),
);
isa.encode(&mut encoder, &mut ())
.expect("Failed to encode IssuerSignatureAlgorithm");
// Array of 2 items: 0x82
// 2.16.840 .1 .101 .3 .4 .2 .1: 0x49608648016503040201
// bytes "example": 0x476578616d706c65
assert_eq!(
hex::encode(buffer.clone()),
"8249608648016503040201476578616d706c65"
);

let mut decoder = Decoder::new(&buffer);
let decoded_isa = IssuerSignatureAlgorithm::decode(&mut decoder, &mut ())
.expect("Failed to decode IssuerSignatureAlgorithm");
assert_eq!(decoded_isa, isa);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
//! Public key algorithm data provides a necessary information for encoding and decoding
//! of C509 `subjectPublicKeyAlgorithm`. See [C509 Certificate](https://datatracker.ietf.org/doc/draft-ietf-cose-cbor-encoded-cert/09/)
//! Section 9.11 C509 Public Key Algorithms Registry for more information.
// cspell: words Weierstraß secp XMSS brainpool

use anyhow::Error;
use asn1_rs::{oid, Oid};
use once_cell::sync::Lazy;

use crate::tables::IntegerToOidTable;

/// Type of algorithm data
/// INT | OID | Name
type AlgorithmDataTuple = (i16, Oid<'static>, &'static str);

/// Public key algorithm data table.
#[rustfmt::skip]
const PUB_KEY_ALGO_DATA: [AlgorithmDataTuple; 16] = [
// Int | OID | Name
(0, oid!(1.2.840.113549.1.1.1), "RSA"),
(1, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with secp256r1"),
(2, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with secp384r1"),
(3, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with secp521r1"),
(8, oid!(1.3.101.110), "X25519 (Montgomery)"),
(9, oid!(1.3.101.111), "X448 (Montgomery)"),
(10, oid!(1.3.101.112), "Ed25519 (Twisted Edwards)"),
(11, oid!(1.3.101.113), "Ed448 (Edwards)"),
(16, oid!(1.2.840.113549.1.9.16.3.17), "HSS / LMS"),
(17, oid!(0.4.0.127.0.15.1.1.13.0), "XMSS"),
(18, oid!(0.4.0.127.0.15.1.1.14.0), "XMSS^MT"),
(24, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with brainpoolP256r1"),
(25, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with brainpoolP384r1"),
(26, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with brainpoolP512r1"),
(27, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with FRP256v1"),
(28, oid!(1.2.840.10045.2.1), "EC Public Key (Weierstraß) with sm2p256v1"),
];

/// A struct of data that contains lookup table of integer to OID in
/// bidirectional way for `SubjectPublicKeyAlgorithm`.
pub(crate) struct SubjectPubKeyAlgoData(IntegerToOidTable);

impl SubjectPubKeyAlgoData {
/// Get the `IntegerToOidTable`
pub(crate) fn get_int_to_oid_table(&self) -> &IntegerToOidTable {
&self.0
}
}

/// Define static lookup for subject publickey table
static SUBJECT_PUB_KEY_ALGO_TABLE: Lazy<SubjectPubKeyAlgoData> = Lazy::new(|| {
let mut int_to_oid_table = IntegerToOidTable::new();

for data in PUB_KEY_ALGO_DATA {
int_to_oid_table.add(data.0, data.1);
}

SubjectPubKeyAlgoData(int_to_oid_table)
});

/// Static reference to the `SubjectPubKeyAlgoData` lookup table.
pub(crate) static SUBJECT_PUB_KEY_ALGO_LOOKUP: &Lazy<SubjectPubKeyAlgoData> =
&SUBJECT_PUB_KEY_ALGO_TABLE;

/// Get the OID from the int value.
pub(crate) fn get_oid_from_int(i: i16) -> Result<Oid<'static>, Error> {
SUBJECT_PUB_KEY_ALGO_TABLE
.get_int_to_oid_table()
.get_map()
.get_by_left(&i)
.ok_or(Error::msg(format!(
"OID not found in the public key algorithms registry table given int {i}"
)))
.cloned()
}
Loading

0 comments on commit 2f3ccb2

Please sign in to comment.