Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 38 additions & 1 deletion crypto/src/security/CipherUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,21 @@

namespace Org.BouncyCastle.Security
{
/// <summary>
/// Factory for <see cref="IBufferedCipher"/> instances, resolved from a textual algorithm name (with optional
/// mode/padding components) or from an ASN.1 algorithm OID.
/// </summary>
/// <remarks>
/// Cipher Utility class contains methods that can not be specifically grouped into other classes.
/// <para>
/// Algorithm strings follow the JCA-style <c>ALGORITHM[/MODE[/PADDING]]</c> convention (for example
/// <c>"AES/CBC/PKCS7Padding"</c> or <c>"DESEDE/ECB/NoPadding"</c>). Aliases for common algorithm names and
/// many standard ASN.1 OIDs are recognised. When the input cannot be resolved, a
/// <see cref="SecurityUtilityException"/> is thrown.
/// </para>
/// <para>
/// The returned <see cref="IBufferedCipher"/> is uninitialised; the caller must invoke
/// <see cref="IBufferedCipher.Init"/> before processing data.
/// </para>
/// </remarks>
public static class CipherUtilities
{
Expand Down Expand Up @@ -295,11 +308,25 @@ static CipherUtilities()
#endif
}

/// <summary>
/// Returns the canonical algorithm name registered for the given ASN.1 OID, or <c>null</c> if the OID
/// is not mapped to a known cipher.
/// </summary>
/// <param name="oid">An ASN.1 algorithm identifier.</param>
/// <returns>The canonical algorithm name (suitable for passing to <see cref="GetCipher(string)"/>),
/// or <c>null</c>.</returns>
public static string GetAlgorithmName(DerObjectIdentifier oid)
{
return CollectionUtilities.GetValueOrNull(AlgorithmOidMap, oid);
}

/// <summary>
/// Resolve and instantiate an <see cref="IBufferedCipher"/> for the given ASN.1 algorithm OID.
/// </summary>
/// <param name="oid">The algorithm OID to look up.</param>
/// <returns>A new, uninitialised <see cref="IBufferedCipher"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="oid"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the OID does not map to a known cipher.</exception>
public static IBufferedCipher GetCipher(DerObjectIdentifier oid)
{
if (oid == null)
Expand All @@ -315,6 +342,16 @@ public static IBufferedCipher GetCipher(DerObjectIdentifier oid)
throw new SecurityUtilityException("Cipher OID not recognised.");
}

/// <summary>
/// Resolve and instantiate an <see cref="IBufferedCipher"/> for the given algorithm specification.
/// </summary>
/// <param name="algorithm">A JCA-style cipher name of the form <c>ALGORITHM[/MODE[/PADDING]]</c>
/// (e.g. <c>"AES/CBC/PKCS7Padding"</c>). Aliases such as <c>"DESede"</c> or <c>"3DES"</c> are
/// also accepted.</param>
/// <returns>A new, uninitialised <see cref="IBufferedCipher"/>.</returns>
/// <exception cref="ArgumentNullException">If <paramref name="algorithm"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the algorithm, mode, or padding component is not
/// recognised.</exception>
public static IBufferedCipher GetCipher(string algorithm)
{
if (algorithm == null)
Expand Down
45 changes: 41 additions & 4 deletions crypto/src/security/DigestUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,12 @@

namespace Org.BouncyCastle.Security
{
/// <summary>
/// Factory for <see cref="IDigest"/> instances and convenience helpers for one-shot hash computation.
/// </summary>
/// <remarks>
/// Utility class for creating IDigest objects from their names/Oids
/// Digests can be looked up by canonical name (e.g. <c>"SHA-256"</c>, <c>"SHA3-512"</c>) or by ASN.1 OID.
/// Names are matched case-insensitively and a number of common aliases are recognised.
/// </remarks>
public static class DigestUtilities
{
Expand Down Expand Up @@ -202,67 +206,92 @@ static DigestUtilities()
#endif
}

/// <summary>One-shot digest of <paramref name="input"/> using the algorithm identified by
/// <paramref name="id"/>.</summary>
// TODO[api] Change parameter name to 'oid'
public static byte[] CalculateDigest(DerObjectIdentifier id, byte[] input)
{
return CalculateDigest(id.Id, input);
}

/// <summary>One-shot digest of <paramref name="input"/> using the named algorithm.</summary>
/// <exception cref="SecurityUtilityException">If <paramref name="algorithm"/> is not recognised.</exception>
public static byte[] CalculateDigest(string algorithm, byte[] input)
{
IDigest digest = GetDigest(algorithm);
return DoFinal(digest, input);
}

/// <summary>One-shot digest of <paramref name="len"/> bytes from <paramref name="buf"/> starting at
/// offset <paramref name="off"/>.</summary>
public static byte[] CalculateDigest(string algorithm, byte[] buf, int off, int len)
{
IDigest digest = GetDigest(algorithm);
return DoFinal(digest, buf, off, len);
}

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
/// <summary>One-shot digest of <paramref name="buffer"/> using the algorithm identified by
/// <paramref name="oid"/>.</summary>
public static byte[] CalculateDigest(DerObjectIdentifier oid, ReadOnlySpan<byte> buffer) =>
CalculateDigest(oid.GetID(), buffer);

/// <summary>One-shot digest of <paramref name="buffer"/> using the named algorithm.</summary>
public static byte[] CalculateDigest(string algorithm, ReadOnlySpan<byte> buffer)
{
IDigest digest = GetDigest(algorithm);
return DoFinal(digest, buffer);
}
#endif

/// <summary>Finalises <paramref name="digest"/> and returns the resulting hash as a fresh array.</summary>
public static byte[] DoFinal(IDigest digest)
{
byte[] b = new byte[digest.GetDigestSize()];
digest.DoFinal(b, 0);
return b;
}

/// <summary>Feeds <paramref name="input"/> into <paramref name="digest"/>, then finalises and returns the
/// hash.</summary>
public static byte[] DoFinal(IDigest digest, byte[] input)
{
digest.BlockUpdate(input, 0, input.Length);
return DoFinal(digest);
}

/// <summary>Feeds <paramref name="len"/> bytes from <paramref name="buf"/> at offset
/// <paramref name="off"/> into <paramref name="digest"/>, then finalises and returns the hash.</summary>
public static byte[] DoFinal(IDigest digest, byte[] buf, int off, int len)
{
digest.BlockUpdate(buf, off, len);
return DoFinal(digest);
}

#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
/// <summary>Feeds <paramref name="buffer"/> into <paramref name="digest"/>, then finalises and returns
/// the hash.</summary>
public static byte[] DoFinal(IDigest digest, ReadOnlySpan<byte> buffer)
{
digest.BlockUpdate(buffer);
return DoFinal(digest);
}
#endif

/// <summary>
/// Returns the canonical algorithm name registered for the given ASN.1 OID, or <c>null</c> if the OID
/// is not mapped to a known digest.
/// </summary>
public static string GetAlgorithmName(DerObjectIdentifier oid)
{
return CollectionUtilities.GetValueOrNull(AlgorithmOidMap, oid);
}

/// <summary>
/// Resolve and instantiate an <see cref="IDigest"/> for the given ASN.1 algorithm OID.
/// </summary>
/// <exception cref="ArgumentNullException">If <paramref name="id"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the OID does not map to a known digest.</exception>
// TODO[api] Change parameter name to 'oid'
public static IDigest GetDigest(DerObjectIdentifier id)
{
Expand All @@ -279,6 +308,13 @@ public static IDigest GetDigest(DerObjectIdentifier id)
throw new SecurityUtilityException("Digest OID not recognised.");
}

/// <summary>
/// Resolve and instantiate an <see cref="IDigest"/> by name (or alias).
/// </summary>
/// <param name="algorithm">A digest name (e.g. <c>"SHA-256"</c>, <c>"SHA3-512"</c>,
/// <c>"BLAKE2B-512"</c>).</param>
/// <exception cref="ArgumentNullException">If <paramref name="algorithm"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the digest name is not recognised.</exception>
public static IDigest GetDigest(string algorithm)
{
if (algorithm == null)
Expand Down Expand Up @@ -364,10 +400,11 @@ private static string GetMechanism(string algorithm)
}

/// <summary>
/// Returns an ObjectIdentifier for a given digest mechanism.
/// Returns the ASN.1 OID associated with the named digest mechanism, or <c>null</c> when none is
/// registered.
/// </summary>
/// <param name="mechanism">A string representation of the digest meanism.</param>
/// <returns>A DerObjectIdentifier, null if the Oid is not available.</returns>
/// <param name="mechanism">A digest name or alias (e.g. <c>"SHA-256"</c>).</param>
/// <exception cref="ArgumentNullException">If <paramref name="mechanism"/> is <c>null</c>.</exception>
public static DerObjectIdentifier GetObjectIdentifier(string mechanism)
{
if (mechanism == null)
Expand Down
23 changes: 23 additions & 0 deletions crypto/src/security/GeneratorUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@

namespace Org.BouncyCastle.Security
{
/// <summary>
/// Factory for symmetric key generators (<see cref="CipherKeyGenerator"/>) and asymmetric key pair
/// generators (<see cref="IAsymmetricCipherKeyPairGenerator"/>), resolved by algorithm name or ASN.1 OID.
/// </summary>
/// <remarks>
/// Names are matched case-insensitively. Symmetric generators are pre-configured with the algorithm's
/// default key size; asymmetric generators are returned uninitialised — the caller must invoke
/// <see cref="IAsymmetricCipherKeyPairGenerator.Init"/> with appropriate
/// <see cref="KeyGenerationParameters"/> before generating a key pair.
/// </remarks>
public static class GeneratorUtilities
{
private static readonly IDictionary<string, string> KgAlgorithms =
Expand Down Expand Up @@ -352,11 +362,18 @@ internal static string GetCanonicalKeyPairGeneratorAlgorithm(string algorithm)
return CollectionUtilities.GetValueOrNull(KpgAlgorithms, algorithm);
}

/// <summary>Resolve a <see cref="CipherKeyGenerator"/> for the given symmetric algorithm OID.</summary>
public static CipherKeyGenerator GetKeyGenerator(DerObjectIdentifier oid)
{
return GetKeyGenerator(oid.Id);
}

/// <summary>
/// Resolve a <see cref="CipherKeyGenerator"/> for the named symmetric algorithm (e.g. <c>"AES"</c>,
/// <c>"DESede"</c>, <c>"ChaCha20"</c>), pre-configured with the algorithm's default key size.
/// </summary>
/// <exception cref="SecurityUtilityException">If the algorithm is not recognised or has no default
/// key size.</exception>
public static CipherKeyGenerator GetKeyGenerator(string algorithm)
{
string canonicalName = GetCanonicalKeyGeneratorAlgorithm(algorithm);
Expand All @@ -378,11 +395,17 @@ public static CipherKeyGenerator GetKeyGenerator(string algorithm)
return new CipherKeyGenerator(defaultKeySize);
}

/// <summary>Resolve an <see cref="IAsymmetricCipherKeyPairGenerator"/> for the given algorithm OID.</summary>
public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(DerObjectIdentifier oid)
{
return GetKeyPairGenerator(oid.Id);
}

/// <summary>
/// Resolve an <see cref="IAsymmetricCipherKeyPairGenerator"/> for the named asymmetric algorithm
/// (e.g. <c>"RSA"</c>, <c>"ECDSA"</c>, <c>"Ed25519"</c>, <c>"DH"</c>).
/// </summary>
/// <exception cref="SecurityUtilityException">If the algorithm is not recognised.</exception>
public static IAsymmetricCipherKeyPairGenerator GetKeyPairGenerator(string algorithm)
{
string canonicalName = GetCanonicalKeyPairGeneratorAlgorithm(algorithm);
Expand Down
29 changes: 28 additions & 1 deletion crypto/src/security/MacUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,14 @@

namespace Org.BouncyCastle.Security
{
/// <summary>
/// Factory for <see cref="IMac"/> instances (HMAC, CMAC, GMAC, Poly1305, etc.) and convenience helpers for
/// one-shot MAC computation.
/// </summary>
/// <remarks>
/// Utility class for creating HMac object from their names/Oids
/// MACs can be looked up by canonical name (e.g. <c>"HMAC-SHA256"</c>, <c>"AESCMAC"</c>) or by ASN.1 OID;
/// names are matched case-insensitively. The returned <see cref="IMac"/> is uninitialised — the caller
/// must invoke <see cref="IMac.Init"/> with a key before processing data.
/// </remarks>
public static class MacUtilities
{
Expand Down Expand Up @@ -111,6 +117,12 @@ static MacUtilities()
#endif
}

/// <summary>
/// One-shot MAC of <paramref name="input"/> using the named algorithm and the supplied key parameters.
/// </summary>
/// <param name="algorithm">A MAC name or alias (e.g. <c>"HMAC-SHA256"</c>).</param>
/// <param name="cp">Key (and any other) parameters required to initialise the MAC.</param>
/// <param name="input">The data to authenticate.</param>
public static byte[] CalculateMac(string algorithm, ICipherParameters cp, byte[] input)
{
IMac mac = GetMac(algorithm);
Expand All @@ -119,24 +131,34 @@ public static byte[] CalculateMac(string algorithm, ICipherParameters cp, byte[]
return DoFinal(mac);
}

/// <summary>Finalises <paramref name="mac"/> and returns the resulting tag as a fresh array.</summary>
public static byte[] DoFinal(IMac mac)
{
byte[] b = new byte[mac.GetMacSize()];
mac.DoFinal(b, 0);
return b;
}

/// <summary>Feeds <paramref name="input"/> into <paramref name="mac"/>, then finalises and returns the
/// tag.</summary>
public static byte[] DoFinal(IMac mac, byte[] input)
{
mac.BlockUpdate(input, 0, input.Length);
return DoFinal(mac);
}

/// <summary>
/// Returns the canonical algorithm name registered for the given ASN.1 OID, or <c>null</c> if the OID
/// is not mapped to a known MAC.
/// </summary>
public static string GetAlgorithmName(DerObjectIdentifier oid)
{
return CollectionUtilities.GetValueOrNull(AlgorithmOidMap, oid);
}

/// <summary>Resolve and instantiate an <see cref="IMac"/> for the given ASN.1 algorithm OID.</summary>
/// <exception cref="ArgumentNullException">If <paramref name="id"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the OID does not map to a known MAC.</exception>
// TODO[api] Change parameter name to 'oid'
public static IMac GetMac(DerObjectIdentifier id)
{
Expand All @@ -153,6 +175,11 @@ public static IMac GetMac(DerObjectIdentifier id)
throw new SecurityUtilityException("Mac OID not recognised.");
}

/// <summary>Resolve and instantiate an <see cref="IMac"/> by name (or alias).</summary>
/// <param name="algorithm">A MAC name (e.g. <c>"HMAC-SHA512"</c>, <c>"AESCMAC"</c>,
/// <c>"POLY1305"</c>).</param>
/// <exception cref="ArgumentNullException">If <paramref name="algorithm"/> is <c>null</c>.</exception>
/// <exception cref="SecurityUtilityException">If the MAC name is not recognised.</exception>
public static IMac GetMac(string algorithm)
{
if (algorithm == null)
Expand Down
Loading