Imported Upstream version 3.6.0

Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
This commit is contained in:
Jo Shields
2014-08-13 10:39:27 +01:00
commit a575963da9
50588 changed files with 8155799 additions and 0 deletions

View File

@ -0,0 +1,379 @@
2010-05-25 Jb Evain <jbevain@novell.com>
* CryptoTools.cs: make types internal for INSIDE_SYSCORE as well.
2010-03-16 Jb Evain <jbevain@novell.com>
* CryptoTools.cs, PKCS1.cs, PKCS8.cs, SymmetricTransform.cs,
KeyPairPersistence.cs: use MOONLIGHT symbol to disambiguate
MonoTouch and Moonlight code.
2009-09-18 Sebastien Pouliot <sebastien@ximian.com>
* PKCS1.cs: Fix compiler warning for NET_2_1
2009-04-30 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs, PKCS8.cs: Adapt to work with only [DSA|RSA]
Managed when built for NET_2_1, i.e. remove use of [DSA|RSA]
CryptoServiceProvider
* KeyPairPersistence.cs: Remove from NET_2_1
2009-04-29 Sebastien Pouliot <sebastien@ximian.com>
* PKCS1.cs: Make this work under NET_2_1 where SHA384 and SHA512
are not available in the BCL.
2008-08-07 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Make this (more) usable with SL2 limited
crypto support.
2008-08-05 Sebastien Pouliot <sebastien@ximian.com>
* CryptoTools.cs: Make this usable with Silverlight 2.0 (NET_2_1)
2008-04-21 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Fix HMAC to respect start index inside an array.
Patch by Kazuki Oikawa.
2008-03-13 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Re-order exception handling to report the most
precise error to caller. Apply RSA extra check to DSA.
* RSAManaged.cs: Test imported parameters to ensure the public and
private parts of the keypair match together.
2008-03-04 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fix ANSIX923 padding check (#366623) to be
just like PKCS7 (but comparing to 0).
2008-02-03 Sebastien Pouliot <sebastien@ximian.com>
* DSAManaged.cs: Replace "" (found by Gendarme) with more useful text.
* RSAManaged.cs: Replace "" (found by Gendarme) with more useful text.
2008-01-10 Sebastien Pouliot <sebastien@ximian.com>
* PKCS1.cs: Add a new method that optionally checks for badly
padding, technically invalid, PKCS#1 block. This is required to
support timestamping verification for Authenticode (since the
main timestamping service does this). Fix for #350958
2007-11-18 Sebastien Pouliot <sebastien@ximian.com>
* RSAManaged.cs: Fix the rare case where the inverse of q modulo p
can result in bigint one byte shorter than expected, which could
mess up the export/import of the key.
2007-05-08 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Sync with Mono.Security version - mostly the patch
from Randolph Chung to add DSA CAPI BLOB support.
2007-05-08 Randolph Chung <tausq@debian.org>
* DSAManaged.cs: Do not reject the input if only Y is null.
Fixes #81558. [small edits from Sebastien]
2007-03-22 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Before 2.0 an IndexOutOfRangeException was
thrown (for all unmanaged transforms) in case of an overflow.
2007-03-05 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fix KeepLastBlock to be true for decryption
with no padding or zero padding. Part of the fix for #81008.
2007-01-08 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fix #80439 again. This time we have tests for
all ciphers, modes and padding.
2007-01-04 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fix previous fix (for #80439) as we were now
too permissive.
2007-01-03 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Reduce inputCount if larger than the output
data can hold. Fix bug #80439.
2006-12-11 Sebastien Pouliot <sebastien@ximian.com>
* PKCS8.cs: Synchronize source with Mono.Security.dll
2006-09-27 Sebastien Pouliot <sebastien@ximian.com>
* RSAManaged.cs: Ensure that the results of Encrypt and Decrypt will
always be the same length as the key. If smaller then we left pad the
result with 0x00 (same integer, correct length for everyone). Fix bug
#79502 where an LDAP/SSL server didn't like the missing byte.
2006-09-05 Sebastien Pouliot <sebastien@ximian.com>
* RSAManaged.cs: Fix a NRE when decrypting without a private key
(#79269). We now throw a CryptographicException with an appropriate
text message.
2006-06-15 Sebastien Pouliot <sebastien@ximian.com>
* CryptoTools.cs: Fix offset in block processor. This fix the HMAC
algorithms when large buffer where used (with multiple calls to
TransformBlock).
2005-11-23 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Virtualized some methods (like Dispose). Fix
bug #76801.
2005-11-22 Sebastien Pouliot <sebastien@ximian.com>
* DSAManaged.cs: Don't export J if it wasn't imported (i.e. it was
calculated from the other parameters).
2005-10-21 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Clone IV so it cannot be changed once the
transform starts. Generate a new IV if null is specified (not really
useful but compatible with MS behaviour). Added a check for IV length
on 2.0.
2005-05-26 Ben Maurer <bmaurer@ximian.com>
* KeyPairPersistence.cs: Lock *before* checking if things are null
to prevent race conditions. Also, do not lock on typeof object.
2005-05-09 Sebastien Pouliot <sebastien@ximian.com>
* KeyPairPersistence.cs: Use PlatformID.Unix under NET_2_0.
2005-04-27 Sebastien Pouliot <sebastien@ximian.com>
* PKCS8.cs: New. Copied from Mono.Security.dll to allow support of
PKCS#12 files in X509Certificate for 2.0.
2005-04-18 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fixed a division by zero if someone changes
the feedback value to 0.
2005-03-30 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fixed a padding bug affecting that can occurs
when no padding is used.
2005-01-11 Sebastien Pouliot <sebastien@ximian.com>
* DSAManaged.cs: PublicOnly now reports false when a key hasn't yet
been generated.
* RSAManaged.cs: PublicOnly now reports false when a key hasn't yet
been generated.
2005-01-10 Sebastien Pouliot <sebastien@ximian.com>
* MACAlgorithm.cs: Added support for different padding modes (required
in 2.0).
* SymmetricTransform.cs: Added support for ANSI X9.23 padding and
ISO 10126 padding modes (applies to all symmetric block ciphers).
2004-12-22 Sebastien Pouliot <sebastien@ximian.com>
* KeyPairPersistence.cs: Commented imperative asserts until it is
supported by the runtime.
2004-12-06 Sebastien Pouliot <sebastien@ximian.com>
* RSAManaged.cs: Implement key blinding for RSA decryption with, or
without, using CRT.
2004-11-23 Sebastien Pouliot <sebastien@ximian.com>
* PKCS1.cs: Fix PKCS#1 v1.5 decryption when the ciphertext isn't
exactly the same of the public key (which happens sometimes on Fx 1.1
probably because it doesn't do the last I2OSP operation to left pad
the resulting big integer with zeros).
2004-10-28 Sebastien Pouliot <sebastien@ximian.com>
* KeyPairPersistence.cs: Added localization for exceptions messages.
Also added more details (type and path) when an exception is thrown.
2004-09-29 Sebastien Pouliot <sebastien@ximian.com>
* RSAManaged.cs: KeySize is always a multiple of 8 bits (promotion to
a bigger size if required) to match MS implementation (and other
issues like SSL).
2004-09-16 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Fixed warning (l4) for unused variables.
* KeyPairPersistence.cs: Fixed warning (l4) for unused variable.
* PKCS1.cs: Added empty {} to fix warning about possible empty stmnt.
2004-07-07 Sebastien Pouliot <sebastien@ximian.com>
* MACAlgorithm.cs: Removed the hardcoded PaddingMode.Zeros as this is
now selectable in Fx 2.0.
* SymmetricTransform.cs: Throw CryptographicException when CipherMode
CTS or OFB is being used (to match MS implementation).
2004-06-23 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Reduce by one the number of block when
decrypting. This operation was in CryptoStream before but is only
required for decryption (which CryptoStream can't know).
Fix bug #60573.
2004-05-27 Sebastien Pouliot <sebastien@ximian.com>
* SymmetricTransform.cs: Fixed possible integer overflow. Added
missing exception handling in TransformBlock and TransformFinalBlock.
2004-05-01 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Synched with Mono.Security.dll. Fix bug #57941
(truncated key pair).
* RSAManaged.cs: Synched with Mono.Security.dll. Fix bug #57941
(truncated key pair).
2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: In sync with Mono.Security.dll version.
* CryptoTools.cs: In sync with Mono.Security.dll version.
* DSAManaged.cs: Changed delegate to please FxCop.
* PKCS1.cs: In sync with Mono.Security.dll version.
* RSAManaged.cs: In sync with Mono.Security.dll version.
* SymmetricTransform.cs: Fixed a bug when offset > 0 in destination
buffer. Changed Array.Copy to Buffer.BlockCopy.
2004-04-23 Sebastien Pouliot <sebastien@ximian.com>
* KeyPairPersistence.cs: Completed key pair protection for both
Linux and Windows (protection done by runtime).
2004-04-08 Bernie Solomon <bernard@ugsolutions.com>
* PKCS1.cs: Use BitConverterLE
2004-04-06 Bernie Solomon <bernard@ugsolutions.com>
* CryptoConvert.cs: Add private methods to always
handle data as little endian (GetBytesLE, ToInt32LE, ToUInt32LE).
2004-03-23 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Added support for public keys preceded by an
header like the one generated by "sn -e".
2004-03-23 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Added exception for null and bad parameters.
* RSAManaged.cs: CryptographicException thrown when trying to export
the private key when only the public key is present (CRT aware).
2004-03-22 Sebastien Pouliot <sebastien@ximian.com>
* CryptoConvert.cs: Added new methods to convert [From|To]Hex. Added
new version of FromCapiPublicKeyBlob with an integer offset.
2004-02-06 Sebastien Pouliot <sebastien@ximian.com>
* DSAManaged.cs: Added an event after key generation (so that
DSACryptoServiceProvider can persist the keypair if required). Added
PublicOnly property (like 1.2) so we do not have to catch an exception
to know if a private key is present or not. Added a Random property so
we do not always have to create a RNG instance (not always required).
* RSAManaged.cs: Added an event after key generation (so that
DSACryptoServiceProvider can persist the keypair if required). Added
PublicOnly property (like 1.2) so we do not have to catch an exception
to know if a private key is present or not.
* SymmetricTransform.cs: This class was split from S.S.C.
SymmetricAlgorithm.cs so it could be reused in Mono.Security
assembly for other symmetric algorithms transforms.
2004-02-05 Sebastien Pouliot <sebastien@ximian.com>
* KeyPairPersistence.cs: New. Class to persist keypairs in an XML
format to mimic the CryptoAPI key containers.
2004-01-12 Sebastien Pouliot <spouliot@videotron.ca>
* CryptoConvert.cs: RSA doesn't start with a Q - at least that what
a strongname told me. Sorry Ron :(
2003-12-15 Sebastien Pouliot <spouliot@videotron.ca>
* MACAlgorithm.cs: Fixed difference between 1.0 and 1.1 framework.
The 1.0 framework is adding an additional padding block (empty)
to MAC when MACing an exact multiple of the TripleDES block size.
* PKCS1.cs: Fixed a typo which prevented "lame" (without OID)
signature verification.
2003-10-30 Sebastien Pouliot <spouliot@videotron.ca>
* CryptoConvert.cs: Fixed strongname generation for small exponents
(like 17). Part of the fixed for bug #50341.
2003-10-17 Sebastien Pouliot <spouliot@videotron.ca>
* CryptoConvert.cs: Added from Mono.Security to support StrongNames.
2003-07-05 Sebastien Pouliot <spouliot@videotron.ca>
* DSAManaged.cs: Fixed bugs that appeared with the new unit tests.
* RSAManaged.cs: Fixed bugs that appeared with the new unit tests.
2003-07-02 Zoltan Varga <vargaz@freemail.hu>
* PKCS1.cs DSAManaged.cs: Changed strange characters in comments to
human-readable ones, since they break XML export in monocov.
2003-06-15 Sebastien Pouliot <spouliot@motus.com>
* RSAManaged.cs: Now includes CRT (Chinese Remainder Theorem)
optimization when using the private key (DecryptValue). This
cut more than 5 seconds of nunit on my system (out of 14 sec
for complete asymmetric tests). Thanks to Ben Maurer for help!
2003-06-11 Sebastien Pouliot <spouliot@motus.com>
* DSAManaged.cs: Refactored from DSACryptoServiceProvider.cs. Cannot
be reused outside [ms]corlib because DSA constructor is internal :-(
* PKCS1.cs: Now support any hash algorithm when encoding PKCS 1.5
(i.e. not limited to pre-calculated values for known hashes). Some
other API changes to ease the use of other hash algorithms.
* RSAManaged.cs: Refactored from RSACryptoServiceProvider.cs. This
class is required for custom PKCS#1 padding in SSL (which is not
possible using RSACryptoServiceProvider).
2003-05-12 Sebastien Pouliot <spouliot@videotron.ca>
* PKCS1.cs: Corrected I2OSP to match PKCS#1 v.2.1 test vector
and fix the OAEP incompatibility issue.
2003-04-01 Sebastien Pouliot <spouliot@videotron.ca>
* PKCS1.cs: Corrected fix (partially) for the lame PKCS1 v1.5
signatures done without specifying an OID.
2003-03-01 Sebastien Pouliot <spouliot@videotron.ca>
* PKCS1.cs: Fix for some (lame) PKCS1 v1.5 signatures done
without specifying an OID.
2003-02-08 Sebastien Pouliot <spouliot@videotron.ca>
* CryptoTools.cs: Renamed namespace to match new location.
* PKCS1.cs: Renamed namespace to match new location.
* HMACAlgorithm.cs: New. Generic class to implement HMAC
using any hash algorithm (was in S.S.C.HMACSHA1.cs).
* MACAlgorithm.cs: New. Generic class to implement MAC
using any symmetric algorithm (was in S.S.C.MACTripleDES.cs).

View File

@ -0,0 +1,471 @@
//
// DSAManaged.cs - Implements the DSA algorithm.
//
// Authors:
// Dan Lewis (dihlewis@yahoo.co.uk)
// Sebastien Pouliot (spouliot@motus.com)
// Ben Maurer (bmaurer@users.sf.net)
//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
// Portions (C) 2003 Ben Maurer
//
// Key generation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
// See bouncycastle.txt for license.
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
using Mono.Math;
namespace Mono.Security.Cryptography {
#if INSIDE_CORLIB
internal
#else
public
#endif
class DSAManaged : DSA {
private const int defaultKeySize = 1024;
private bool keypairGenerated = false;
private bool m_disposed = false;
private BigInteger p;
private BigInteger q;
private BigInteger g;
private BigInteger x; // private key
private BigInteger y;
private BigInteger j;
private BigInteger seed;
private int counter;
private bool j_missing;
private RandomNumberGenerator rng;
public DSAManaged () : this (defaultKeySize) {}
public DSAManaged (int dwKeySize)
{
KeySizeValue = dwKeySize;
LegalKeySizesValue = new KeySizes [1];
LegalKeySizesValue [0] = new KeySizes (512, 1024, 64);
}
~DSAManaged ()
{
// Zeroize private key
Dispose (false);
}
// generate both the group and the keypair
private void Generate ()
{
GenerateParams (base.KeySize);
GenerateKeyPair ();
keypairGenerated = true;
if (KeyGenerated != null)
KeyGenerated (this, null);
}
// this part is quite fast
private void GenerateKeyPair ()
{
x = BigInteger.GenerateRandom (160);
while ((x == 0) || (x >= q)) {
// size of x (private key) isn't affected by the keysize (512-1024)
x.Randomize ();
}
// calculate the public key y = g^x % p
y = g.ModPow (x, p);
}
private void add (byte[] a, byte[] b, int value)
{
uint x = (uint) ((b [b.Length - 1] & 0xff) + value);
a [b.Length - 1] = (byte)x;
x >>= 8;
for (int i = b.Length - 2; i >= 0; i--) {
x += (uint) (b [i] & 0xff);
a [i] = (byte)x;
x >>= 8;
}
}
private void GenerateParams (int keyLength)
{
byte[] seed = new byte[20];
byte[] part1 = new byte[20];
byte[] part2 = new byte[20];
byte[] u = new byte[20];
// TODO: a prime generator should be made for this
SHA1 sha = SHA1.Create ();
int n = (keyLength - 1) / 160;
byte[] w = new byte [keyLength / 8];
bool primesFound = false;
while (!primesFound) {
do {
Random.GetBytes (seed);
part1 = sha.ComputeHash (seed);
Array.Copy(seed, 0, part2, 0, seed.Length);
add (part2, seed, 1);
part2 = sha.ComputeHash (part2);
for (int i = 0; i != u.Length; i++)
u [i] = (byte)(part1 [i] ^ part2 [i]);
// first bit must be set (to respect key length)
u[0] |= (byte)0x80;
// last bit must be set (prime are all odds - except 2)
u[19] |= (byte)0x01;
q = new BigInteger (u);
}
while (!q.IsProbablePrime ());
counter = 0;
int offset = 2;
while (counter < 4096) {
for (int k = 0; k < n; k++) {
add(part1, seed, offset + k);
part1 = sha.ComputeHash (part1);
Array.Copy (part1, 0, w, w.Length - (k + 1) * part1.Length, part1.Length);
}
add(part1, seed, offset + n);
part1 = sha.ComputeHash (part1);
Array.Copy (part1, part1.Length - ((w.Length - (n) * part1.Length)), w, 0, w.Length - n * part1.Length);
w[0] |= (byte)0x80;
BigInteger x = new BigInteger (w);
BigInteger c = x % (q * 2);
p = x - (c - 1);
if (p.TestBit ((uint)(keyLength - 1))) {
if (p.IsProbablePrime ()) {
primesFound = true;
break;
}
}
counter += 1;
offset += n + 1;
}
}
// calculate the generator g
BigInteger pMinusOneOverQ = (p - 1) / q;
for (;;) {
BigInteger h = BigInteger.GenerateRandom (keyLength);
if ((h <= 1) || (h >= (p - 1)))
continue;
g = h.ModPow (pMinusOneOverQ, p);
if (g <= 1)
continue;
break;
}
this.seed = new BigInteger (seed);
j = (p - 1) / q;
}
private RandomNumberGenerator Random {
get {
if (rng == null)
rng = RandomNumberGenerator.Create ();
return rng;
}
}
// overrides from DSA class
public override int KeySize {
get {
// in case keypair hasn't been (yet) generated
if (keypairGenerated)
return p.BitCount ();
else
return base.KeySize;
}
}
public override string KeyExchangeAlgorithm {
get { return null; }
}
// note: when (if) we generate a keypair then it will have both
// the public and private keys
public bool PublicOnly {
get { return ((keypairGenerated) && (x == null)); }
}
public override string SignatureAlgorithm {
get { return "http://www.w3.org/2000/09/xmldsig#dsa-sha1"; }
}
private byte[] NormalizeArray (byte[] array)
{
int n = (array.Length % 4);
if (n > 0) {
byte[] temp = new byte [array.Length + 4 - n];
Array.Copy (array, 0, temp, (4 - n), array.Length);
return temp;
}
else
return array;
}
public override DSAParameters ExportParameters (bool includePrivateParameters)
{
if (m_disposed)
throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
if (!keypairGenerated)
Generate ();
if ((includePrivateParameters) && (x == null))
throw new CryptographicException ("no private key to export");
DSAParameters param = new DSAParameters ();
// all parameters must be in multiple of 4 bytes arrays
// this isn't (generally) a problem for most of the parameters
// except for J (but we won't take a chance)
param.P = NormalizeArray (p.GetBytes ());
param.Q = NormalizeArray (q.GetBytes ());
param.G = NormalizeArray (g.GetBytes ());
param.Y = NormalizeArray (y.GetBytes ());
if (!j_missing) {
param.J = NormalizeArray (j.GetBytes ());
}
if (seed != 0) {
param.Seed = NormalizeArray (seed.GetBytes ());
param.Counter = counter;
}
if (includePrivateParameters) {
byte[] privateKey = x.GetBytes ();
if (privateKey.Length == 20) {
param.X = NormalizeArray (privateKey);
}
}
return param;
}
public override void ImportParameters (DSAParameters parameters)
{
if (m_disposed)
throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
// if missing "mandatory" parameters
if ((parameters.P == null) || (parameters.Q == null) || (parameters.G == null))
throw new CryptographicException (Locale.GetText ("Missing mandatory DSA parameters (P, Q or G)."));
// We can calculate Y from X, but both can't be missing
if ((parameters.X == null) && (parameters.Y == null))
throw new CryptographicException (Locale.GetText ("Missing both public (Y) and private (X) keys."));
p = new BigInteger (parameters.P);
q = new BigInteger (parameters.Q);
g = new BigInteger (parameters.G);
// optional parameter - private key
if (parameters.X != null)
x = new BigInteger (parameters.X);
else
x = null;
// we can calculate Y from X if required
if (parameters.Y != null)
y = new BigInteger (parameters.Y);
else
y = g.ModPow (x, p);
// optional parameter - pre-computation
if (parameters.J != null) {
j = new BigInteger (parameters.J);
} else {
j = (p - 1) / q;
j_missing = true;
}
// optional - seed and counter must both be present (or absent)
if (parameters.Seed != null) {
seed = new BigInteger (parameters.Seed);
counter = parameters.Counter;
}
else
seed = 0;
// we now have a keypair
keypairGenerated = true;
}
public override byte[] CreateSignature (byte[] rgbHash)
{
if (m_disposed)
throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
if (rgbHash == null)
throw new ArgumentNullException ("rgbHash");
if (rgbHash.Length != 20)
throw new CryptographicException ("invalid hash length");
if (!keypairGenerated)
Generate ();
// if required key must be generated before checking for X
if (x == null)
throw new CryptographicException ("no private key available for signature");
BigInteger m = new BigInteger (rgbHash);
// (a) Select a random secret integer k; 0 < k < q.
BigInteger k = BigInteger.GenerateRandom (160);
while (k >= q)
k.Randomize ();
// (b) Compute r = (g^k mod p) mod q
BigInteger r = (g.ModPow (k, p)) % q;
// (c) Compute k -1 mod q (e.g., using Algorithm 2.142).
// (d) Compute s = k -1 fh(m) +arg mod q.
BigInteger s = (k.ModInverse (q) * (m + x * r)) % q;
// (e) A's signature for m is the pair (r; s).
byte[] signature = new byte [40];
byte[] part1 = r.GetBytes ();
byte[] part2 = s.GetBytes ();
// note: sometime (1/256) we may get less than 20 bytes (if first is 00)
int start = 20 - part1.Length;
Array.Copy (part1, 0, signature, start, part1.Length);
start = 40 - part2.Length;
Array.Copy (part2, 0, signature, start, part2.Length);
return signature;
}
public override bool VerifySignature (byte[] rgbHash, byte[] rgbSignature)
{
if (m_disposed)
throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
if (rgbHash == null)
throw new ArgumentNullException ("rgbHash");
if (rgbSignature == null)
throw new ArgumentNullException ("rgbSignature");
if (rgbHash.Length != 20)
throw new CryptographicException ("invalid hash length");
// signature is always 40 bytes (no matter the size of the
// public key). In fact it is 2 times the size of the private
// key (which is 20 bytes for 512 to 1024 bits DSA keypairs)
if (rgbSignature.Length != 40)
throw new CryptographicException ("invalid signature length");
// it would be stupid to verify a signature with a newly
// generated keypair - so we return false
if (!keypairGenerated)
return false;
try {
BigInteger m = new BigInteger (rgbHash);
byte[] half = new byte [20];
Array.Copy (rgbSignature, 0, half, 0, 20);
BigInteger r = new BigInteger (half);
Array.Copy (rgbSignature, 20, half, 0, 20);
BigInteger s = new BigInteger (half);
if ((r < 0) || (q <= r))
return false;
if ((s < 0) || (q <= s))
return false;
BigInteger w = s.ModInverse(q);
BigInteger u1 = m * w % q;
BigInteger u2 = r * w % q;
u1 = g.ModPow(u1, p);
u2 = y.ModPow(u2, p);
BigInteger v = ((u1 * u2 % p) % q);
return (v == r);
}
catch {
throw new CryptographicException ("couldn't compute signature verification");
}
}
protected override void Dispose (bool disposing)
{
if (!m_disposed) {
// Always zeroize private key
if (x != null) {
x.Clear ();
x = null;
}
if (disposing) {
// clear group
if (p != null) {
p.Clear ();
p = null;
}
if (q != null) {
q.Clear ();
q = null;
}
if (g != null) {
g.Clear ();
g = null;
}
if (j != null) {
j.Clear ();
j = null;
}
if (seed != null) {
seed.Clear ();
seed = null;
}
// clear public key
if (y != null) {
y.Clear ();
y = null;
}
}
}
// call base class
// no need as they all are abstract before us
m_disposed = true;
}
public delegate void KeyGeneratedEventHandler (object sender, EventArgs e);
public event KeyGeneratedEventHandler KeyGenerated;
}
}

View File

@ -0,0 +1,149 @@
//
// HMACAlgorithm.cs: Handles HMAC with any hash algorithm
//
// Author:
// Sebastien Pouliot (spouliot@motus.com)
//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
//
//
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
namespace Mono.Security.Cryptography {
// References:
// a. FIPS PUB 198: The Keyed-Hash Message Authentication Code (HMAC), 2002 March.
// http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf
// b. Internet RFC 2104, HMAC, Keyed-Hashing for Message Authentication
// (include C source for HMAC-MD5)
// http://www.ietf.org/rfc/rfc2104.txt
// c. IETF RFC2202: Test Cases for HMAC-MD5 and HMAC-SHA-1
// (include C source for HMAC-MD5 and HAMAC-SHA1)
// http://www.ietf.org/rfc/rfc2202.txt
// d. ANSI X9.71, Keyed Hash Message Authentication Code.
// not free :-(
// http://webstore.ansi.org/ansidocstore/product.asp?sku=ANSI+X9%2E71%2D2000
// Generic HMAC mechanisms - most of HMAC work is done in here.
// It should work with any hash function e.g. MD5 for HMACMD5 (RFC2104)
internal class HMACAlgorithm {
private byte[] key;
private byte[] hash;
private HashAlgorithm algo;
private string hashName;
private BlockProcessor block;
public HMACAlgorithm (string algoName)
{
CreateHash (algoName);
}
~HMACAlgorithm ()
{
Dispose ();
}
private void CreateHash (string algoName)
{
algo = HashAlgorithm.Create (algoName);
hashName = algoName;
block = new BlockProcessor (algo, 8);
}
public void Dispose ()
{
if (key != null)
Array.Clear (key, 0, key.Length);
}
public HashAlgorithm Algo {
get { return algo; }
}
public string HashName {
get { return hashName; }
set { CreateHash (value); }
}
public byte[] Key {
get { return key; }
set {
if ((value != null) && (value.Length > 64))
key = algo.ComputeHash (value);
else
key = (byte[]) value.Clone();
}
}
public void Initialize ()
{
hash = null;
block.Initialize ();
byte[] buf = KeySetup (key, 0x36);
algo.Initialize ();
block.Core (buf);
// zeroize key
Array.Clear (buf, 0, buf.Length);
}
private byte[] KeySetup (byte[] key, byte padding)
{
byte[] buf = new byte [64];
for (int i = 0; i < key.Length; ++i)
buf [i] = (byte) ((byte) key [i] ^ padding);
for (int i = key.Length; i < 64; ++i)
buf [i] = padding;
return buf;
}
public void Core (byte[] rgb, int ib, int cb)
{
block.Core (rgb, ib, cb);
}
public byte[] Final ()
{
block.Final ();
byte[] intermediate = algo.Hash;
byte[] buf = KeySetup (key, 0x5C);
algo.Initialize ();
algo.TransformBlock (buf, 0, buf.Length, buf, 0);
algo.TransformFinalBlock (intermediate, 0, intermediate.Length);
hash = algo.Hash;
algo.Clear ();
// zeroize sensitive data
Array.Clear (buf, 0, buf.Length);
Array.Clear (intermediate, 0, intermediate.Length);
return hash;
}
}
}

View File

@ -0,0 +1,111 @@
//
// MACAlgorithm.cs: Handles MAC with any symmetric algorithm
//
// Author:
// Sebastien Pouliot (spouliot@motus.com)
//
// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System;
using System.Security.Cryptography;
namespace Mono.Security.Cryptography {
// References:
// a. FIPS PUB 81: DES MODES OF OPERATION
// MAC: Appendix F (MACDES not MACTripleDES but close enough ;-)
// http://www.itl.nist.gov/fipspubs/fip81.htm
// Generic MAC mechanims - most of the work is done in here
// It should work with any symmetric algorithm function e.g. DES for MACDES (fips81)
internal class MACAlgorithm {
private SymmetricAlgorithm algo;
private ICryptoTransform enc;
private byte[] block;
private int blockSize;
private int blockCount;
public MACAlgorithm (SymmetricAlgorithm algorithm)
{
algo = (SymmetricAlgorithm) algorithm;
algo.Mode = CipherMode.CBC;
blockSize = (algo.BlockSize >> 3); // in bytes
algo.IV = new byte [blockSize];
block = new byte [blockSize];
}
public void Initialize (byte[] key)
{
algo.Key = key;
// note: the encryptor transform may be reusable - see Final
if (enc == null) {
enc = algo.CreateEncryptor ();
}
Array.Clear (block, 0, blockSize);
blockCount = 0;
}
public void Core (byte[] rgb, int ib, int cb)
{
// 1. fill the rest of the "block"
int n = System.Math.Min (blockSize - blockCount, cb);
Array.Copy (rgb, ib, block, blockCount, n);
blockCount += n;
// 2. if block is full then transform it
if (blockCount == blockSize) {
enc.TransformBlock (block, 0, blockSize, block, 0);
// 3. transform any other full block in specified buffer
int b = (int) ((cb - n) / blockSize);
for (int i=0; i < b; i++) {
enc.TransformBlock (rgb, n, blockSize, block, 0);
n += blockSize;
}
// 4. if data is still present fill the "block" with the remainder
blockCount = cb - n;
if (blockCount > 0)
Array.Copy (rgb, n, block, 0, blockCount);
}
}
public byte[] Final ()
{
byte[] result;
if ((blockCount > 0) || ((algo.Padding != PaddingMode.Zeros) && (algo.Padding != PaddingMode.None))) {
result = enc.TransformFinalBlock (block, 0, blockCount);
} else {
result = (byte[]) block.Clone ();
}
if (!enc.CanReuseTransform) {
enc.Dispose ();
enc = null;
}
return result;
}
}
}