Skip to main content

Identity

Enum Identity 

pub enum Identity {
    PubKey(Vec<u8>),
    Token(u64),
    EcmaKey(Vec<u8>),
}
Expand description

Assembly identity representation for .NET CIL assemblies.

Represents the cryptographic identity of a .NET assembly using one of three standardized identity mechanisms defined by ECMA-335. This enum supports all primary assembly identification types used throughout the .NET ecosystem.

§Variants

  • Identity::PubKey: Stores the complete RSA public key data for strong-named assemblies
  • Identity::Token: Stores an 8-byte hash of the public key for compact representation
  • Identity::EcmaKey: Stores a 16-byte ECMA key used by framework assemblies

§Usage in .NET

  • Strong-named assemblies: Use public keys for cryptographic verification
  • Assembly references: Often use tokens for compact storage in metadata
  • GAC storage: Uses tokens as part of the unique assembly identifier
  • Security policies: May require full public key validation

§Examples

use dotscope::metadata::identity::Identity;
use dotscope::metadata::tables::AssemblyHashAlgorithm;

// Full public key identity
let pubkey_data = vec![0x30, 0x82, 0x01, 0x0A]; // RSA public key start
let identity = Identity::from(&pubkey_data, true)?;

// Generate token for compact representation
match identity {
    Identity::PubKey(ref key_data) => {
        let token = identity.to_token(AssemblyHashAlgorithm::SHA1)?;
        println!("Key length: {} bytes, Token: 0x{:016X}", key_data.len(), token);
    }
    Identity::Token(token) => {
        println!("Direct token: 0x{:016X}", token);
    }
    _ => {}
}

Variants§

§

PubKey(Vec<u8>)

Complete RSA public key data for strong-named assemblies.

Contains the full binary representation of an RSA public key as stored in .NET assembly metadata. This data can be used for cryptographic verification of assembly signatures and strong name validation.

§Format

The data typically follows the standard RSA public key format used by .NET:

  • ASN.1 DER encoding for the public key structure
  • May include additional .NET-specific metadata
  • Variable length depending on key size (typically 1024-4096 bits)
§

Token(u64)

Compact 8-byte token derived from hashing the public key.

The token is computed as the last 8 bytes of the hash (MD5 or SHA1) of the public key data. This provides a compact identifier while maintaining reasonable uniqueness for assembly identification purposes.

§Token Generation

  1. Hash the complete public key using the specified algorithm
  2. Extract the last 8 bytes of the hash result
  3. Interpret as little-endian 64-bit unsigned integer

§Collision Resistance

While 8 bytes provides only 64 bits of collision resistance, this is considered sufficient for .NET assembly identification in practice.

§

EcmaKey(Vec<u8>)

ECMA standard 16-byte key for framework assemblies.

ECMA keys are special shortened cryptographic identities used by core framework assemblies as defined in ECMA-335. These 16-byte keys provide a standardized identity mechanism for system assemblies while being more compact than full RSA public keys.

§Usage Context

  • Framework assemblies: mscorlib, System.Core, System.dll, etc.
  • Standard libraries: Core .NET framework components
  • Platform assemblies: Mono framework assemblies
  • Compatibility: Legacy and cross-platform .NET implementations

§Format

ECMA keys are exactly 16 bytes in length and follow the ECMA-335 specification for standard assembly identification. Unlike full public keys, they cannot be used for cryptographic verification but provide reliable assembly identification.

§Examples

Common ECMA key patterns found in framework assemblies:

  • Fixed byte sequences for standard framework components
  • Platform-specific variations for Mono/Unity implementations
  • Standardized keys for cross-platform compatibility

Implementations§

§

impl Identity

pub fn from(data: &[u8], is_pub: bool) -> Result<Self>

Create an Identity from raw binary data.

Constructs the appropriate identity type based on data length and the is_pub flag. This method automatically detects ECMA keys and provides the primary constructor for identity objects parsed from .NET metadata.

§Arguments
  • data - Raw binary data from assembly metadata
  • is_pub - true for public key data, false for token data
§Detection Logic
§Returns
§Errors

