using System; using System.Security.Cryptography; using Mono.Math; namespace Mono.Security.Cryptography { // Token: 0x020000A4 RID: 164 internal class DSAManaged : DSA { // Token: 0x060008F2 RID: 2290 RVA: 0x0002324C File Offset: 0x0002144C public DSAManaged() : this(1024) { } // Token: 0x060008F3 RID: 2291 RVA: 0x0002325C File Offset: 0x0002145C public DSAManaged(int dwKeySize) { this.KeySizeValue = dwKeySize; this.LegalKeySizesValue = new KeySizes[1]; this.LegalKeySizesValue[0] = new KeySizes(512, 1024, 64); } // Token: 0x14000001 RID: 1 // (add) Token: 0x060008F4 RID: 2292 RVA: 0x0002329C File Offset: 0x0002149C // (remove) Token: 0x060008F5 RID: 2293 RVA: 0x000232B8 File Offset: 0x000214B8 public event DSAManaged.KeyGeneratedEventHandler KeyGenerated; // Token: 0x060008F6 RID: 2294 RVA: 0x000232D4 File Offset: 0x000214D4 ~DSAManaged() { this.Dispose(false); } // Token: 0x060008F7 RID: 2295 RVA: 0x00023310 File Offset: 0x00021510 private void Generate() { this.GenerateParams(base.KeySize); this.GenerateKeyPair(); this.keypairGenerated = true; if (this.KeyGenerated != null) { this.KeyGenerated(this, null); } } // Token: 0x060008F8 RID: 2296 RVA: 0x00023350 File Offset: 0x00021550 private void GenerateKeyPair() { this.x = BigInteger.GenerateRandom(160); while (this.x == 0U || this.x >= this.q) { this.x.Randomize(); } this.y = this.g.ModPow(this.x, this.p); } // Token: 0x060008F9 RID: 2297 RVA: 0x000233C4 File Offset: 0x000215C4 private void add(byte[] a, byte[] b, int value) { uint num = (uint)((int)(b[b.Length - 1] & byte.MaxValue) + value); a[b.Length - 1] = (byte)num; num >>= 8; for (int i = b.Length - 2; i >= 0; i--) { num += (uint)(b[i] & byte.MaxValue); a[i] = (byte)num; num >>= 8; } } // Token: 0x060008FA RID: 2298 RVA: 0x0002341C File Offset: 0x0002161C private void GenerateParams(int keyLength) { byte[] array = new byte[20]; byte[] array2 = new byte[20]; byte[] array3 = new byte[20]; byte[] array4 = new byte[20]; SHA1 sha = SHA1.Create(); int num = (keyLength - 1) / 160; byte[] array5 = new byte[keyLength / 8]; bool flag = false; while (!flag) { do { this.Random.GetBytes(array); array2 = sha.ComputeHash(array); Array.Copy(array, 0, array3, 0, array.Length); this.add(array3, array, 1); array3 = sha.ComputeHash(array3); for (int num2 = 0; num2 != array4.Length; num2++) { array4[num2] = array2[num2] ^ array3[num2]; } byte[] array6 = array4; int num3 = 0; array6[num3] |= 128; byte[] array7 = array4; int num4 = 19; array7[num4] |= 1; this.q = new BigInteger(array4); } while (!this.q.IsProbablePrime()); this.counter = 0; int num5 = 2; while (this.counter < 4096) { for (int i = 0; i < num; i++) { this.add(array2, array, num5 + i); array2 = sha.ComputeHash(array2); Array.Copy(array2, 0, array5, array5.Length - (i + 1) * array2.Length, array2.Length); } this.add(array2, array, num5 + num); array2 = sha.ComputeHash(array2); Array.Copy(array2, array2.Length - (array5.Length - num * array2.Length), array5, 0, array5.Length - num * array2.Length); byte[] array8 = array5; int num6 = 0; array8[num6] |= 128; BigInteger bigInteger = new BigInteger(array5); BigInteger bigInteger2 = bigInteger % (this.q * 2); this.p = bigInteger - (bigInteger2 - 1); if (this.p.TestBit((uint)(keyLength - 1)) && this.p.IsProbablePrime()) { flag = true; break; } this.counter++; num5 += num + 1; } } BigInteger bigInteger3 = (this.p - 1) / this.q; for (;;) { BigInteger bigInteger4 = BigInteger.GenerateRandom(keyLength); if (!(bigInteger4 <= 1) && !(bigInteger4 >= this.p - 1)) { this.g = bigInteger4.ModPow(bigInteger3, this.p); if (!(this.g <= 1)) { break; } } } this.seed = new BigInteger(array); this.j = (this.p - 1) / this.q; } // Token: 0x170000F2 RID: 242 // (get) Token: 0x060008FB RID: 2299 RVA: 0x000236FC File Offset: 0x000218FC private RandomNumberGenerator Random { get { if (this.rng == null) { this.rng = RandomNumberGenerator.Create(); } return this.rng; } } // Token: 0x170000F3 RID: 243 // (get) Token: 0x060008FC RID: 2300 RVA: 0x0002371C File Offset: 0x0002191C public override int KeySize { get { if (this.keypairGenerated) { return this.p.BitCount(); } return base.KeySize; } } // Token: 0x170000F4 RID: 244 // (get) Token: 0x060008FD RID: 2301 RVA: 0x0002373C File Offset: 0x0002193C public override string KeyExchangeAlgorithm { get { return null; } } // Token: 0x170000F5 RID: 245 // (get) Token: 0x060008FE RID: 2302 RVA: 0x00023740 File Offset: 0x00021940 public bool PublicOnly { get { return this.keypairGenerated && this.x == null; } } // Token: 0x170000F6 RID: 246 // (get) Token: 0x060008FF RID: 2303 RVA: 0x0002375C File Offset: 0x0002195C public override string SignatureAlgorithm { get { return "http://www.w3.org/2000/09/xmldsig#dsa-sha1"; } } // Token: 0x06000900 RID: 2304 RVA: 0x00023764 File Offset: 0x00021964 private byte[] NormalizeArray(byte[] array) { int num = array.Length % 4; if (num > 0) { byte[] array2 = new byte[array.Length + 4 - num]; Array.Copy(array, 0, array2, 4 - num, array.Length); return array2; } return array; } // Token: 0x06000901 RID: 2305 RVA: 0x0002379C File Offset: 0x0002199C public override DSAParameters ExportParameters(bool includePrivateParameters) { if (this.m_disposed) { throw new ObjectDisposedException(Locale.GetText("Keypair was disposed")); } if (!this.keypairGenerated) { this.Generate(); } if (includePrivateParameters && this.x == null) { throw new CryptographicException("no private key to export"); } DSAParameters dsaparameters = default(DSAParameters); dsaparameters.P = this.NormalizeArray(this.p.GetBytes()); dsaparameters.Q = this.NormalizeArray(this.q.GetBytes()); dsaparameters.G = this.NormalizeArray(this.g.GetBytes()); dsaparameters.Y = this.NormalizeArray(this.y.GetBytes()); if (!this.j_missing) { dsaparameters.J = this.NormalizeArray(this.j.GetBytes()); } if (this.seed != 0U) { dsaparameters.Seed = this.NormalizeArray(this.seed.GetBytes()); dsaparameters.Counter = this.counter; } if (includePrivateParameters) { byte[] bytes = this.x.GetBytes(); if (bytes.Length == 20) { dsaparameters.X = this.NormalizeArray(bytes); } } return dsaparameters; } // Token: 0x06000902 RID: 2306 RVA: 0x000238E4 File Offset: 0x00021AE4 public override void ImportParameters(DSAParameters parameters) { if (this.m_disposed) { throw new ObjectDisposedException(Locale.GetText("Keypair was disposed")); } if (parameters.P == null || parameters.Q == null || parameters.G == null) { throw new CryptographicException(Locale.GetText("Missing mandatory DSA parameters (P, Q or G).")); } if (parameters.X == null && parameters.Y == null) { throw new CryptographicException(Locale.GetText("Missing both public (Y) and private (X) keys.")); } this.p = new BigInteger(parameters.P); this.q = new BigInteger(parameters.Q); this.g = new BigInteger(parameters.G); if (parameters.X != null) { this.x = new BigInteger(parameters.X); } else { this.x = null; } if (parameters.Y != null) { this.y = new BigInteger(parameters.Y); } else { this.y = this.g.ModPow(this.x, this.p); } if (parameters.J != null) { this.j = new BigInteger(parameters.J); } else { this.j = (this.p - 1) / this.q; this.j_missing = true; } if (parameters.Seed != null) { this.seed = new BigInteger(parameters.Seed); this.counter = parameters.Counter; } else { this.seed = 0; } this.keypairGenerated = true; } // Token: 0x06000903 RID: 2307 RVA: 0x00023A98 File Offset: 0x00021C98 public override byte[] CreateSignature(byte[] rgbHash) { if (this.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 (!this.keypairGenerated) { this.Generate(); } if (this.x == null) { throw new CryptographicException("no private key available for signature"); } BigInteger bigInteger = new BigInteger(rgbHash); BigInteger bigInteger2 = BigInteger.GenerateRandom(160); while (bigInteger2 >= this.q) { bigInteger2.Randomize(); } BigInteger bigInteger3 = this.g.ModPow(bigInteger2, this.p) % this.q; BigInteger bigInteger4 = bigInteger2.ModInverse(this.q) * (bigInteger + this.x * bigInteger3) % this.q; byte[] array = new byte[40]; byte[] bytes = bigInteger3.GetBytes(); byte[] bytes2 = bigInteger4.GetBytes(); int num = 20 - bytes.Length; Array.Copy(bytes, 0, array, num, bytes.Length); num = 40 - bytes2.Length; Array.Copy(bytes2, 0, array, num, bytes2.Length); return array; } // Token: 0x06000904 RID: 2308 RVA: 0x00023BDC File Offset: 0x00021DDC public override bool VerifySignature(byte[] rgbHash, byte[] rgbSignature) { if (this.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"); } if (rgbSignature.Length != 40) { throw new CryptographicException("invalid signature length"); } if (!this.keypairGenerated) { return false; } bool flag; try { BigInteger bigInteger = new BigInteger(rgbHash); byte[] array = new byte[20]; Array.Copy(rgbSignature, 0, array, 0, 20); BigInteger bigInteger2 = new BigInteger(array); Array.Copy(rgbSignature, 20, array, 0, 20); BigInteger bigInteger3 = new BigInteger(array); if (bigInteger2 < 0 || this.q <= bigInteger2) { flag = false; } else if (bigInteger3 < 0 || this.q <= bigInteger3) { flag = false; } else { BigInteger bigInteger4 = bigInteger3.ModInverse(this.q); BigInteger bigInteger5 = bigInteger * bigInteger4 % this.q; BigInteger bigInteger6 = bigInteger2 * bigInteger4 % this.q; bigInteger5 = this.g.ModPow(bigInteger5, this.p); bigInteger6 = this.y.ModPow(bigInteger6, this.p); BigInteger bigInteger7 = bigInteger5 * bigInteger6 % this.p % this.q; flag = bigInteger7 == bigInteger2; } } catch { throw new CryptographicException("couldn't compute signature verification"); } return flag; } // Token: 0x06000905 RID: 2309 RVA: 0x00023DAC File Offset: 0x00021FAC protected override void Dispose(bool disposing) { if (!this.m_disposed) { if (this.x != null) { this.x.Clear(); this.x = null; } if (disposing) { if (this.p != null) { this.p.Clear(); this.p = null; } if (this.q != null) { this.q.Clear(); this.q = null; } if (this.g != null) { this.g.Clear(); this.g = null; } if (this.j != null) { this.j.Clear(); this.j = null; } if (this.seed != null) { this.seed.Clear(); this.seed = null; } if (this.y != null) { this.y.Clear(); this.y = null; } } } this.m_disposed = true; } // Token: 0x040001DF RID: 479 private const int defaultKeySize = 1024; // Token: 0x040001E0 RID: 480 private bool keypairGenerated; // Token: 0x040001E1 RID: 481 private bool m_disposed; // Token: 0x040001E2 RID: 482 private BigInteger p; // Token: 0x040001E3 RID: 483 private BigInteger q; // Token: 0x040001E4 RID: 484 private BigInteger g; // Token: 0x040001E5 RID: 485 private BigInteger x; // Token: 0x040001E6 RID: 486 private BigInteger y; // Token: 0x040001E7 RID: 487 private BigInteger j; // Token: 0x040001E8 RID: 488 private BigInteger seed; // Token: 0x040001E9 RID: 489 private int counter; // Token: 0x040001EA RID: 490 private bool j_missing; // Token: 0x040001EB RID: 491 private RandomNumberGenerator rng; // Token: 0x020006C4 RID: 1732 // (Invoke) Token: 0x06004198 RID: 16792 public delegate void KeyGeneratedEventHandler(object sender, EventArgs e); } }