Returns [crate::Error::OutOfBounds] if:

  • Token creation requested but data has fewer than 8 bytes
  • Data cannot be read as little-endian u64
§Examples
use dotscope::metadata::identity::Identity;

// Create full RSA public key identity (>16 bytes)
let pubkey_data = vec![0x30, 0x82, 0x01, 0x0A, /* ... rest of 160+ byte key ... */];
let pubkey_identity = Identity::from(&pubkey_data, true)?;

// Create ECMA key identity (exactly 16 bytes)
let ecma_data = vec![0x06, 0x28, 0xAC, 0x03, 0x00, 0x06, 0x7A, 0x06,
                     0x6F, 0xAB, 0x02, 0x00, 0x0A, 0x0B, 0x17, 0x6A];
let ecma_identity = Identity::from(&ecma_data, true)?;

// Create token identity (8 bytes)
let token_data = vec![0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0];
let token_identity = Identity::from(&token_data, false)?;

match ecma_identity {
    Identity::EcmaKey(ref key) => println!("ECMA key: {} bytes", key.len()),
    Identity::PubKey(ref key) => println!("Public key: {} bytes", key.len()),
    Identity::Token(token) => println!("Token: 0x{:016X}", token),
}
§Thread Safety

This method is thread-safe and can be called concurrently from multiple threads.

pub fn to_token(&self, algo: u32) -> Result<u64>

Generate a token from this identity using the specified hash algorithm.

Computes an 8-byte token that uniquely identifies this assembly. For public key identities, this involves hashing the key data. For token identities, this returns the stored token value regardless of the algorithm specified.

§Algorithm Support
§Token Extraction

The token is always the last 8 bytes of the hash result, interpreted as a little-endian 64-bit unsigned integer. This follows the .NET runtime convention.

§Arguments
§Returns

64-bit token value suitable for assembly identification and comparison.

§Errors

Returns an error if:

  • The hash algorithm is not supported (only MD5 and SHA1 are implemented)
  • The hash result cannot be read as a little-endian u64
§Examples
use dotscope::metadata::identity::Identity;
use dotscope::metadata::tables::AssemblyHashAlgorithm;

let pubkey_data = vec![0x30, 0x82, /* ... public key data ... */];
let identity = Identity::from(&pubkey_data, true)?;

// Generate token using SHA1 (recommended)
let sha1_token = identity.to_token(AssemblyHashAlgorithm::SHA1)?;
println!("SHA1 token: 0x{:016X}", sha1_token);

// Generate token using MD5 (legacy)
let md5_token = identity.to_token(AssemblyHashAlgorithm::MD5)?;
println!("MD5 token: 0x{:016X}", md5_token);

// Different algorithms produce different tokens
assert_ne!(sha1_token, md5_token);
§Thread Safety

This method is thread-safe and can be called concurrently from multiple threads. Hash operations are stateless and do not modify the identity instance.

Trait Implementations§

§

impl Clone for Identity

§

fn clone(&self) -> Identity

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for Identity

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl Eq for Identity

§

impl Hash for Identity

§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
§

impl PartialEq for Identity

§

fn eq(&self, other: &Identity) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
§

impl StructuralPartialEq for Identity

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AsAny for T
where T: Any,

Source§

fn as_any(&self) -> &(dyn Any + 'static)

Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Source§

fn type_name(&self) -> &'static str

Gets the type name of self
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: AsAny + ?Sized,

Source§

fn is<T>(&self) -> bool
where T: AsAny,

Returns true if the boxed type is the same as T. Read more
Source§

fn downcast_ref<T>(&self) -> Option<&T>
where T: AsAny,

Forward to the method defined on the type Any.
Source§

fn downcast_mut<T>(&mut self) -> Option<&mut T>
where T: AsAny,

Forward to the method defined on the type Any.
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, A> IntoAst<A> for T
where T: Into<A>, A: Ast,

Source§

fn into_ast(self, _a: &A) -> A

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Scalar for T
where T: 'static + Clone + PartialEq + Debug,

Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> TryClone for T
where T: Clone,

Source§

fn try_clone(&self) -> Result<T, Error>

Clones self, possibly returning an error.
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more