+++ /dev/null
-2007-09-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * NextPrimeFinder.cs, PrimeGeneratorBase.cs: Updated to match
- Mono.Security sources.
-
-2004-09-16 Sebastien Pouliot <sebastien@ximian.com>
-
- * SequentialSearchPrimeGeneratorBase.cs: Fixed warning (l4) for unused
- variables.
-
-2004-05-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * SequentialSearchPrimeGeneratorBase.cs: In sync with
- Mono.Security.dll version.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * NextPrimeFinder.cs: In sync with Mono.Security.dll version.
- * PrimeGeneratorBase.cs: In sync with Mono.Security.dll version.
- * SequentialSearchPrimeGeneratorBase.cs: In sync with
- Mono.Security.dll version.
-
-2004-02-13 Sebastien Pouliot <sebastien@ximian.com>
-
- * PrimeGeneratorBase.cs: Changed primality test to Rabin Miller to
- fix issues #51229 (bug), #54262 (very long in same cases).
-
-2003-04-22 Sebastien Pouliot <spouliot@videotron.ca>
-
- * NextPrimeFinder.cs: New. Prime Generator.
- Support class for BigInteger (commited for Ben Maurer).
- * PrimeGeneratorBase.cs: New. Abstract Prime Generator.
- Support class for BigInteger (commited for Ben Maurer).
- * SequentialSearchPrimeGeneratorBase.cs: New. Prime Generator.
- Support class for BigInteger (commited for Ben Maurer).
+++ /dev/null
-//
-// Mono.Math.Prime.Generator.NextPrimeFinder.cs - Prime Generator
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// 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;
-
-namespace Mono.Math.Prime.Generator {
-
- /// <summary>
- /// Finds the next prime after a given number.
- /// </summary>
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class NextPrimeFinder : SequentialSearchPrimeGeneratorBase {
-
- protected override BigInteger GenerateSearchBase (int bits, object Context)
- {
- if (Context == null)
- throw new ArgumentNullException ("Context");
-
- BigInteger ret = new BigInteger ((BigInteger)Context);
- ret.SetBit (0);
- return ret;
- }
- }
-}
+++ /dev/null
-//
-// Mono.Math.Prime.Generator.PrimeGeneratorBase.cs - Abstract Prime Generator
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// 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;
-
-namespace Mono.Math.Prime.Generator {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- abstract class PrimeGeneratorBase {
-
- public virtual ConfidenceFactor Confidence {
- get {
-#if DEBUG
- return ConfidenceFactor.ExtraLow;
-#else
- return ConfidenceFactor.Medium;
-#endif
- }
- }
-
- public virtual Prime.PrimalityTest PrimalityTest {
- get {
- return new Prime.PrimalityTest (PrimalityTests.RabinMillerTest);
- }
- }
-
- public virtual int TrialDivisionBounds {
- get { return 4000; }
- }
-
- /// <summary>
- /// Performs primality tests on bi, assumes trial division has been done.
- /// </summary>
- /// <param name="bi">A BigInteger that has been subjected to and passed trial division</param>
- /// <returns>False if bi is composite, true if it may be prime.</returns>
- /// <remarks>The speed of this method is dependent on Confidence</remarks>
- protected bool PostTrialDivisionTests (BigInteger bi)
- {
- return PrimalityTest (bi, this.Confidence);
- }
-
- public abstract BigInteger GenerateNewPrime (int bits);
- }
-}
+++ /dev/null
-//
-// Mono.Math.Prime.Generator.SequentialSearchPrimeGeneratorBase.cs - Prime Generator
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-// 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.
-//
-
-namespace Mono.Math.Prime.Generator {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class SequentialSearchPrimeGeneratorBase : PrimeGeneratorBase {
-
- protected virtual BigInteger GenerateSearchBase (int bits, object context)
- {
- BigInteger ret = BigInteger.GenerateRandom (bits);
- ret.SetBit (0);
- return ret;
- }
-
-
- public override BigInteger GenerateNewPrime (int bits)
- {
- return GenerateNewPrime (bits, null);
- }
-
-
- public virtual BigInteger GenerateNewPrime (int bits, object context)
- {
- //
- // STEP 1. Find a place to do a sequential search
- //
- BigInteger curVal = GenerateSearchBase (bits, context);
-
- const uint primeProd1 = 3u* 5u * 7u * 11u * 13u * 17u * 19u * 23u * 29u;
-
- uint pMod1 = curVal % primeProd1;
-
- int DivisionBound = TrialDivisionBounds;
- uint[] SmallPrimes = BigInteger.smallPrimes;
- //
- // STEP 2. Search for primes
- //
- while (true) {
-
- //
- // STEP 2.1 Sieve out numbers divisible by the first 9 primes
- //
- if (pMod1 % 3 == 0) goto biNotPrime;
- if (pMod1 % 5 == 0) goto biNotPrime;
- if (pMod1 % 7 == 0) goto biNotPrime;
- if (pMod1 % 11 == 0) goto biNotPrime;
- if (pMod1 % 13 == 0) goto biNotPrime;
- if (pMod1 % 17 == 0) goto biNotPrime;
- if (pMod1 % 19 == 0) goto biNotPrime;
- if (pMod1 % 23 == 0) goto biNotPrime;
- if (pMod1 % 29 == 0) goto biNotPrime;
-
- //
- // STEP 2.2 Sieve out all numbers divisible by the primes <= DivisionBound
- //
- for (int p = 10; p < SmallPrimes.Length && SmallPrimes [p] <= DivisionBound; p++) {
- if (curVal % SmallPrimes [p] == 0)
- goto biNotPrime;
- }
-
- //
- // STEP 2.3 Is the potential prime acceptable?
- //
- if (!IsPrimeAcceptable (curVal, context))
- goto biNotPrime;
-
- //
- // STEP 2.4 Filter out all primes that pass this step with a primality test
- //
- if (PrimalityTest (curVal, Confidence))
- return curVal;
-
- //
- // STEP 2.4
- //
- biNotPrime:
- pMod1 += 2;
- if (pMod1 >= primeProd1)
- pMod1 -= primeProd1;
- curVal.Incr2 ();
- }
- }
-
- protected virtual bool IsPrimeAcceptable (BigInteger bi, object context)
- {
- return true;
- }
- }
-}
+++ /dev/null
-2007-09-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * ConfidenceFactor.cs, PrimalityTests.cs: Updated to match
- Mono.Security sources.
-
-2004-05-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * PrimalityTests.cs: In sync with Mono.Security.dll version.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * PrimalityTests.cs: In sync with Mono.Security.dll version.
-
-2003-04-23 Alp Toker <alp@atoker.com>
-
- * PrimalityTests.cs: Mark PrimalityTest as non-CLS-compliant (build fix)
-
-2003-04-22 Sebastien Pouliot <spouliot@videotron.ca>
-
- * ConfidenceFactor.cs: New. Enum for prime quality.
- Support for BigInteger (commited for Ben Maurer).
- * PrimalityTests.cs: New. Tests for primality.
- Support for BigInteger (commited for Ben Maurer).
-
+++ /dev/null
-//
-// Mono.Math.Prime.ConfidenceFactor.cs - Confidence factor for prime generation
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// 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;
-
-namespace Mono.Math.Prime {
- /// <summary>
- /// A factor of confidence.
- /// </summary>
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- enum ConfidenceFactor {
- /// <summary>
- /// Only suitable for development use, probability of failure may be greater than 1/2^20.
- /// </summary>
- ExtraLow,
- /// <summary>
- /// Suitable only for transactions which do not require forward secrecy. Probability of failure about 1/2^40
- /// </summary>
- Low,
- /// <summary>
- /// Designed for production use. Probability of failure about 1/2^80.
- /// </summary>
- Medium,
- /// <summary>
- /// Suitable for sensitive data. Probability of failure about 1/2^160.
- /// </summary>
- High,
- /// <summary>
- /// Use only if you have lots of time! Probability of failure about 1/2^320.
- /// </summary>
- ExtraHigh,
- /// <summary>
- /// Only use methods which generate provable primes. Not yet implemented.
- /// </summary>
- Provable
- }
-}
+++ /dev/null
-//
-// Mono.Math.Prime.PrimalityTests.cs - Test for primality
-//
-// Authors:
-// Ben Maurer
-//
-// Copyright (c) 2003 Ben Maurer. All rights reserved
-//
-
-//
-// 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;
-
-namespace Mono.Math.Prime {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- delegate bool PrimalityTest (BigInteger bi, ConfidenceFactor confidence);
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class PrimalityTests {
-
- private PrimalityTests ()
- {
- }
-
- #region SPP Test
-
- private static int GetSPPRounds (BigInteger bi, ConfidenceFactor confidence)
- {
- int bc = bi.BitCount();
-
- int Rounds;
-
- // Data from HAC, 4.49
- if (bc <= 100 ) Rounds = 27;
- else if (bc <= 150 ) Rounds = 18;
- else if (bc <= 200 ) Rounds = 15;
- else if (bc <= 250 ) Rounds = 12;
- else if (bc <= 300 ) Rounds = 9;
- else if (bc <= 350 ) Rounds = 8;
- else if (bc <= 400 ) Rounds = 7;
- else if (bc <= 500 ) Rounds = 6;
- else if (bc <= 600 ) Rounds = 5;
- else if (bc <= 800 ) Rounds = 4;
- else if (bc <= 1250) Rounds = 3;
- else Rounds = 2;
-
- switch (confidence) {
- case ConfidenceFactor.ExtraLow:
- Rounds >>= 2;
- return Rounds != 0 ? Rounds : 1;
- case ConfidenceFactor.Low:
- Rounds >>= 1;
- return Rounds != 0 ? Rounds : 1;
- case ConfidenceFactor.Medium:
- return Rounds;
- case ConfidenceFactor.High:
- return Rounds << 1;
- case ConfidenceFactor.ExtraHigh:
- return Rounds << 2;
- case ConfidenceFactor.Provable:
- throw new Exception ("The Rabin-Miller test can not be executed in a way such that its results are provable");
- default:
- throw new ArgumentOutOfRangeException ("confidence");
- }
- }
-
- public static bool Test (BigInteger n, ConfidenceFactor confidence)
- {
- // Rabin-Miller fails with smaller primes (at least with our BigInteger code)
- if (n.BitCount () < 33)
- return SmallPrimeSppTest (n, confidence);
- else
- return RabinMillerTest (n, confidence);
- }
-
- /// <summary>
- /// Probabilistic prime test based on Rabin-Miller's test
- /// </summary>
- /// <param name="n" type="BigInteger.BigInteger">
- /// <para>
- /// The number to test.
- /// </para>
- /// </param>
- /// <param name="confidence" type="int">
- /// <para>
- /// The number of chosen bases. The test has at least a
- /// 1/4^confidence chance of falsely returning True.
- /// </para>
- /// </param>
- /// <returns>
- /// <para>
- /// True if "this" is a strong pseudoprime to randomly chosen bases.
- /// </para>
- /// <para>
- /// False if "this" is definitely NOT prime.
- /// </para>
- /// </returns>
- public static bool RabinMillerTest (BigInteger n, ConfidenceFactor confidence)
- {
- int bits = n.BitCount ();
- int t = GetSPPRounds (bits, confidence);
-
- // n - 1 == 2^s * r, r is odd
- BigInteger n_minus_1 = n - 1;
- int s = n_minus_1.LowestSetBit ();
- BigInteger r = n_minus_1 >> s;
-
- BigInteger.ModulusRing mr = new BigInteger.ModulusRing (n);
-
- // Applying optimization from HAC section 4.50 (base == 2)
- // not a really random base but an interesting (and speedy) one
- BigInteger y = null;
- // FIXME - optimization disable for small primes due to bug #81857
- if (n.BitCount () > 100)
- y = mr.Pow (2, r);
-
- // still here ? start at round 1 (round 0 was a == 2)
- for (int round = 0; round < t; round++) {
-
- if ((round > 0) || (y == null)) {
- BigInteger a = null;
-
- // check for 2 <= a <= n - 2
- // ...but we already did a == 2 previously as an optimization
- do {
- a = BigInteger.GenerateRandom (bits);
- } while ((a <= 2) && (a >= n_minus_1));
-
- y = mr.Pow (a, r);
- }
-
- if (y == 1)
- continue;
-
- for (int j = 0; ((j < s) && (y != n_minus_1)); j++) {
-
- y = mr.Pow (y, 2);
- if (y == 1)
- return false;
- }
-
- if (y != n_minus_1)
- return false;
- }
- return true;
- }
-
- public static bool SmallPrimeSppTest (BigInteger bi, ConfidenceFactor confidence)
- {
- int Rounds = GetSPPRounds (bi, confidence);
-
- // calculate values of s and t
- BigInteger p_sub1 = bi - 1;
- int s = p_sub1.LowestSetBit ();
-
- BigInteger t = p_sub1 >> s;
-
-
- BigInteger.ModulusRing mr = new BigInteger.ModulusRing (bi);
-
- for (int round = 0; round < Rounds; round++) {
-
- BigInteger b = mr.Pow (BigInteger.smallPrimes [round], t);
-
- if (b == 1) continue; // a^t mod p = 1
-
- bool result = false;
- for (int j = 0; j < s; j++) {
-
- if (b == p_sub1) { // a^((2^j)*t) mod p = p-1 for some 0 <= j <= s-1
- result = true;
- break;
- }
-
- b = (b * b) % bi;
- }
-
- if (result == false)
- return false;
- }
- return true;
- }
-
- #endregion
-
- // TODO: Implement the Lucus test
- // TODO: Implement other new primality tests
- // TODO: Implement primality proving
- }
-}
+++ /dev/null
-//
-// BigInteger.cs - Big Integer implementation
-//
-// Authors:
-// Ben Maurer
-// Chew Keong TAN
-// Sebastien Pouliot <sebastien@ximian.com>
-// Pieter Philippaerts <Pieter@mentalis.org>
-//
-// Copyright (c) 2003 Ben Maurer
-// All rights reserved
-//
-// Copyright (c) 2002 Chew Keong TAN
-// All rights reserved.
-//
-// Copyright (C) 2004, 2007 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.Prime.Generator;
-using Mono.Math.Prime;
-
-namespace Mono.Math {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class BigInteger {
-
- #region Data Storage
-
- /// <summary>
- /// The Length of this BigInteger
- /// </summary>
- uint length = 1;
-
- /// <summary>
- /// The data for this BigInteger
- /// </summary>
- uint [] data;
-
- #endregion
-
- #region Constants
-
- /// <summary>
- /// Default length of a BigInteger in bytes
- /// </summary>
- const uint DEFAULT_LEN = 20;
-
- /// <summary>
- /// Table of primes below 2000.
- /// </summary>
- /// <remarks>
- /// <para>
- /// This table was generated using Mathematica 4.1 using the following function:
- /// </para>
- /// <para>
- /// <code>
- /// PrimeTable [x_] := Prime [Range [1, PrimePi [x]]]
- /// PrimeTable [6000]
- /// </code>
- /// </para>
- /// </remarks>
- internal static readonly uint [] smallPrimes = {
- 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
- 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151,
- 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233,
- 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317,
- 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419,
- 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503,
- 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607,
- 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701,
- 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811,
- 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911,
- 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997,
-
- 1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069, 1087,
- 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163, 1171, 1181,
- 1187, 1193, 1201, 1213, 1217, 1223, 1229, 1231, 1237, 1249, 1259, 1277, 1279,
- 1283, 1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
- 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459, 1471,
- 1481, 1483, 1487, 1489, 1493, 1499, 1511, 1523, 1531, 1543, 1549, 1553, 1559,
- 1567, 1571, 1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637,
- 1657, 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
- 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811, 1823, 1831, 1847, 1861, 1867,
- 1871, 1873, 1877, 1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973,
- 1979, 1987, 1993, 1997, 1999,
-
- 2003, 2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069, 2081, 2083, 2087, 2089,
- 2099, 2111, 2113, 2129, 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207,
- 2213, 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287, 2293, 2297,
- 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377, 2381, 2383, 2389,
- 2393, 2399, 2411, 2417, 2423, 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
- 2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617, 2621,
- 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693, 2699, 2707,
- 2711, 2713, 2719, 2729, 2731, 2741, 2749, 2753, 2767, 2777, 2789, 2791, 2797,
- 2801, 2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
- 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
-
- 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079, 3083, 3089, 3109,
- 3119, 3121, 3137, 3163, 3167, 3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
- 3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329,
- 3331, 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413, 3433, 3449,
- 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511, 3517, 3527, 3529, 3533, 3539,
- 3541, 3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631,
- 3637, 3643, 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727, 3733,
- 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821, 3823, 3833, 3847, 3851,
- 3853, 3863, 3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923, 3929, 3931, 3943,
- 3947, 3967, 3989,
-
- 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057, 4073, 4079, 4091,
- 4093, 4099, 4111, 4127, 4129, 4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
- 4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289,
- 4297, 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409, 4421, 4423,
- 4441, 4447, 4451, 4457, 4463, 4481, 4483, 4493, 4507, 4513, 4517, 4519, 4523,
- 4547, 4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621, 4637, 4639, 4643, 4649,
- 4651, 4657, 4663, 4673, 4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751, 4759,
- 4783, 4787, 4789, 4793, 4799, 4801, 4813, 4817, 4831, 4861, 4871, 4877, 4889,
- 4903, 4909, 4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967, 4969, 4973, 4987,
- 4993, 4999,
-
- 5003, 5009, 5011, 5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087, 5099, 5101,
- 5107, 5113, 5119, 5147, 5153, 5167, 5171, 5179, 5189, 5197, 5209, 5227, 5231,
- 5233, 5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309, 5323, 5333, 5347, 5351,
- 5381, 5387, 5393, 5399, 5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443, 5449,
- 5471, 5477, 5479, 5483, 5501, 5503, 5507, 5519, 5521, 5527, 5531, 5557, 5563,
- 5569, 5573, 5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653, 5657, 5659, 5669,
- 5683, 5689, 5693, 5701, 5711, 5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
- 5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849, 5851, 5857, 5861, 5867, 5869,
- 5879, 5881, 5897, 5903, 5923, 5927, 5939, 5953, 5981, 5987
- };
-
- public enum Sign : int {
- Negative = -1,
- Zero = 0,
- Positive = 1
- };
-
- #region Exception Messages
- const string WouldReturnNegVal = "Operation would return a negative value";
- #endregion
-
- #endregion
-
- #region Constructors
-
- public BigInteger ()
- {
- data = new uint [DEFAULT_LEN];
- this.length = DEFAULT_LEN;
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public BigInteger (Sign sign, uint len)
- {
- this.data = new uint [len];
- this.length = len;
- }
-
- public BigInteger (BigInteger bi)
- {
- this.data = (uint [])bi.data.Clone ();
- this.length = bi.length;
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public BigInteger (BigInteger bi, uint len)
- {
-
- this.data = new uint [len];
-
- for (uint i = 0; i < bi.length; i++)
- this.data [i] = bi.data [i];
-
- this.length = bi.length;
- }
-
- #endregion
-
- #region Conversions
-
- public BigInteger (byte [] inData)
- {
- if (inData.Length == 0)
- inData = new byte [1];
- length = (uint)inData.Length >> 2;
- int leftOver = inData.Length & 0x3;
-
- // length not multiples of 4
- if (leftOver != 0) length++;
-
- data = new uint [length];
-
- for (int i = inData.Length - 1, j = 0; i >= 3; i -= 4, j++) {
- data [j] = (uint)(
- (inData [i-3] << (3*8)) |
- (inData [i-2] << (2*8)) |
- (inData [i-1] << (1*8)) |
- (inData [i])
- );
- }
-
- switch (leftOver) {
- case 1: data [length-1] = (uint)inData [0]; break;
- case 2: data [length-1] = (uint)((inData [0] << 8) | inData [1]); break;
- case 3: data [length-1] = (uint)((inData [0] << 16) | (inData [1] << 8) | inData [2]); break;
- }
-
- this.Normalize ();
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public BigInteger (uint [] inData)
- {
- if (inData.Length == 0)
- inData = new uint [1];
- length = (uint)inData.Length;
-
- data = new uint [length];
-
- for (int i = (int)length - 1, j = 0; i >= 0; i--, j++)
- data [j] = inData [i];
-
- this.Normalize ();
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public BigInteger (uint ui)
- {
- data = new uint [] {ui};
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public BigInteger (ulong ul)
- {
- data = new uint [2] { (uint)ul, (uint)(ul >> 32)};
- length = 2;
-
- this.Normalize ();
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static implicit operator BigInteger (uint value)
- {
- return (new BigInteger (value));
- }
-
- public static implicit operator BigInteger (int value)
- {
- if (value < 0) throw new ArgumentOutOfRangeException ("value");
- return (new BigInteger ((uint)value));
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static implicit operator BigInteger (ulong value)
- {
- return (new BigInteger (value));
- }
-
- /* This is the BigInteger.Parse method I use. This method works
- because BigInteger.ToString returns the input I gave to Parse. */
- public static BigInteger Parse (string number)
- {
- if (number == null)
- throw new ArgumentNullException ("number");
-
- int i = 0, len = number.Length;
- char c;
- bool digits_seen = false;
- BigInteger val = new BigInteger (0);
- if (number [i] == '+') {
- i++;
- }
- else if (number [i] == '-') {
- throw new FormatException (WouldReturnNegVal);
- }
-
- for (; i < len; i++) {
- c = number [i];
- if (c == '\0') {
- i = len;
- continue;
- }
- if (c >= '0' && c <= '9') {
- val = val * 10 + (c - '0');
- digits_seen = true;
- }
- else {
- if (Char.IsWhiteSpace (c)) {
- for (i++; i < len; i++) {
- if (!Char.IsWhiteSpace (number [i]))
- throw new FormatException ();
- }
- break;
- }
- else
- throw new FormatException ();
- }
- }
- if (!digits_seen)
- throw new FormatException ();
- return val;
- }
-
- #endregion
-
- #region Operators
-
- public static BigInteger operator + (BigInteger bi1, BigInteger bi2)
- {
- if (bi1 == 0)
- return new BigInteger (bi2);
- else if (bi2 == 0)
- return new BigInteger (bi1);
- else
- return Kernel.AddSameSign (bi1, bi2);
- }
-
- public static BigInteger operator - (BigInteger bi1, BigInteger bi2)
- {
- if (bi2 == 0)
- return new BigInteger (bi1);
-
- if (bi1 == 0)
- throw new ArithmeticException (WouldReturnNegVal);
-
- switch (Kernel.Compare (bi1, bi2)) {
-
- case Sign.Zero:
- return 0;
-
- case Sign.Positive:
- return Kernel.Subtract (bi1, bi2);
-
- case Sign.Negative:
- throw new ArithmeticException (WouldReturnNegVal);
- default:
- throw new Exception ();
- }
- }
-
- public static int operator % (BigInteger bi, int i)
- {
- if (i > 0)
- return (int)Kernel.DwordMod (bi, (uint)i);
- else
- return -(int)Kernel.DwordMod (bi, (uint)-i);
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static uint operator % (BigInteger bi, uint ui)
- {
- return Kernel.DwordMod (bi, (uint)ui);
- }
-
- public static BigInteger operator % (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.multiByteDivide (bi1, bi2)[1];
- }
-
- public static BigInteger operator / (BigInteger bi, int i)
- {
- if (i > 0)
- return Kernel.DwordDiv (bi, (uint)i);
-
- throw new ArithmeticException (WouldReturnNegVal);
- }
-
- public static BigInteger operator / (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.multiByteDivide (bi1, bi2)[0];
- }
-
- public static BigInteger operator * (BigInteger bi1, BigInteger bi2)
- {
- if (bi1 == 0 || bi2 == 0) return 0;
-
- //
- // Validate pointers
- //
- if (bi1.data.Length < bi1.length) throw new IndexOutOfRangeException ("bi1 out of range");
- if (bi2.data.Length < bi2.length) throw new IndexOutOfRangeException ("bi2 out of range");
-
- BigInteger ret = new BigInteger (Sign.Positive, bi1.length + bi2.length);
-
- Kernel.Multiply (bi1.data, 0, bi1.length, bi2.data, 0, bi2.length, ret.data, 0);
-
- ret.Normalize ();
- return ret;
- }
-
- public static BigInteger operator * (BigInteger bi, int i)
- {
- if (i < 0) throw new ArithmeticException (WouldReturnNegVal);
- if (i == 0) return 0;
- if (i == 1) return new BigInteger (bi);
-
- return Kernel.MultiplyByDword (bi, (uint)i);
- }
-
- public static BigInteger operator << (BigInteger bi1, int shiftVal)
- {
- return Kernel.LeftShift (bi1, shiftVal);
- }
-
- public static BigInteger operator >> (BigInteger bi1, int shiftVal)
- {
- return Kernel.RightShift (bi1, shiftVal);
- }
-
- #endregion
-
- #region Friendly names for operators
-
- // with names suggested by FxCop 1.30
-
- public static BigInteger Add (BigInteger bi1, BigInteger bi2)
- {
- return (bi1 + bi2);
- }
-
- public static BigInteger Subtract (BigInteger bi1, BigInteger bi2)
- {
- return (bi1 - bi2);
- }
-
- public static int Modulus (BigInteger bi, int i)
- {
- return (bi % i);
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static uint Modulus (BigInteger bi, uint ui)
- {
- return (bi % ui);
- }
-
- public static BigInteger Modulus (BigInteger bi1, BigInteger bi2)
- {
- return (bi1 % bi2);
- }
-
- public static BigInteger Divid (BigInteger bi, int i)
- {
- return (bi / i);
- }
-
- public static BigInteger Divid (BigInteger bi1, BigInteger bi2)
- {
- return (bi1 / bi2);
- }
-
- public static BigInteger Multiply (BigInteger bi1, BigInteger bi2)
- {
- return (bi1 * bi2);
- }
-
- public static BigInteger Multiply (BigInteger bi, int i)
- {
- return (bi * i);
- }
-
- #endregion
-
- #region Random
- private static RandomNumberGenerator rng;
- private static RandomNumberGenerator Rng {
- get {
- if (rng == null)
- rng = RandomNumberGenerator.Create ();
- return rng;
- }
- }
-
- /// <summary>
- /// Generates a new, random BigInteger of the specified length.
- /// </summary>
- /// <param name="bits">The number of bits for the new number.</param>
- /// <param name="rng">A random number generator to use to obtain the bits.</param>
- /// <returns>A random number of the specified length.</returns>
- public static BigInteger GenerateRandom (int bits, RandomNumberGenerator rng)
- {
- int dwords = bits >> 5;
- int remBits = bits & 0x1F;
-
- if (remBits != 0)
- dwords++;
-
- BigInteger ret = new BigInteger (Sign.Positive, (uint)dwords + 1);
- byte [] random = new byte [dwords << 2];
-
- rng.GetBytes (random);
- Buffer.BlockCopy (random, 0, ret.data, 0, (int)dwords << 2);
-
- if (remBits != 0) {
- uint mask = (uint)(0x01 << (remBits-1));
- ret.data [dwords-1] |= mask;
-
- mask = (uint)(0xFFFFFFFF >> (32 - remBits));
- ret.data [dwords-1] &= mask;
- }
- else
- ret.data [dwords-1] |= 0x80000000;
-
- ret.Normalize ();
- return ret;
- }
-
- /// <summary>
- /// Generates a new, random BigInteger of the specified length using the default RNG crypto service provider.
- /// </summary>
- /// <param name="bits">The number of bits for the new number.</param>
- /// <returns>A random number of the specified length.</returns>
- public static BigInteger GenerateRandom (int bits)
- {
- return GenerateRandom (bits, Rng);
- }
-
- /// <summary>
- /// Randomizes the bits in "this" from the specified RNG.
- /// </summary>
- /// <param name="rng">A RNG.</param>
- public void Randomize (RandomNumberGenerator rng)
- {
- if (this == 0)
- return;
-
- int bits = this.BitCount ();
- int dwords = bits >> 5;
- int remBits = bits & 0x1F;
-
- if (remBits != 0)
- dwords++;
-
- byte [] random = new byte [dwords << 2];
-
- rng.GetBytes (random);
- Buffer.BlockCopy (random, 0, data, 0, (int)dwords << 2);
-
- if (remBits != 0) {
- uint mask = (uint)(0x01 << (remBits-1));
- data [dwords-1] |= mask;
-
- mask = (uint)(0xFFFFFFFF >> (32 - remBits));
- data [dwords-1] &= mask;
- }
-
- else
- data [dwords-1] |= 0x80000000;
-
- Normalize ();
- }
-
- /// <summary>
- /// Randomizes the bits in "this" from the default RNG.
- /// </summary>
- public void Randomize ()
- {
- Randomize (Rng);
- }
-
- #endregion
-
- #region Bitwise
-
- public int BitCount ()
- {
- this.Normalize ();
-
- uint value = data [length - 1];
- uint mask = 0x80000000;
- uint bits = 32;
-
- while (bits > 0 && (value & mask) == 0) {
- bits--;
- mask >>= 1;
- }
- bits += ((length - 1) << 5);
-
- return (int)bits;
- }
-
- /// <summary>
- /// Tests if the specified bit is 1.
- /// </summary>
- /// <param name="bitNum">The bit to test. The least significant bit is 0.</param>
- /// <returns>True if bitNum is set to 1, else false.</returns>
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public bool TestBit (uint bitNum)
- {
- uint bytePos = bitNum >> 5; // divide by 32
- byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
-
- uint mask = (uint)1 << bitPos;
- return ((this.data [bytePos] & mask) != 0);
- }
-
- public bool TestBit (int bitNum)
- {
- if (bitNum < 0) throw new IndexOutOfRangeException ("bitNum out of range");
-
- uint bytePos = (uint)bitNum >> 5; // divide by 32
- byte bitPos = (byte)(bitNum & 0x1F); // get the lowest 5 bits
-
- uint mask = (uint)1 << bitPos;
- return ((this.data [bytePos] | mask) == this.data [bytePos]);
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public void SetBit (uint bitNum)
- {
- SetBit (bitNum, true);
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public void ClearBit (uint bitNum)
- {
- SetBit (bitNum, false);
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public void SetBit (uint bitNum, bool value)
- {
- uint bytePos = bitNum >> 5; // divide by 32
-
- if (bytePos < this.length) {
- uint mask = (uint)1 << (int)(bitNum & 0x1F);
- if (value)
- this.data [bytePos] |= mask;
- else
- this.data [bytePos] &= ~mask;
- }
- }
-
- public int LowestSetBit ()
- {
- if (this == 0) return -1;
- int i = 0;
- while (!TestBit (i)) i++;
- return i;
- }
-
- public byte[] GetBytes ()
- {
- if (this == 0) return new byte [1];
-
- int numBits = BitCount ();
- int numBytes = numBits >> 3;
- if ((numBits & 0x7) != 0)
- numBytes++;
-
- byte [] result = new byte [numBytes];
-
- int numBytesInWord = numBytes & 0x3;
- if (numBytesInWord == 0) numBytesInWord = 4;
-
- int pos = 0;
- for (int i = (int)length - 1; i >= 0; i--) {
- uint val = data [i];
- for (int j = numBytesInWord - 1; j >= 0; j--) {
- result [pos+j] = (byte)(val & 0xFF);
- val >>= 8;
- }
- pos += numBytesInWord;
- numBytesInWord = 4;
- }
- return result;
- }
-
- #endregion
-
- #region Compare
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static bool operator == (BigInteger bi1, uint ui)
- {
- if (bi1.length != 1) bi1.Normalize ();
- return bi1.length == 1 && bi1.data [0] == ui;
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public static bool operator != (BigInteger bi1, uint ui)
- {
- if (bi1.length != 1) bi1.Normalize ();
- return !(bi1.length == 1 && bi1.data [0] == ui);
- }
-
- public static bool operator == (BigInteger bi1, BigInteger bi2)
- {
- // we need to compare with null
- if ((bi1 as object) == (bi2 as object))
- return true;
- if (null == bi1 || null == bi2)
- return false;
- return Kernel.Compare (bi1, bi2) == 0;
- }
-
- public static bool operator != (BigInteger bi1, BigInteger bi2)
- {
- // we need to compare with null
- if ((bi1 as object) == (bi2 as object))
- return false;
- if (null == bi1 || null == bi2)
- return true;
- return Kernel.Compare (bi1, bi2) != 0;
- }
-
- public static bool operator > (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.Compare (bi1, bi2) > 0;
- }
-
- public static bool operator < (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.Compare (bi1, bi2) < 0;
- }
-
- public static bool operator >= (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.Compare (bi1, bi2) >= 0;
- }
-
- public static bool operator <= (BigInteger bi1, BigInteger bi2)
- {
- return Kernel.Compare (bi1, bi2) <= 0;
- }
-
- public Sign Compare (BigInteger bi)
- {
- return Kernel.Compare (this, bi);
- }
-
- #endregion
-
- #region Formatting
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public string ToString (uint radix)
- {
- return ToString (radix, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- }
-
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
- public string ToString (uint radix, string characterSet)
- {
- if (characterSet.Length < radix)
- throw new ArgumentException ("charSet length less than radix", "characterSet");
- if (radix == 1)
- throw new ArgumentException ("There is no such thing as radix one notation", "radix");
-
- if (this == 0) return "0";
- if (this == 1) return "1";
-
- string result = "";
-
- BigInteger a = new BigInteger (this);
-
- while (a != 0) {
- uint rem = Kernel.SingleByteDivideInPlace (a, radix);
- result = characterSet [(int) rem] + result;
- }
-
- return result;
- }
-
- #endregion
-
- #region Misc
-
- /// <summary>
- /// Normalizes this by setting the length to the actual number of
- /// uints used in data and by setting the sign to Sign.Zero if the
- /// value of this is 0.
- /// </summary>
- private void Normalize ()
- {
- // Normalize length
- while (length > 0 && data [length-1] == 0) length--;
-
- // Check for zero
- if (length == 0)
- length++;
- }
-
- public void Clear ()
- {
- for (int i=0; i < length; i++)
- data [i] = 0x00;
- }
-
- #endregion
-
- #region Object Impl
-
- public override int GetHashCode ()
- {
- uint val = 0;
-
- for (uint i = 0; i < this.length; i++)
- val ^= this.data [i];
-
- return (int)val;
- }
-
- public override string ToString ()
- {
- return ToString (10);
- }
-
- public override bool Equals (object o)
- {
- if (o == null)
- return false;
- if (o is int)
- return (int)o >= 0 && this == (uint)o;
-
- BigInteger bi = o as BigInteger;
- if (bi == null)
- return false;
-
- return Kernel.Compare (this, bi) == 0;
- }
-
- #endregion
-
- #region Number Theory
-
- public BigInteger GCD (BigInteger bi)
- {
- return Kernel.gcd (this, bi);
- }
-
- public BigInteger ModInverse (BigInteger modulus)
- {
- return Kernel.modInverse (this, modulus);
- }
-
- public BigInteger ModPow (BigInteger exp, BigInteger n)
- {
- ModulusRing mr = new ModulusRing (n);
- return mr.Pow (this, exp);
- }
-
- #endregion
-
- #region Prime Testing
-
- public bool IsProbablePrime ()
- {
- // can we use our small-prime table ?
- if (this <= smallPrimes[smallPrimes.Length - 1]) {
- for (int p = 0; p < smallPrimes.Length; p++) {
- if (this == smallPrimes[p])
- return true;
- }
- // the list is complete, so it's not a prime
- return false;
- }
-
- // otherwise check if we can divide by one of the small primes
- for (int p = 0; p < smallPrimes.Length; p++) {
- if (this % smallPrimes[p] == 0)
- return false;
- }
- // the last step is to confirm the "large" prime with the SPP or Miller-Rabin test
- return PrimalityTests.Test (this, Prime.ConfidenceFactor.Medium);
- }
-
- #endregion
-
- #region Prime Number Generation
-
- /// <summary>
- /// Generates the smallest prime >= bi
- /// </summary>
- /// <param name="bi">A BigInteger</param>
- /// <returns>The smallest prime >= bi. More mathematically, if bi is prime: bi, else Prime [PrimePi [bi] + 1].</returns>
- public static BigInteger NextHighestPrime (BigInteger bi)
- {
- NextPrimeFinder npf = new NextPrimeFinder ();
- return npf.GenerateNewPrime (0, bi);
- }
-
- public static BigInteger GeneratePseudoPrime (int bits)
- {
- SequentialSearchPrimeGeneratorBase sspg = new SequentialSearchPrimeGeneratorBase ();
- return sspg.GenerateNewPrime (bits);
- }
-
- /// <summary>
- /// Increments this by two
- /// </summary>
- public void Incr2 ()
- {
- int i = 0;
-
- data [0] += 2;
-
- // If there was no carry, nothing to do
- if (data [0] < 2) {
-
- // Account for the first carry
- data [++i]++;
-
- // Keep adding until no carry
- while (data [i++] == 0x0)
- data [i]++;
-
- // See if we increased the data length
- if (length == (uint)i)
- length++;
- }
- }
-
- #endregion
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class ModulusRing {
-
- BigInteger mod, constant;
-
- public ModulusRing (BigInteger modulus)
- {
- this.mod = modulus;
-
- // calculate constant = b^ (2k) / m
- uint i = mod.length << 1;
-
- constant = new BigInteger (Sign.Positive, i + 1);
- constant.data [i] = 0x00000001;
-
- constant = constant / mod;
- }
-
- public void BarrettReduction (BigInteger x)
- {
- BigInteger n = mod;
- uint k = n.length,
- kPlusOne = k+1,
- kMinusOne = k-1;
-
- // x < mod, so nothing to do.
- if (x.length < k) return;
-
- BigInteger q3;
-
- //
- // Validate pointers
- //
- if (x.data.Length < x.length) throw new IndexOutOfRangeException ("x out of range");
-
- // q1 = x / b^ (k-1)
- // q2 = q1 * constant
- // q3 = q2 / b^ (k+1), Needs to be accessed with an offset of kPlusOne
-
- // TODO: We should the method in HAC p 604 to do this (14.45)
- q3 = new BigInteger (Sign.Positive, x.length - kMinusOne + constant.length);
- Kernel.Multiply (x.data, kMinusOne, x.length - kMinusOne, constant.data, 0, constant.length, q3.data, 0);
-
- // r1 = x mod b^ (k+1)
- // i.e. keep the lowest (k+1) words
-
- uint lengthToCopy = (x.length > kPlusOne) ? kPlusOne : x.length;
-
- x.length = lengthToCopy;
- x.Normalize ();
-
- // r2 = (q3 * n) mod b^ (k+1)
- // partial multiplication of q3 and n
-
- BigInteger r2 = new BigInteger (Sign.Positive, kPlusOne);
- Kernel.MultiplyMod2p32pmod (q3.data, (int)kPlusOne, (int)q3.length - (int)kPlusOne, n.data, 0, (int)n.length, r2.data, 0, (int)kPlusOne);
-
- r2.Normalize ();
-
- if (r2 <= x) {
- Kernel.MinusEq (x, r2);
- } else {
- BigInteger val = new BigInteger (Sign.Positive, kPlusOne + 1);
- val.data [kPlusOne] = 0x00000001;
-
- Kernel.MinusEq (val, r2);
- Kernel.PlusEq (x, val);
- }
-
- while (x >= n)
- Kernel.MinusEq (x, n);
- }
-
- public BigInteger Multiply (BigInteger a, BigInteger b)
- {
- if (a == 0 || b == 0) return 0;
-
- if (a > mod)
- a %= mod;
-
- if (b > mod)
- b %= mod;
-
- BigInteger ret = a * b;
- BarrettReduction (ret);
-
- return ret;
- }
-
- public BigInteger Difference (BigInteger a, BigInteger b)
- {
- Sign cmp = Kernel.Compare (a, b);
- BigInteger diff;
-
- switch (cmp) {
- case Sign.Zero:
- return 0;
- case Sign.Positive:
- diff = a - b; break;
- case Sign.Negative:
- diff = b - a; break;
- default:
- throw new Exception ();
- }
-
- if (diff >= mod) {
- if (diff.length >= mod.length << 1)
- diff %= mod;
- else
- BarrettReduction (diff);
- }
- if (cmp == Sign.Negative)
- diff = mod - diff;
- return diff;
- }
-#if true
- public BigInteger Pow (BigInteger a, BigInteger k)
- {
- BigInteger b = new BigInteger (1);
- if (k == 0)
- return b;
-
- BigInteger A = a;
- if (k.TestBit (0))
- b = a;
-
- for (int i = 1; i < k.BitCount (); i++) {
- A = Multiply (A, A);
- if (k.TestBit (i))
- b = Multiply (A, b);
- }
- return b;
- }
-#else
- public BigInteger Pow (BigInteger b, BigInteger exp)
- {
- if ((mod.data [0] & 1) == 1) return OddPow (b, exp);
- else return EvenPow (b, exp);
- }
-
- public BigInteger EvenPow (BigInteger b, BigInteger exp)
- {
- BigInteger resultNum = new BigInteger ((BigInteger)1, mod.length << 1);
- BigInteger tempNum = new BigInteger (b % mod, mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
-
- uint totalBits = (uint)exp.BitCount ();
-
- uint [] wkspace = new uint [mod.length << 1];
-
- // perform squaring and multiply exponentiation
- for (uint pos = 0; pos < totalBits; pos++) {
- if (exp.TestBit (pos)) {
-
- Array.Clear (wkspace, 0, wkspace.Length);
- Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
- resultNum.length += tempNum.length;
- uint [] t = wkspace;
- wkspace = resultNum.data;
- resultNum.data = t;
-
- BarrettReduction (resultNum);
- }
-
- Kernel.SquarePositive (tempNum, ref wkspace);
- BarrettReduction (tempNum);
-
- if (tempNum == 1) {
- return resultNum;
- }
- }
-
- return resultNum;
- }
-
- private BigInteger OddPow (BigInteger b, BigInteger exp)
- {
- BigInteger resultNum = new BigInteger (Montgomery.ToMont (1, mod), mod.length << 1);
- BigInteger tempNum = new BigInteger (Montgomery.ToMont (b, mod), mod.length << 1); // ensures (tempNum * tempNum) < b^ (2k)
- uint mPrime = Montgomery.Inverse (mod.data [0]);
- uint totalBits = (uint)exp.BitCount ();
-
- uint [] wkspace = new uint [mod.length << 1];
-
- // perform squaring and multiply exponentiation
- for (uint pos = 0; pos < totalBits; pos++) {
- if (exp.TestBit (pos)) {
-
- Array.Clear (wkspace, 0, wkspace.Length);
- Kernel.Multiply (resultNum.data, 0, resultNum.length, tempNum.data, 0, tempNum.length, wkspace, 0);
- resultNum.length += tempNum.length;
- uint [] t = wkspace;
- wkspace = resultNum.data;
- resultNum.data = t;
-
- Montgomery.Reduce (resultNum, mod, mPrime);
- }
-
- // the value of tempNum is required in the last loop
- if (pos < totalBits - 1) {
- Kernel.SquarePositive (tempNum, ref wkspace);
- Montgomery.Reduce (tempNum, mod, mPrime);
- }
- }
-
- Montgomery.Reduce (resultNum, mod, mPrime);
- return resultNum;
- }
-#endif
- #region Pow Small Base
-
- // TODO: Make tests for this, not really needed b/c prime stuff
- // checks it, but still would be nice
-#if !INSIDE_CORLIB
- [CLSCompliant (false)]
-#endif
-#if true
- public BigInteger Pow (uint b, BigInteger exp)
- {
- return Pow (new BigInteger (b), exp);
- }
-#else
- public BigInteger Pow (uint b, BigInteger exp)
- {
-// if (b != 2) {
- if ((mod.data [0] & 1) == 1)
- return OddPow (b, exp);
- else
- return EvenPow (b, exp);
-/* buggy in some cases (like the well tested primes)
- } else {
- if ((mod.data [0] & 1) == 1)
- return OddModTwoPow (exp);
- else
- return EvenModTwoPow (exp);
- }*/
- }
-
- private unsafe BigInteger OddPow (uint b, BigInteger exp)
- {
- exp.Normalize ();
- uint [] wkspace = new uint [mod.length << 1 + 1];
-
- BigInteger resultNum = Montgomery.ToMont ((BigInteger)b, this.mod);
- resultNum = new BigInteger (resultNum, mod.length << 1 +1);
-
- uint mPrime = Montgomery.Inverse (mod.data [0]);
-
- int bc = exp.BitCount () - 2;
- uint pos = (bc > 1 ? (uint) bc : 1);
-
- //
- // We know that the first itr will make the val b
- //
-
- do {
- //
- // r = r ^ 2 % m
- //
- Kernel.SquarePositive (resultNum, ref wkspace);
- resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
-
- if (exp.TestBit (pos)) {
-
- //
- // r = r * b % m
- //
-
- // TODO: Is Unsafe really speeding things up?
- fixed (uint* u = resultNum.data) {
-
- uint i = 0;
- ulong mc = 0;
-
- do {
- mc += (ulong)u [i] * (ulong)b;
- u [i] = (uint)mc;
- mc >>= 32;
- } while (++i < resultNum.length);
-
- if (resultNum.length < mod.length) {
- if (mc != 0) {
- u [i] = (uint)mc;
- resultNum.length++;
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- }
- } else if (mc != 0) {
-
- //
- // First, we estimate the quotient by dividing
- // the first part of each of the numbers. Then
- // we correct this, if necessary, with a subtraction.
- //
-
- uint cc = (uint)mc;
-
- // We would rather have this estimate overshoot,
- // so we add one to the divisor
- uint divEstimate;
- if (mod.data [mod.length - 1] < UInt32.MaxValue) {
- divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
- (mod.data [mod.length-1] + 1));
- }
- else {
- // guess but don't divide by 0
- divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
- (mod.data [mod.length-1]));
- }
-
- uint t;
-
- i = 0;
- mc = 0;
- do {
- mc += (ulong)mod.data [i] * (ulong)divEstimate;
- t = u [i];
- u [i] -= (uint)mc;
- mc >>= 32;
- if (u [i] > t) mc++;
- i++;
- } while (i < resultNum.length);
- cc -= (uint)mc;
-
- if (cc != 0) {
-
- uint sc = 0, j = 0;
- uint [] s = mod.data;
- do {
- uint a = s [j];
- if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
- else sc = 0;
- j++;
- } while (j < resultNum.length);
- cc -= sc;
- }
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- } else {
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- }
- }
- }
- } while (pos-- > 0);
-
- resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
- return resultNum;
-
- }
-
- private unsafe BigInteger EvenPow (uint b, BigInteger exp)
- {
- exp.Normalize ();
- uint [] wkspace = new uint [mod.length << 1 + 1];
- BigInteger resultNum = new BigInteger ((BigInteger)b, mod.length << 1 + 1);
-
- uint pos = (uint)exp.BitCount () - 2;
-
- //
- // We know that the first itr will make the val b
- //
-
- do {
- //
- // r = r ^ 2 % m
- //
- Kernel.SquarePositive (resultNum, ref wkspace);
- if (!(resultNum.length < mod.length))
- BarrettReduction (resultNum);
-
- if (exp.TestBit (pos)) {
-
- //
- // r = r * b % m
- //
-
- // TODO: Is Unsafe really speeding things up?
- fixed (uint* u = resultNum.data) {
-
- uint i = 0;
- ulong mc = 0;
-
- do {
- mc += (ulong)u [i] * (ulong)b;
- u [i] = (uint)mc;
- mc >>= 32;
- } while (++i < resultNum.length);
-
- if (resultNum.length < mod.length) {
- if (mc != 0) {
- u [i] = (uint)mc;
- resultNum.length++;
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- }
- } else if (mc != 0) {
-
- //
- // First, we estimate the quotient by dividing
- // the first part of each of the numbers. Then
- // we correct this, if necessary, with a subtraction.
- //
-
- uint cc = (uint)mc;
-
- // We would rather have this estimate overshoot,
- // so we add one to the divisor
- uint divEstimate = (uint) ((((ulong)cc << 32) | (ulong) u [i -1]) /
- (mod.data [mod.length-1] + 1));
-
- uint t;
-
- i = 0;
- mc = 0;
- do {
- mc += (ulong)mod.data [i] * (ulong)divEstimate;
- t = u [i];
- u [i] -= (uint)mc;
- mc >>= 32;
- if (u [i] > t) mc++;
- i++;
- } while (i < resultNum.length);
- cc -= (uint)mc;
-
- if (cc != 0) {
-
- uint sc = 0, j = 0;
- uint [] s = mod.data;
- do {
- uint a = s [j];
- if (((a += sc) < sc) | ((u [j] -= a) > ~a)) sc = 1;
- else sc = 0;
- j++;
- } while (j < resultNum.length);
- cc -= sc;
- }
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- } else {
- while (resultNum >= mod)
- Kernel.MinusEq (resultNum, mod);
- }
- }
- }
- } while (pos-- > 0);
-
- return resultNum;
- }
-#endif
-/* known to be buggy in some cases */
-#if false
- private unsafe BigInteger EvenModTwoPow (BigInteger exp)
- {
- exp.Normalize ();
- uint [] wkspace = new uint [mod.length << 1 + 1];
-
- BigInteger resultNum = new BigInteger (2, mod.length << 1 +1);
-
- uint value = exp.data [exp.length - 1];
- uint mask = 0x80000000;
-
- // Find the first bit of the exponent
- while ((value & mask) == 0)
- mask >>= 1;
-
- //
- // We know that the first itr will make the val 2,
- // so eat one bit of the exponent
- //
- mask >>= 1;
-
- uint wPos = exp.length - 1;
-
- do {
- value = exp.data [wPos];
- do {
- Kernel.SquarePositive (resultNum, ref wkspace);
- if (resultNum.length >= mod.length)
- BarrettReduction (resultNum);
-
- if ((value & mask) != 0) {
- //
- // resultNum = (resultNum * 2) % mod
- //
-
- fixed (uint* u = resultNum.data) {
- //
- // Double
- //
- uint* uu = u;
- uint* uuE = u + resultNum.length;
- uint x, carry = 0;
- while (uu < uuE) {
- x = *uu;
- *uu = (x << 1) | carry;
- carry = x >> (32 - 1);
- uu++;
- }
-
- // subtraction inlined because we know it is square
- if (carry != 0 || resultNum >= mod) {
- uu = u;
- uint c = 0;
- uint [] s = mod.data;
- uint i = 0;
- do {
- uint a = s [i];
- if (((a += c) < c) | ((* (uu++) -= a) > ~a))
- c = 1;
- else
- c = 0;
- i++;
- } while (uu < uuE);
- }
- }
- }
- } while ((mask >>= 1) > 0);
- mask = 0x80000000;
- } while (wPos-- > 0);
-
- return resultNum;
- }
-
- private unsafe BigInteger OddModTwoPow (BigInteger exp)
- {
-
- uint [] wkspace = new uint [mod.length << 1 + 1];
-
- BigInteger resultNum = Montgomery.ToMont ((BigInteger)2, this.mod);
- resultNum = new BigInteger (resultNum, mod.length << 1 +1);
-
- uint mPrime = Montgomery.Inverse (mod.data [0]);
-
- //
- // TODO: eat small bits, the ones we can do with no modular reduction
- //
- uint pos = (uint)exp.BitCount () - 2;
-
- do {
- Kernel.SquarePositive (resultNum, ref wkspace);
- resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
-
- if (exp.TestBit (pos)) {
- //
- // resultNum = (resultNum * 2) % mod
- //
-
- fixed (uint* u = resultNum.data) {
- //
- // Double
- //
- uint* uu = u;
- uint* uuE = u + resultNum.length;
- uint x, carry = 0;
- while (uu < uuE) {
- x = *uu;
- *uu = (x << 1) | carry;
- carry = x >> (32 - 1);
- uu++;
- }
-
- // subtraction inlined because we know it is square
- if (carry != 0 || resultNum >= mod) {
- fixed (uint* s = mod.data) {
- uu = u;
- uint c = 0;
- uint* ss = s;
- do {
- uint a = *ss++;
- if (((a += c) < c) | ((* (uu++) -= a) > ~a))
- c = 1;
- else
- c = 0;
- } while (uu < uuE);
- }
- }
- }
- }
- } while (pos-- > 0);
-
- resultNum = Montgomery.Reduce (resultNum, mod, mPrime);
- return resultNum;
- }
-#endif
- #endregion
- }
-
- /// <summary>
- /// Low level functions for the BigInteger
- /// </summary>
- private sealed class Kernel {
-
- #region Addition/Subtraction
-
- /// <summary>
- /// Adds two numbers with the same sign.
- /// </summary>
- /// <param name="bi1">A BigInteger</param>
- /// <param name="bi2">A BigInteger</param>
- /// <returns>bi1 + bi2</returns>
- public static BigInteger AddSameSign (BigInteger bi1, BigInteger bi2)
- {
- uint [] x, y;
- uint yMax, xMax, i = 0;
-
- // x should be bigger
- if (bi1.length < bi2.length) {
- x = bi2.data;
- xMax = bi2.length;
- y = bi1.data;
- yMax = bi1.length;
- } else {
- x = bi1.data;
- xMax = bi1.length;
- y = bi2.data;
- yMax = bi2.length;
- }
-
- BigInteger result = new BigInteger (Sign.Positive, xMax + 1);
-
- uint [] r = result.data;
-
- ulong sum = 0;
-
- // Add common parts of both numbers
- do {
- sum = ((ulong)x [i]) + ((ulong)y [i]) + sum;
- r [i] = (uint)sum;
- sum >>= 32;
- } while (++i < yMax);
-
- // Copy remainder of longer number while carry propagation is required
- bool carry = (sum != 0);
-
- if (carry) {
-
- if (i < xMax) {
- do
- carry = ((r [i] = x [i] + 1) == 0);
- while (++i < xMax && carry);
- }
-
- if (carry) {
- r [i] = 1;
- result.length = ++i;
- return result;
- }
- }
-
- // Copy the rest
- if (i < xMax) {
- do
- r [i] = x [i];
- while (++i < xMax);
- }
-
- result.Normalize ();
- return result;
- }
-
- public static BigInteger Subtract (BigInteger big, BigInteger small)
- {
- BigInteger result = new BigInteger (Sign.Positive, big.length);
-
- uint [] r = result.data, b = big.data, s = small.data;
- uint i = 0, c = 0;
-
- do {
-
- uint x = s [i];
- if (((x += c) < c) | ((r [i] = b [i] - x) > ~x))
- c = 1;
- else
- c = 0;
-
- } while (++i < small.length);
-
- if (i == big.length) goto fixup;
-
- if (c == 1) {
- do
- r [i] = b [i] - 1;
- while (b [i++] == 0 && i < big.length);
-
- if (i == big.length) goto fixup;
- }
-
- do
- r [i] = b [i];
- while (++i < big.length);
-
- fixup:
-
- result.Normalize ();
- return result;
- }
-
- public static void MinusEq (BigInteger big, BigInteger small)
- {
- uint [] b = big.data, s = small.data;
- uint i = 0, c = 0;
-
- do {
- uint x = s [i];
- if (((x += c) < c) | ((b [i] -= x) > ~x))
- c = 1;
- else
- c = 0;
- } while (++i < small.length);
-
- if (i == big.length) goto fixup;
-
- if (c == 1) {
- do
- b [i]--;
- while (b [i++] == 0 && i < big.length);
- }
-
- fixup:
-
- // Normalize length
- while (big.length > 0 && big.data [big.length-1] == 0) big.length--;
-
- // Check for zero
- if (big.length == 0)
- big.length++;
-
- }
-
- public static void PlusEq (BigInteger bi1, BigInteger bi2)
- {
- uint [] x, y;
- uint yMax, xMax, i = 0;
- bool flag = false;
-
- // x should be bigger
- if (bi1.length < bi2.length){
- flag = true;
- x = bi2.data;
- xMax = bi2.length;
- y = bi1.data;
- yMax = bi1.length;
- } else {
- x = bi1.data;
- xMax = bi1.length;
- y = bi2.data;
- yMax = bi2.length;
- }
-
- uint [] r = bi1.data;
-
- ulong sum = 0;
-
- // Add common parts of both numbers
- do {
- sum += ((ulong)x [i]) + ((ulong)y [i]);
- r [i] = (uint)sum;
- sum >>= 32;
- } while (++i < yMax);
-
- // Copy remainder of longer number while carry propagation is required
- bool carry = (sum != 0);
-
- if (carry){
-
- if (i < xMax) {
- do
- carry = ((r [i] = x [i] + 1) == 0);
- while (++i < xMax && carry);
- }
-
- if (carry) {
- r [i] = 1;
- bi1.length = ++i;
- return;
- }
- }
-
- // Copy the rest
- if (flag && i < xMax - 1) {
- do
- r [i] = x [i];
- while (++i < xMax);
- }
-
- bi1.length = xMax + 1;
- bi1.Normalize ();
- }
-
- #endregion
-
- #region Compare
-
- /// <summary>
- /// Compares two BigInteger
- /// </summary>
- /// <param name="bi1">A BigInteger</param>
- /// <param name="bi2">A BigInteger</param>
- /// <returns>The sign of bi1 - bi2</returns>
- public static Sign Compare (BigInteger bi1, BigInteger bi2)
- {
- //
- // Step 1. Compare the lengths
- //
- uint l1 = bi1.length, l2 = bi2.length;
-
- while (l1 > 0 && bi1.data [l1-1] == 0) l1--;
- while (l2 > 0 && bi2.data [l2-1] == 0) l2--;
-
- if (l1 == 0 && l2 == 0) return Sign.Zero;
-
- // bi1 len < bi2 len
- if (l1 < l2) return Sign.Negative;
- // bi1 len > bi2 len
- else if (l1 > l2) return Sign.Positive;
-
- //
- // Step 2. Compare the bits
- //
-
- uint pos = l1 - 1;
-
- while (pos != 0 && bi1.data [pos] == bi2.data [pos]) pos--;
-
- if (bi1.data [pos] < bi2.data [pos])
- return Sign.Negative;
- else if (bi1.data [pos] > bi2.data [pos])
- return Sign.Positive;
- else
- return Sign.Zero;
- }
-
- #endregion
-
- #region Division
-
- #region Dword
-
- /// <summary>
- /// Performs n / d and n % d in one operation.
- /// </summary>
- /// <param name="n">A BigInteger, upon exit this will hold n / d</param>
- /// <param name="d">The divisor</param>
- /// <returns>n % d</returns>
- public static uint SingleByteDivideInPlace (BigInteger n, uint d)
- {
- ulong r = 0;
- uint i = n.length;
-
- while (i-- > 0) {
- r <<= 32;
- r |= n.data [i];
- n.data [i] = (uint)(r / d);
- r %= d;
- }
- n.Normalize ();
-
- return (uint)r;
- }
-
- public static uint DwordMod (BigInteger n, uint d)
- {
- ulong r = 0;
- uint i = n.length;
-
- while (i-- > 0) {
- r <<= 32;
- r |= n.data [i];
- r %= d;
- }
-
- return (uint)r;
- }
-
- public static BigInteger DwordDiv (BigInteger n, uint d)
- {
- BigInteger ret = new BigInteger (Sign.Positive, n.length);
-
- ulong r = 0;
- uint i = n.length;
-
- while (i-- > 0) {
- r <<= 32;
- r |= n.data [i];
- ret.data [i] = (uint)(r / d);
- r %= d;
- }
- ret.Normalize ();
-
- return ret;
- }
-
- public static BigInteger [] DwordDivMod (BigInteger n, uint d)
- {
- BigInteger ret = new BigInteger (Sign.Positive , n.length);
-
- ulong r = 0;
- uint i = n.length;
-
- while (i-- > 0) {
- r <<= 32;
- r |= n.data [i];
- ret.data [i] = (uint)(r / d);
- r %= d;
- }
- ret.Normalize ();
-
- BigInteger rem = (uint)r;
-
- return new BigInteger [] {ret, rem};
- }
-
- #endregion
-
- #region BigNum
-
- public static BigInteger [] multiByteDivide (BigInteger bi1, BigInteger bi2)
- {
- if (Kernel.Compare (bi1, bi2) == Sign.Negative)
- return new BigInteger [2] { 0, new BigInteger (bi1) };
-
- bi1.Normalize (); bi2.Normalize ();
-
- if (bi2.length == 1)
- return DwordDivMod (bi1, bi2.data [0]);
-
- uint remainderLen = bi1.length + 1;
- int divisorLen = (int)bi2.length + 1;
-
- uint mask = 0x80000000;
- uint val = bi2.data [bi2.length - 1];
- int shift = 0;
- int resultPos = (int)bi1.length - (int)bi2.length;
-
- while (mask != 0 && (val & mask) == 0) {
- shift++; mask >>= 1;
- }
-
- BigInteger quot = new BigInteger (Sign.Positive, bi1.length - bi2.length + 1);
- BigInteger rem = (bi1 << shift);
-
- uint [] remainder = rem.data;
-
- bi2 = bi2 << shift;
-
- int j = (int)(remainderLen - bi2.length);
- int pos = (int)remainderLen - 1;
-
- uint firstDivisorByte = bi2.data [bi2.length-1];
- ulong secondDivisorByte = bi2.data [bi2.length-2];
-
- while (j > 0) {
- ulong dividend = ((ulong)remainder [pos] << 32) + (ulong)remainder [pos-1];
-
- ulong q_hat = dividend / (ulong)firstDivisorByte;
- ulong r_hat = dividend % (ulong)firstDivisorByte;
-
- do {
-
- if (q_hat == 0x100000000 ||
- (q_hat * secondDivisorByte) > ((r_hat << 32) + remainder [pos-2])) {
- q_hat--;
- r_hat += (ulong)firstDivisorByte;
-
- if (r_hat < 0x100000000)
- continue;
- }
- break;
- } while (true);
-
- //
- // At this point, q_hat is either exact, or one too large
- // (more likely to be exact) so, we attempt to multiply the
- // divisor by q_hat, if we get a borrow, we just subtract
- // one from q_hat and add the divisor back.
- //
-
- uint t;
- uint dPos = 0;
- int nPos = pos - divisorLen + 1;
- ulong mc = 0;
- uint uint_q_hat = (uint)q_hat;
- do {
- mc += (ulong)bi2.data [dPos] * (ulong)uint_q_hat;
- t = remainder [nPos];
- remainder [nPos] -= (uint)mc;
- mc >>= 32;
- if (remainder [nPos] > t) mc++;
- dPos++; nPos++;
- } while (dPos < divisorLen);
-
- nPos = pos - divisorLen + 1;
- dPos = 0;
-
- // Overestimate
- if (mc != 0) {
- uint_q_hat--;
- ulong sum = 0;
-
- do {
- sum = ((ulong)remainder [nPos]) + ((ulong)bi2.data [dPos]) + sum;
- remainder [nPos] = (uint)sum;
- sum >>= 32;
- dPos++; nPos++;
- } while (dPos < divisorLen);
-
- }
-
- quot.data [resultPos--] = (uint)uint_q_hat;
-
- pos--;
- j--;
- }
-
- quot.Normalize ();
- rem.Normalize ();
- BigInteger [] ret = new BigInteger [2] { quot, rem };
-
- if (shift != 0)
- ret [1] >>= shift;
-
- return ret;
- }
-
- #endregion
-
- #endregion
-
- #region Shift
- public static BigInteger LeftShift (BigInteger bi, int n)
- {
- if (n == 0) return new BigInteger (bi, bi.length + 1);
-
- int w = n >> 5;
- n &= ((1 << 5) - 1);
-
- BigInteger ret = new BigInteger (Sign.Positive, bi.length + 1 + (uint)w);
-
- uint i = 0, l = bi.length;
- if (n != 0) {
- uint x, carry = 0;
- while (i < l) {
- x = bi.data [i];
- ret.data [i + w] = (x << n) | carry;
- carry = x >> (32 - n);
- i++;
- }
- ret.data [i + w] = carry;
- } else {
- while (i < l) {
- ret.data [i + w] = bi.data [i];
- i++;
- }
- }
-
- ret.Normalize ();
- return ret;
- }
-
- public static BigInteger RightShift (BigInteger bi, int n)
- {
- if (n == 0) return new BigInteger (bi);
-
- int w = n >> 5;
- int s = n & ((1 << 5) - 1);
-
- BigInteger ret = new BigInteger (Sign.Positive, bi.length - (uint)w + 1);
- uint l = (uint)ret.data.Length - 1;
-
- if (s != 0) {
-
- uint x, carry = 0;
-
- while (l-- > 0) {
- x = bi.data [l + w];
- ret.data [l] = (x >> n) | carry;
- carry = x << (32 - n);
- }
- } else {
- while (l-- > 0)
- ret.data [l] = bi.data [l + w];
-
- }
- ret.Normalize ();
- return ret;
- }
-
- #endregion
-
- #region Multiply
-
- public static BigInteger MultiplyByDword (BigInteger n, uint f)
- {
- BigInteger ret = new BigInteger (Sign.Positive, n.length + 1);
-
- uint i = 0;
- ulong c = 0;
-
- do {
- c += (ulong)n.data [i] * (ulong)f;
- ret.data [i] = (uint)c;
- c >>= 32;
- } while (++i < n.length);
- ret.data [i] = (uint)c;
- ret.Normalize ();
- return ret;
-
- }
-
- /// <summary>
- /// Multiplies the data in x [xOffset:xOffset+xLen] by
- /// y [yOffset:yOffset+yLen] and puts it into
- /// d [dOffset:dOffset+xLen+yLen].
- /// </summary>
- /// <remarks>
- /// This code is unsafe! It is the caller's responsibility to make
- /// sure that it is safe to access x [xOffset:xOffset+xLen],
- /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+xLen+yLen].
- /// </remarks>
- public static unsafe void Multiply (uint [] x, uint xOffset, uint xLen, uint [] y, uint yOffset, uint yLen, uint [] d, uint dOffset)
- {
- fixed (uint* xx = x, yy = y, dd = d) {
- uint* xP = xx + xOffset,
- xE = xP + xLen,
- yB = yy + yOffset,
- yE = yB + yLen,
- dB = dd + dOffset;
-
- for (; xP < xE; xP++, dB++) {
-
- if (*xP == 0) continue;
-
- ulong mcarry = 0;
-
- uint* dP = dB;
- for (uint* yP = yB; yP < yE; yP++, dP++) {
- mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
-
- *dP = (uint)mcarry;
- mcarry >>= 32;
- }
-
- if (mcarry != 0)
- *dP = (uint)mcarry;
- }
- }
- }
-
- /// <summary>
- /// Multiplies the data in x [xOffset:xOffset+xLen] by
- /// y [yOffset:yOffset+yLen] and puts the low mod words into
- /// d [dOffset:dOffset+mod].
- /// </summary>
- /// <remarks>
- /// This code is unsafe! It is the caller's responsibility to make
- /// sure that it is safe to access x [xOffset:xOffset+xLen],
- /// y [yOffset:yOffset+yLen], and d [dOffset:dOffset+mod].
- /// </remarks>
- public static unsafe void MultiplyMod2p32pmod (uint [] x, int xOffset, int xLen, uint [] y, int yOffest, int yLen, uint [] d, int dOffset, int mod)
- {
- fixed (uint* xx = x, yy = y, dd = d) {
- uint* xP = xx + xOffset,
- xE = xP + xLen,
- yB = yy + yOffest,
- yE = yB + yLen,
- dB = dd + dOffset,
- dE = dB + mod;
-
- for (; xP < xE; xP++, dB++) {
-
- if (*xP == 0) continue;
-
- ulong mcarry = 0;
- uint* dP = dB;
- for (uint* yP = yB; yP < yE && dP < dE; yP++, dP++) {
- mcarry += ((ulong)*xP * (ulong)*yP) + (ulong)*dP;
-
- *dP = (uint)mcarry;
- mcarry >>= 32;
- }
-
- if (mcarry != 0 && dP < dE)
- *dP = (uint)mcarry;
- }
- }
- }
-
- public static unsafe void SquarePositive (BigInteger bi, ref uint [] wkSpace)
- {
- uint [] t = wkSpace;
- wkSpace = bi.data;
- uint [] d = bi.data;
- uint dl = bi.length;
- bi.data = t;
-
- fixed (uint* dd = d, tt = t) {
-
- uint* ttE = tt + t.Length;
- // Clear the dest
- for (uint* ttt = tt; ttt < ttE; ttt++)
- *ttt = 0;
-
- uint* dP = dd, tP = tt;
-
- for (uint i = 0; i < dl; i++, dP++) {
- if (*dP == 0)
- continue;
-
- ulong mcarry = 0;
- uint bi1val = *dP;
-
- uint* dP2 = dP + 1, tP2 = tP + 2*i + 1;
-
- for (uint j = i + 1; j < dl; j++, tP2++, dP2++) {
- // k = i + j
- mcarry += ((ulong)bi1val * (ulong)*dP2) + *tP2;
-
- *tP2 = (uint)mcarry;
- mcarry >>= 32;
- }
-
- if (mcarry != 0)
- *tP2 = (uint)mcarry;
- }
-
- // Double t. Inlined for speed.
-
- tP = tt;
-
- uint x, carry = 0;
- while (tP < ttE) {
- x = *tP;
- *tP = (x << 1) | carry;
- carry = x >> (32 - 1);
- tP++;
- }
- if (carry != 0) *tP = carry;
-
- // Add in the diagnals
-
- dP = dd;
- tP = tt;
- for (uint* dE = dP + dl; (dP < dE); dP++, tP++) {
- ulong val = (ulong)*dP * (ulong)*dP + *tP;
- *tP = (uint)val;
- val >>= 32;
- *(++tP) += (uint)val;
- if (*tP < (uint)val) {
- uint* tP3 = tP;
- // Account for the first carry
- (*++tP3)++;
-
- // Keep adding until no carry
- while ((*tP3++) == 0)
- (*tP3)++;
- }
-
- }
-
- bi.length <<= 1;
-
- // Normalize length
- while (tt [bi.length-1] == 0 && bi.length > 1) bi.length--;
-
- }
- }
-
-/*
- * Never called in BigInteger (and part of a private class)
- * public static bool Double (uint [] u, int l)
- {
- uint x, carry = 0;
- uint i = 0;
- while (i < l) {
- x = u [i];
- u [i] = (x << 1) | carry;
- carry = x >> (32 - 1);
- i++;
- }
- if (carry != 0) u [l] = carry;
- return carry != 0;
- }*/
-
- #endregion
-
- #region Number Theory
-
- public static BigInteger gcd (BigInteger a, BigInteger b)
- {
- BigInteger x = a;
- BigInteger y = b;
-
- BigInteger g = y;
-
- while (x.length > 1) {
- g = x;
- x = y % x;
- y = g;
-
- }
- if (x == 0) return g;
-
- // TODO: should we have something here if we can convert to long?
-
- //
- // Now we can just do it with single precision. I am using the binary gcd method,
- // as it should be faster.
- //
-
- uint yy = x.data [0];
- uint xx = y % yy;
-
- int t = 0;
-
- while (((xx | yy) & 1) == 0) {
- xx >>= 1; yy >>= 1; t++;
- }
- while (xx != 0) {
- while ((xx & 1) == 0) xx >>= 1;
- while ((yy & 1) == 0) yy >>= 1;
- if (xx >= yy)
- xx = (xx - yy) >> 1;
- else
- yy = (yy - xx) >> 1;
- }
-
- return yy << t;
- }
-
- public static uint modInverse (BigInteger bi, uint modulus)
- {
- uint a = modulus, b = bi % modulus;
- uint p0 = 0, p1 = 1;
-
- while (b != 0) {
- if (b == 1)
- return p1;
- p0 += (a / b) * p1;
- a %= b;
-
- if (a == 0)
- break;
- if (a == 1)
- return modulus-p0;
-
- p1 += (b / a) * p0;
- b %= a;
-
- }
- return 0;
- }
-
- public static BigInteger modInverse (BigInteger bi, BigInteger modulus)
- {
- if (modulus.length == 1) return modInverse (bi, modulus.data [0]);
-
- BigInteger [] p = { 0, 1 };
- BigInteger [] q = new BigInteger [2]; // quotients
- BigInteger [] r = { 0, 0 }; // remainders
-
- int step = 0;
-
- BigInteger a = modulus;
- BigInteger b = bi;
-
- ModulusRing mr = new ModulusRing (modulus);
-
- while (b != 0) {
-
- if (step > 1) {
-
- BigInteger pval = mr.Difference (p [0], p [1] * q [0]);
- p [0] = p [1]; p [1] = pval;
- }
-
- BigInteger [] divret = multiByteDivide (a, b);
-
- q [0] = q [1]; q [1] = divret [0];
- r [0] = r [1]; r [1] = divret [1];
- a = b;
- b = divret [1];
-
- step++;
- }
-
- if (r [0] != 1)
- throw (new ArithmeticException ("No inverse!"));
-
- return mr.Difference (p [0], p [1] * q [0]);
-
- }
- #endregion
- }
- }
-}
+++ /dev/null
-2007-05-31 Alan McGovern <alan.mcgovern@gmail.com>
-
- * BigInteger.cs: Don't instantiate a new BigInteger after
- multiplying - it's not needed.
-
-2007-09-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Updated to match Mono.Security sources.
-
-2007-07-28 Miguel de Icaza <miguel@novell.com>
-
- * BigInteger.cs: Do not cast inside Equals,instead use the as
- operator, as reported by Jesse Jones.
-
-2004-12-03 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Fix issue #70169 in ModPow when modulus is a power of
- two.
-
-2004-10-19 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Fix issue #68452 when Randomize was being called on a
- 0 BigInteger (i.e. BitCount == 0).
-
-2004-05-14 Marek Safar <marek.safar@seznam.cz>
-
- * BigInteger.cs: Removed useless [CLSCompliant (false)]
-
-2004-05-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: In sync with Mono.Security.dll version.
-
-2004-04-30 Ben Maurer <bmaurer@users.sourceforge.net>
-
- * BigInteger.cs: use readonly for prime array.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: In sync with Mono.Security.dll version.
-
-2004-02-23 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Corrected isProbablePrime by removing the redundant
- loop. Fix #54750.
-
-2004-02-13 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Fixed isProbablePrime() and added Parse method from
- patch provided by Pieter (#51229). Changed SmallPrimeSppTest to
- RabinMillerTest (#51229, #54262). Removed obsoleted method
- isProbablePrime(int).
-
-2004-02-09 Sebastien Pouliot <sebastien@ximian.com>
-
- * BigInteger.cs: Added INSIDE_CORLIB to define ModulusRing as
- internal. Without this the unit tests for Mono.Math (now in
- Mono.Security assembly) wont compile (see bugzilla #44845).
-
-2003-11-20 Ben Maurer <bmaurer@users.sourceforge.net>
-
- * BigInteger.cs: Fix prob. prime test for small numbers (Pieter Philippaerts)
-
-2003-06-11 Sebastien Pouliot <spouliot@motus.com>
-
- * BigInteger.cs: Added Clear to zeroize big integers and code to allow
- compares with null (because operators == and != are re-defined). Note:
- The class may still leak some private info in temp arrays (thanks Ben).
-
-2003-04-22 Sebastien Pouliot <spouliot@videotron.ca>
-
- * BigInteger.cs: New, much faster, version by Ben Maurer.
- Warning: this version requires "unsafe" compilation switch
- (which isn't a problem in corlib but may be elsewhere)
-
-2003-02-08 Sebastien Pouliot <spouliot@videotron.ca>
-
- * BigInteger.cs: Renamed namespace to match new location.
-
+++ /dev/null
-//
-// AuthenticodeBase.cs: Authenticode signature base class
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004, 2006 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.IO;
-using System.Security.Cryptography;
-
-namespace Mono.Security.Authenticode {
-
- // References:
- // a. http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- enum Authority {
- Individual,
- Commercial,
- Maximum
- }
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class AuthenticodeBase {
-
- public const string spcIndirectDataContext = "1.3.6.1.4.1.311.2.1.4";
-
- private byte[] fileblock;
- private FileStream fs;
- private int blockNo;
- private int blockLength;
- private int peOffset;
- private int dirSecurityOffset;
- private int dirSecuritySize;
- private int coffSymbolTableOffset;
-
- public AuthenticodeBase ()
- {
- fileblock = new byte [4096];
- }
-
- internal int PEOffset {
- get {
- if (blockNo < 1)
- ReadFirstBlock ();
- return peOffset;
- }
- }
-
- internal int CoffSymbolTableOffset {
- get {
- if (blockNo < 1)
- ReadFirstBlock ();
- return coffSymbolTableOffset;
- }
- }
-
- internal int SecurityOffset {
- get {
- if (blockNo < 1)
- ReadFirstBlock ();
- return dirSecurityOffset;
- }
- }
-
- internal void Open (string filename)
- {
- if (fs != null)
- Close ();
- fs = new FileStream (filename, FileMode.Open, FileAccess.Read, FileShare.Read);
- }
-
- internal void Close ()
- {
- if (fs != null) {
- fs.Close ();
- fs = null;
- blockNo = 0;
- }
- }
-
- internal bool ReadFirstBlock ()
- {
- if (fs == null)
- return false;
-
- fs.Position = 0;
- // read first block - it will include (100% sure)
- // the MZ header and (99.9% sure) the PE header
- blockLength = fs.Read (fileblock, 0, fileblock.Length);
- blockNo = 1;
- if (blockLength < 64)
- return false; // invalid PE file
-
- // 1. Validate the MZ header informations
- // 1.1. Check for magic MZ at start of header
- if (BitConverterLE.ToUInt16 (fileblock, 0) != 0x5A4D)
- return false;
-
- // 1.2. Find the offset of the PE header
- peOffset = BitConverterLE.ToInt32 (fileblock, 60);
- if (peOffset > fileblock.Length) {
- // just in case (0.1%) this can actually happen
- string msg = String.Format (Locale.GetText (
- "Header size too big (> {0} bytes)."),
- fileblock.Length);
- throw new NotSupportedException (msg);
- }
- if (peOffset > fs.Length)
- return false;
-
- // 2. Read between DOS header and first part of PE header
- // 2.1. Check for magic PE at start of header
- // PE - NT header ('P' 'E' 0x00 0x00)
- if (BitConverterLE.ToUInt32 (fileblock, peOffset) != 0x4550)
- return false;
-
- // 2.2. Locate IMAGE_DIRECTORY_ENTRY_SECURITY (offset and size)
- dirSecurityOffset = BitConverterLE.ToInt32 (fileblock, peOffset + 152);
- dirSecuritySize = BitConverterLE.ToInt32 (fileblock, peOffset + 156);
-
- // COFF symbol tables are deprecated - we'll strip them if we see them!
- // (otherwise the signature won't work on MS and we don't want to support COFF for that)
- coffSymbolTableOffset = BitConverterLE.ToInt32 (fileblock, peOffset + 12);
-
- return true;
- }
-
- internal byte[] GetSecurityEntry ()
- {
- if (blockNo < 1)
- ReadFirstBlock ();
-
- if (dirSecuritySize > 8) {
- // remove header from size (not ASN.1 based)
- byte[] secEntry = new byte [dirSecuritySize - 8];
- // position after header and read entry
- fs.Position = dirSecurityOffset + 8;
- fs.Read (secEntry, 0, secEntry.Length);
- return secEntry;
- }
- return null;
- }
-
- internal byte[] GetHash (HashAlgorithm hash)
- {
- if (blockNo < 1)
- ReadFirstBlock ();
- fs.Position = blockLength;
-
- // hash the rest of the file
- long n;
- int addsize = 0;
- // minus any authenticode signature (with 8 bytes header)
- if (dirSecurityOffset > 0) {
- // it is also possible that the signature block
- // starts within the block in memory (small EXE)
- if (dirSecurityOffset < blockLength) {
- blockLength = dirSecurityOffset;
- n = 0;
- } else {
- n = dirSecurityOffset - blockLength;
- }
- } else if (coffSymbolTableOffset > 0) {
- fileblock[PEOffset + 12] = 0;
- fileblock[PEOffset + 13] = 0;
- fileblock[PEOffset + 14] = 0;
- fileblock[PEOffset + 15] = 0;
- fileblock[PEOffset + 16] = 0;
- fileblock[PEOffset + 17] = 0;
- fileblock[PEOffset + 18] = 0;
- fileblock[PEOffset + 19] = 0;
- // it is also possible that the signature block
- // starts within the block in memory (small EXE)
- if (coffSymbolTableOffset < blockLength) {
- blockLength = coffSymbolTableOffset;
- n = 0;
- } else {
- n = coffSymbolTableOffset - blockLength;
- }
- } else {
- addsize = (int) (fs.Length & 7);
- if (addsize > 0)
- addsize = 8 - addsize;
-
- n = fs.Length - blockLength;
- }
-
- // Authenticode(r) gymnastics
- // Hash from (generally) 0 to 215 (216 bytes)
- int pe = peOffset + 88;
- hash.TransformBlock (fileblock, 0, pe, fileblock, 0);
- // then skip 4 for checksum
- pe += 4;
- // Continue hashing from (generally) 220 to 279 (60 bytes)
- hash.TransformBlock (fileblock, pe, 60, fileblock, pe);
- // then skip 8 bytes for IMAGE_DIRECTORY_ENTRY_SECURITY
- pe += 68;
-
- // everything is present so start the hashing
- if (n == 0) {
- // hash the (only) block
- hash.TransformFinalBlock (fileblock, pe, blockLength - pe);
- }
- else {
- // hash the last part of the first (already in memory) block
- hash.TransformBlock (fileblock, pe, blockLength - pe, fileblock, pe);
-
- // hash by blocks of 4096 bytes
- long blocks = (n >> 12);
- int remainder = (int)(n - (blocks << 12));
- if (remainder == 0) {
- blocks--;
- remainder = 4096;
- }
- // blocks
- while (blocks-- > 0) {
- fs.Read (fileblock, 0, fileblock.Length);
- hash.TransformBlock (fileblock, 0, fileblock.Length, fileblock, 0);
- }
- // remainder
- if (fs.Read (fileblock, 0, remainder) != remainder)
- return null;
-
- if (addsize > 0) {
- hash.TransformBlock (fileblock, 0, remainder, fileblock, 0);
- hash.TransformFinalBlock (new byte [addsize], 0, addsize);
- } else {
- hash.TransformFinalBlock (fileblock, 0, remainder);
- }
- }
- return hash.Hash;
- }
-
- // for compatibility only
- protected byte[] HashFile (string fileName, string hashName)
- {
- try {
- Open (fileName);
- HashAlgorithm hash = HashAlgorithm.Create (hashName);
- byte[] result = GetHash (hash);
- Close ();
- return result;
- }
- catch {
- return null;
- }
- }
- }
-}
+++ /dev/null
-//
-// AuthenticodeDeformatter.cs: Authenticode signature validator
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2006 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.IO;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Cryptography;
-
-using Mono.Security.Cryptography;
-using Mono.Security.X509;
-
-namespace Mono.Security.Authenticode {
-
- // References:
- // a. http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class AuthenticodeDeformatter : AuthenticodeBase {
-
- private string filename;
- private byte[] hash;
- private X509CertificateCollection coll;
- private ASN1 signedHash;
- private DateTime timestamp;
- private X509Certificate signingCertificate;
- private int reason;
- private bool trustedRoot;
- private bool trustedTimestampRoot;
- private byte[] entry;
-
- private X509Chain signerChain;
- private X509Chain timestampChain;
-
- public AuthenticodeDeformatter () : base ()
- {
- reason = -1;
- signerChain = new X509Chain ();
- timestampChain = new X509Chain ();
- }
-
- public AuthenticodeDeformatter (string fileName) : this ()
- {
- FileName = fileName;
- }
-
- public string FileName {
- get { return filename; }
- set {
- Reset ();
- try {
- CheckSignature (value);
- }
- catch (SecurityException) {
- throw;
- }
- catch (Exception) {
- reason = 1;
- }
- }
- }
-
- public byte[] Hash {
- get {
- if (signedHash == null)
- return null;
- return (byte[]) signedHash.Value.Clone ();
- }
- }
-
- public int Reason {
- get {
- if (reason == -1)
- IsTrusted ();
- return reason;
- }
- }
-
- public bool IsTrusted ()
- {
- if (entry == null) {
- reason = 1;
- return false;
- }
-
- if (signingCertificate == null) {
- reason = 7;
- return false;
- }
-
- if ((signerChain.Root == null) || !trustedRoot) {
- reason = 6;
- return false;
- }
-
- if (timestamp != DateTime.MinValue) {
- if ((timestampChain.Root == null) || !trustedTimestampRoot) {
- reason = 6;
- return false;
- }
-
- // check that file was timestamped when certificates were valid
- if (!signingCertificate.WasCurrent (Timestamp)) {
- reason = 4;
- return false;
- }
- }
- else if (!signingCertificate.IsCurrent) {
- // signature only valid if the certificate is valid
- reason = 8;
- return false;
- }
-
- if (reason == -1)
- reason = 0;
- return true;
- }
-
- public byte[] Signature {
- get {
- if (entry == null)
- return null;
- return (byte[]) entry.Clone ();
- }
- }
-
- public DateTime Timestamp {
- get { return timestamp; }
- }
-
- public X509CertificateCollection Certificates {
- get { return coll; }
- }
-
- public X509Certificate SigningCertificate {
- get { return signingCertificate; }
- }
-
- private bool CheckSignature (string fileName)
- {
- filename = fileName;
- Open (filename);
- entry = GetSecurityEntry ();
- if (entry == null) {
- // no signature is present
- reason = 1;
- Close ();
- return false;
- }
-
- PKCS7.ContentInfo ci = new PKCS7.ContentInfo (entry);
- if (ci.ContentType != PKCS7.Oid.signedData) {
- Close ();
- return false;
- }
-
- PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content);
- if (sd.ContentInfo.ContentType != spcIndirectDataContext) {
- Close ();
- return false;
- }
-
- coll = sd.Certificates;
-
- ASN1 spc = sd.ContentInfo.Content;
- signedHash = spc [0][1][1];
-
- HashAlgorithm ha = null;
- switch (signedHash.Length) {
- case 16:
- ha = HashAlgorithm.Create ("MD5");
- hash = GetHash (ha);
- break;
- case 20:
- ha = HashAlgorithm.Create ("SHA1");
- hash = GetHash (ha);
- break;
- default:
- reason = 5;
- Close ();
- return false;
- }
- Close ();
-
- if (!signedHash.CompareValue (hash)) {
- reason = 2;
- }
-
- // messageDigest is a hash of spcIndirectDataContext (which includes the file hash)
- byte[] spcIDC = spc [0].Value;
- ha.Initialize (); // re-using hash instance
- byte[] messageDigest = ha.ComputeHash (spcIDC);
-
- bool sign = VerifySignature (sd, messageDigest, ha);
- return (sign && (reason == 0));
- }
-
- private bool CompareIssuerSerial (string issuer, byte[] serial, X509Certificate x509)
- {
- if (issuer != x509.IssuerName)
- return false;
- if (serial.Length != x509.SerialNumber.Length)
- return false;
- // MS shows the serial number inversed (so is Mono.Security.X509.X509Certificate)
- int n = serial.Length;
- for (int i=0; i < serial.Length; i++) {
- if (serial [i] != x509.SerialNumber [--n])
- return false;
- }
- // must be true
- return true;
- }
-
- //private bool VerifySignature (ASN1 cs, byte[] calculatedMessageDigest, string hashName)
- private bool VerifySignature (PKCS7.SignedData sd, byte[] calculatedMessageDigest, HashAlgorithm ha)
- {
- string contentType = null;
- ASN1 messageDigest = null;
-// string spcStatementType = null;
-// string spcSpOpusInfo = null;
-
- for (int i=0; i < sd.SignerInfo.AuthenticatedAttributes.Count; i++) {
- ASN1 attr = (ASN1) sd.SignerInfo.AuthenticatedAttributes [i];
- string oid = ASN1Convert.ToOid (attr[0]);
- switch (oid) {
- case "1.2.840.113549.1.9.3":
- // contentType
- contentType = ASN1Convert.ToOid (attr[1][0]);
- break;
- case "1.2.840.113549.1.9.4":
- // messageDigest
- messageDigest = attr[1][0];
- break;
- case "1.3.6.1.4.1.311.2.1.11":
- // spcStatementType (Microsoft code signing)
- // possible values
- // - individualCodeSigning (1 3 6 1 4 1 311 2 1 21)
- // - commercialCodeSigning (1 3 6 1 4 1 311 2 1 22)
-// spcStatementType = ASN1Convert.ToOid (attr[1][0][0]);
- break;
- case "1.3.6.1.4.1.311.2.1.12":
- // spcSpOpusInfo (Microsoft code signing)
-/* try {
- spcSpOpusInfo = System.Text.Encoding.UTF8.GetString (attr[1][0][0][0].Value);
- }
- catch (NullReferenceException) {
- spcSpOpusInfo = null;
- }*/
- break;
- default:
- break;
- }
- }
- if (contentType != spcIndirectDataContext)
- return false;
-
- // verify message digest
- if (messageDigest == null)
- return false;
- if (!messageDigest.CompareValue (calculatedMessageDigest))
- return false;
-
- // verify signature
- string hashOID = CryptoConfig.MapNameToOID (ha.ToString ());
-
- // change to SET OF (not [0]) as per PKCS #7 1.5
- ASN1 aa = new ASN1 (0x31);
- foreach (ASN1 a in sd.SignerInfo.AuthenticatedAttributes)
- aa.Add (a);
- ha.Initialize ();
- byte[] p7hash = ha.ComputeHash (aa.GetBytes ());
-
- byte[] signature = sd.SignerInfo.Signature;
- // we need to find the specified certificate
- string issuer = sd.SignerInfo.IssuerName;
- byte[] serial = sd.SignerInfo.SerialNumber;
- foreach (X509Certificate x509 in coll) {
- if (CompareIssuerSerial (issuer, serial, x509)) {
- // don't verify is key size don't match
- if (x509.PublicKey.Length > (signature.Length >> 3)) {
- // return the signing certificate even if the signature isn't correct
- // (required behaviour for 2.0 support)
- signingCertificate = x509;
- RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA;
- if (rsa.VerifyHash (p7hash, hashOID, signature)) {
- signerChain.LoadCertificates (coll);
- trustedRoot = signerChain.Build (x509);
- break;
- }
- }
- }
- }
-
- // timestamp signature is optional
- if (sd.SignerInfo.UnauthenticatedAttributes.Count == 0) {
- trustedTimestampRoot = true;
- } else {
- for (int i = 0; i < sd.SignerInfo.UnauthenticatedAttributes.Count; i++) {
- ASN1 attr = (ASN1) sd.SignerInfo.UnauthenticatedAttributes[i];
- string oid = ASN1Convert.ToOid (attr[0]);
- switch (oid) {
- case PKCS7.Oid.countersignature:
- // SEQUENCE {
- // OBJECT IDENTIFIER
- // countersignature (1 2 840 113549 1 9 6)
- // SET {
- PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr[1]);
- trustedTimestampRoot = VerifyCounterSignature (cs, signature);
- break;
- default:
- // we don't support other unauthenticated attributes
- break;
- }
- }
- }
-
- return (trustedRoot && trustedTimestampRoot);
- }
-
- private bool VerifyCounterSignature (PKCS7.SignerInfo cs, byte[] signature)
- {
- // SEQUENCE {
- // INTEGER 1
- if (cs.Version != 1)
- return false;
- // SEQUENCE {
- // SEQUENCE {
-
- string contentType = null;
- ASN1 messageDigest = null;
- for (int i=0; i < cs.AuthenticatedAttributes.Count; i++) {
- // SEQUENCE {
- // OBJECT IDENTIFIER
- ASN1 attr = (ASN1) cs.AuthenticatedAttributes [i];
- string oid = ASN1Convert.ToOid (attr[0]);
- switch (oid) {
- case "1.2.840.113549.1.9.3":
- // contentType
- contentType = ASN1Convert.ToOid (attr[1][0]);
- break;
- case "1.2.840.113549.1.9.4":
- // messageDigest
- messageDigest = attr[1][0];
- break;
- case "1.2.840.113549.1.9.5":
- // SEQUENCE {
- // OBJECT IDENTIFIER
- // signingTime (1 2 840 113549 1 9 5)
- // SET {
- // UTCTime '030124013651Z'
- // }
- // }
- timestamp = ASN1Convert.ToDateTime (attr[1][0]);
- break;
- default:
- break;
- }
- }
-
- if (contentType != PKCS7.Oid.data)
- return false;
-
- // verify message digest
- if (messageDigest == null)
- return false;
- // TODO: must be read from the ASN.1 structure
- string hashName = null;
- switch (messageDigest.Length) {
- case 16:
- hashName = "MD5";
- break;
- case 20:
- hashName = "SHA1";
- break;
- }
- HashAlgorithm ha = HashAlgorithm.Create (hashName);
- if (!messageDigest.CompareValue (ha.ComputeHash (signature)))
- return false;
-
- // verify signature
- byte[] counterSignature = cs.Signature;
-
- // change to SET OF (not [0]) as per PKCS #7 1.5
- ASN1 aa = new ASN1 (0x31);
- foreach (ASN1 a in cs.AuthenticatedAttributes)
- aa.Add (a);
- byte[] p7hash = ha.ComputeHash (aa.GetBytes ());
-
- // we need to try all certificates
- string issuer = cs.IssuerName;
- byte[] serial = cs.SerialNumber;
- foreach (X509Certificate x509 in coll) {
- if (CompareIssuerSerial (issuer, serial, x509)) {
- if (x509.PublicKey.Length > counterSignature.Length) {
- RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA;
- // we need to HACK around bad (PKCS#1 1.5) signatures made by Verisign Timestamp Service
- // and this means copying stuff into our own RSAManaged to get the required flexibility
- RSAManaged rsam = new RSAManaged ();
- rsam.ImportParameters (rsa.ExportParameters (false));
- if (PKCS1.Verify_v15 (rsam, ha, p7hash, counterSignature, true)) {
- timestampChain.LoadCertificates (coll);
- return (timestampChain.Build (x509));
- }
- }
- }
- }
- // no certificate can verify this signature!
- return false;
- }
-
- private void Reset ()
- {
- filename = null;
- entry = null;
- hash = null;
- signedHash = null;
- signingCertificate = null;
- reason = -1;
- trustedRoot = false;
- trustedTimestampRoot = false;
- signerChain.Reset ();
- timestampChain.Reset ();
- timestamp = DateTime.MinValue;
- }
- }
-}
+++ /dev/null
-2010-03-16 Jb Evain <jbevain@novell.com>
-
- * AuthenticodeBase.cs, AuthenticodeDeformatter.cs: use MOONLIGHT
- symbol to disambiguate MonoTouch and Moonlight code.
-
-2009-04-30 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeBase.cs, AuthenticodeDeformatter.cs: Remove from NET_2_1
-
-2008-01-10 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeDeformatter.cs: Use RSAManaged and the new overloaded
- PKCS1.Verify_v15 with tryNonStandardEncoding == true when verifying
- timestamping certificate signatures. Fix for #350958
-
-2007-04-26 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeBase.cs: Synch with latest Mono.Security version
- * AuthenticodeDeformatter.cs: Synch with latest Mono.Security version
-
-2006-11-08 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeDeformatter.cs: Return (find) the SigningCertificate
- even if the signature isn't verifiable. This is the behaviour required
- for 2.0.
-
-2006-06-14 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeBase.cs: Fix destination offset. Note that this works
- under MS but not under Mono.
- * AuthenticodeDeformatter.cs: Report a more useful error if the file
- hash doesn't match the signed hash.
-
-2005-03-24 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeDeformatter.cs: Don't hide the SecurityException (e.g.
- file access).
-
-2004-09-16 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeDeformatter.cs: Fixed warning (l4) for unused variables.
-
-2004-09-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeBase.cs: Merge from Mono.Security.dll. This version is
- less memory consuming (it works by 4kb blocks instead of loading the
- entire assembly).
- * AuthenticodeDeformatter.cs: Merge from Mono.Security.dll. Hash will
- only be created if the assembly is signed. Benefits from Authenticode
- Base changes.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * AuthenticodeBase.cs: In sync with Mono.Security.dll version.
- * AuthenticodeDeformatter.cs: In sync with Mono.Security.dll version.
-
-2004-04-08 Bernie Solomon <bernard@ugsolutions.com>
-
- * AuthenticodeBase.cs: Use BitConverterLE
-
-2003-12-15 Sebastien Pouliot <spouliot@videotron.ca>
-
- * AuthenticodeDeformatter.cs: Now throw a COMException for invalid
- signature. Added a SigningCertificate property (to be independant of
- the certificate collection ordering).
-
-2003-10-12 Sebastien Pouliot <spouliot@videotron.ca>
-
- * AuthenticodeBase.cs: Added from Mono.Security assembly for
- Authenticode support in X509Certificate.CreateFromSignedFile
- * AuthenticodeDeformatter.cs: Added from Mono.Security assembly for
- Authenticode support in X509Certificate.CreateFromSignedFile
+++ /dev/null
-//
-// CryptoConvert.cs - Crypto Convertion Routines
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2006 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.Globalization;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Mono.Security.Cryptography {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class CryptoConvert {
-
- private CryptoConvert ()
- {
- }
-
- static private int ToInt32LE (byte [] bytes, int offset)
- {
- return (bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset];
- }
-
- static private uint ToUInt32LE (byte [] bytes, int offset)
- {
- return (uint)((bytes [offset+3] << 24) | (bytes [offset+2] << 16) | (bytes [offset+1] << 8) | bytes [offset]);
- }
-
- static private byte [] GetBytesLE (int val)
- {
- return new byte [] {
- (byte) (val & 0xff),
- (byte) ((val >> 8) & 0xff),
- (byte) ((val >> 16) & 0xff),
- (byte) ((val >> 24) & 0xff)
- };
- }
-
- static private byte[] Trim (byte[] array)
- {
- for (int i=0; i < array.Length; i++) {
- if (array [i] != 0x00) {
- byte[] result = new byte [array.Length - i];
- Buffer.BlockCopy (array, i, result, 0, result.Length);
- return result;
- }
- }
- return null;
- }
-
- // convert the key from PRIVATEKEYBLOB to RSA
- // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/security/Security/private_key_blobs.asp
- // e.g. SNK files, PVK files
- static public RSA FromCapiPrivateKeyBlob (byte[] blob)
- {
- return FromCapiPrivateKeyBlob (blob, 0);
- }
-
- static public RSA FromCapiPrivateKeyBlob (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- RSAParameters rsap = new RSAParameters ();
- try {
- if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07)
- (blob [offset+1] != 0x02) || // Version (0x02)
- (blob [offset+2] != 0x00) || // Reserved (word)
- (blob [offset+3] != 0x00) ||
- (ToUInt32LE (blob, offset+8) != 0x32415352)) // DWORD magic = RSA2
- throw new CryptographicException ("Invalid blob header");
-
- // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
- // int algId = ToInt32LE (blob, offset+4);
-
- // DWORD bitlen
- int bitLen = ToInt32LE (blob, offset+12);
-
- // DWORD public exponent
- byte[] exp = new byte [4];
- Buffer.BlockCopy (blob, offset+16, exp, 0, 4);
- Array.Reverse (exp);
- rsap.Exponent = Trim (exp);
-
- int pos = offset+20;
- // BYTE modulus[rsapubkey.bitlen/8];
- int byteLen = (bitLen >> 3);
- rsap.Modulus = new byte [byteLen];
- Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
- Array.Reverse (rsap.Modulus);
- pos += byteLen;
-
- // BYTE prime1[rsapubkey.bitlen/16];
- int byteHalfLen = (byteLen >> 1);
- rsap.P = new byte [byteHalfLen];
- Buffer.BlockCopy (blob, pos, rsap.P, 0, byteHalfLen);
- Array.Reverse (rsap.P);
- pos += byteHalfLen;
-
- // BYTE prime2[rsapubkey.bitlen/16];
- rsap.Q = new byte [byteHalfLen];
- Buffer.BlockCopy (blob, pos, rsap.Q, 0, byteHalfLen);
- Array.Reverse (rsap.Q);
- pos += byteHalfLen;
-
- // BYTE exponent1[rsapubkey.bitlen/16];
- rsap.DP = new byte [byteHalfLen];
- Buffer.BlockCopy (blob, pos, rsap.DP, 0, byteHalfLen);
- Array.Reverse (rsap.DP);
- pos += byteHalfLen;
-
- // BYTE exponent2[rsapubkey.bitlen/16];
- rsap.DQ = new byte [byteHalfLen];
- Buffer.BlockCopy (blob, pos, rsap.DQ, 0, byteHalfLen);
- Array.Reverse (rsap.DQ);
- pos += byteHalfLen;
-
- // BYTE coefficient[rsapubkey.bitlen/16];
- rsap.InverseQ = new byte [byteHalfLen];
- Buffer.BlockCopy (blob, pos, rsap.InverseQ, 0, byteHalfLen);
- Array.Reverse (rsap.InverseQ);
- pos += byteHalfLen;
-
- // ok, this is hackish but CryptoAPI support it so...
- // note: only works because CRT is used by default
- // http://bugzilla.ximian.com/show_bug.cgi?id=57941
- rsap.D = new byte [byteLen]; // must be allocated
- if (pos + byteLen + offset <= blob.Length) {
- // BYTE privateExponent[rsapubkey.bitlen/8];
- Buffer.BlockCopy (blob, pos, rsap.D, 0, byteLen);
- Array.Reverse (rsap.D);
- }
- }
- catch (Exception e) {
- throw new CryptographicException ("Invalid blob.", e);
- }
-
-#if NET_2_1
- RSA rsa = RSA.Create ();
- rsa.ImportParameters (rsap);
-#else
- RSA rsa = null;
- try {
- rsa = RSA.Create ();
- rsa.ImportParameters (rsap);
- }
- catch (CryptographicException ce) {
- // this may cause problem when this code is run under
- // the SYSTEM identity on Windows (e.g. ASP.NET). See
- // http://bugzilla.ximian.com/show_bug.cgi?id=77559
- try {
- CspParameters csp = new CspParameters ();
- csp.Flags = CspProviderFlags.UseMachineKeyStore;
- rsa = new RSACryptoServiceProvider (csp);
- rsa.ImportParameters (rsap);
- }
- catch {
- // rethrow original, not the later, exception if this fails
- throw ce;
- }
- }
-#endif
- return rsa;
- }
-
- static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob)
- {
- return FromCapiPrivateKeyBlobDSA (blob, 0);
- }
-
- static public DSA FromCapiPrivateKeyBlobDSA (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- DSAParameters dsap = new DSAParameters ();
- try {
- if ((blob [offset] != 0x07) || // PRIVATEKEYBLOB (0x07)
- (blob [offset + 1] != 0x02) || // Version (0x02)
- (blob [offset + 2] != 0x00) || // Reserved (word)
- (blob [offset + 3] != 0x00) ||
- (ToUInt32LE (blob, offset + 8) != 0x32535344)) // DWORD magic
- throw new CryptographicException ("Invalid blob header");
-
- int bitlen = ToInt32LE (blob, offset + 12);
- int bytelen = bitlen >> 3;
- int pos = offset + 16;
-
- dsap.P = new byte [bytelen];
- Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
- Array.Reverse (dsap.P);
- pos += bytelen;
-
- dsap.Q = new byte [20];
- Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
- Array.Reverse (dsap.Q);
- pos += 20;
-
- dsap.G = new byte [bytelen];
- Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
- Array.Reverse (dsap.G);
- pos += bytelen;
-
- dsap.X = new byte [20];
- Buffer.BlockCopy (blob, pos, dsap.X, 0, 20);
- Array.Reverse (dsap.X);
- pos += 20;
-
- dsap.Counter = ToInt32LE (blob, pos);
- pos += 4;
-
- dsap.Seed = new byte [20];
- Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
- Array.Reverse (dsap.Seed);
- pos += 20;
- }
- catch (Exception e) {
- throw new CryptographicException ("Invalid blob.", e);
- }
-
-#if NET_2_1
- DSA dsa = (DSA)DSA.Create ();
- dsa.ImportParameters (dsap);
-#else
- DSA dsa = null;
- try {
- dsa = (DSA)DSA.Create ();
- dsa.ImportParameters (dsap);
- }
- catch (CryptographicException ce) {
- // this may cause problem when this code is run under
- // the SYSTEM identity on Windows (e.g. ASP.NET). See
- // http://bugzilla.ximian.com/show_bug.cgi?id=77559
- try {
- CspParameters csp = new CspParameters ();
- csp.Flags = CspProviderFlags.UseMachineKeyStore;
- dsa = new DSACryptoServiceProvider (csp);
- dsa.ImportParameters (dsap);
- }
- catch {
- // rethrow original, not the later, exception if this fails
- throw ce;
- }
- }
-#endif
- return dsa;
- }
-
- static public byte[] ToCapiPrivateKeyBlob (RSA rsa)
- {
- RSAParameters p = rsa.ExportParameters (true);
- int keyLength = p.Modulus.Length; // in bytes
- byte[] blob = new byte [20 + (keyLength << 2) + (keyLength >> 1)];
-
- blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07)
- blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
- // [2], [3] // RESERVED - Always 0
- blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
- blob [8] = 0x52; // Magic - RSA2 (ASCII in hex)
- blob [9] = 0x53;
- blob [10] = 0x41;
- blob [11] = 0x32;
-
- byte[] bitlen = GetBytesLE (keyLength << 3);
- blob [12] = bitlen [0]; // bitlen
- blob [13] = bitlen [1];
- blob [14] = bitlen [2];
- blob [15] = bitlen [3];
-
- // public exponent (DWORD)
- int pos = 16;
- int n = p.Exponent.Length;
- while (n > 0)
- blob [pos++] = p.Exponent [--n];
- // modulus
- pos = 20;
- byte[] part = p.Modulus;
- int len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
- // private key
- part = p.P;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
-
- part = p.Q;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
-
- part = p.DP;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
-
- part = p.DQ;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
-
- part = p.InverseQ;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
-
- part = p.D;
- len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
-
- return blob;
- }
-
- static public byte[] ToCapiPrivateKeyBlob (DSA dsa)
- {
- DSAParameters p = dsa.ExportParameters (true);
- int keyLength = p.P.Length; // in bytes
-
- // header + P + Q + G + X + count + seed
- byte[] blob = new byte [16 + keyLength + 20 + keyLength + 20 + 4 + 20];
-
- blob [0] = 0x07; // Type - PRIVATEKEYBLOB (0x07)
- blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
- // [2], [3] // RESERVED - Always 0
- blob [5] = 0x22; // ALGID
- blob [8] = 0x44; // Magic
- blob [9] = 0x53;
- blob [10] = 0x53;
- blob [11] = 0x32;
-
- byte[] bitlen = GetBytesLE (keyLength << 3);
- blob [12] = bitlen [0];
- blob [13] = bitlen [1];
- blob [14] = bitlen [2];
- blob [15] = bitlen [3];
-
- int pos = 16;
- byte[] part = p.P;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, keyLength);
- pos += keyLength;
-
- part = p.Q;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, 20);
- pos += 20;
-
- part = p.G;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, keyLength);
- pos += keyLength;
-
- part = p.X;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, 20);
- pos += 20;
-
- Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
- pos += 4;
-
- part = p.Seed;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, 20);
-
- return blob;
- }
-
- static public RSA FromCapiPublicKeyBlob (byte[] blob)
- {
- return FromCapiPublicKeyBlob (blob, 0);
- }
-
- static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- try {
- if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06)
- (blob [offset+1] != 0x02) || // Version (0x02)
- (blob [offset+2] != 0x00) || // Reserved (word)
- (blob [offset+3] != 0x00) ||
- (ToUInt32LE (blob, offset+8) != 0x31415352)) // DWORD magic = RSA1
- throw new CryptographicException ("Invalid blob header");
-
- // ALGID (CALG_RSA_SIGN, CALG_RSA_KEYX, ...)
- // int algId = ToInt32LE (blob, offset+4);
-
- // DWORD bitlen
- int bitLen = ToInt32LE (blob, offset+12);
-
- // DWORD public exponent
- RSAParameters rsap = new RSAParameters ();
- rsap.Exponent = new byte [3];
- rsap.Exponent [0] = blob [offset+18];
- rsap.Exponent [1] = blob [offset+17];
- rsap.Exponent [2] = blob [offset+16];
-
- int pos = offset+20;
- // BYTE modulus[rsapubkey.bitlen/8];
- int byteLen = (bitLen >> 3);
- rsap.Modulus = new byte [byteLen];
- Buffer.BlockCopy (blob, pos, rsap.Modulus, 0, byteLen);
- Array.Reverse (rsap.Modulus);
-#if NET_2_1
- RSA rsa = RSA.Create ();
- rsa.ImportParameters (rsap);
-#else
- RSA rsa = null;
- try {
- rsa = RSA.Create ();
- rsa.ImportParameters (rsap);
- }
- catch (CryptographicException) {
- // this may cause problem when this code is run under
- // the SYSTEM identity on Windows (e.g. ASP.NET). See
- // http://bugzilla.ximian.com/show_bug.cgi?id=77559
- CspParameters csp = new CspParameters ();
- csp.Flags = CspProviderFlags.UseMachineKeyStore;
- rsa = new RSACryptoServiceProvider (csp);
- rsa.ImportParameters (rsap);
- }
-#endif
- return rsa;
- }
- catch (Exception e) {
- throw new CryptographicException ("Invalid blob.", e);
- }
- }
-
- static public DSA FromCapiPublicKeyBlobDSA (byte[] blob)
- {
- return FromCapiPublicKeyBlobDSA (blob, 0);
- }
-
- static public DSA FromCapiPublicKeyBlobDSA (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- try {
- if ((blob [offset] != 0x06) || // PUBLICKEYBLOB (0x06)
- (blob [offset + 1] != 0x02) || // Version (0x02)
- (blob [offset + 2] != 0x00) || // Reserved (word)
- (blob [offset + 3] != 0x00) ||
- (ToUInt32LE (blob, offset + 8) != 0x31535344)) // DWORD magic
- throw new CryptographicException ("Invalid blob header");
-
- int bitlen = ToInt32LE (blob, offset + 12);
- DSAParameters dsap = new DSAParameters ();
- int bytelen = bitlen >> 3;
- int pos = offset + 16;
-
- dsap.P = new byte [bytelen];
- Buffer.BlockCopy (blob, pos, dsap.P, 0, bytelen);
- Array.Reverse (dsap.P);
- pos += bytelen;
-
- dsap.Q = new byte [20];
- Buffer.BlockCopy (blob, pos, dsap.Q, 0, 20);
- Array.Reverse (dsap.Q);
- pos += 20;
-
- dsap.G = new byte [bytelen];
- Buffer.BlockCopy (blob, pos, dsap.G, 0, bytelen);
- Array.Reverse (dsap.G);
- pos += bytelen;
-
- dsap.Y = new byte [bytelen];
- Buffer.BlockCopy (blob, pos, dsap.Y, 0, bytelen);
- Array.Reverse (dsap.Y);
- pos += bytelen;
-
- dsap.Counter = ToInt32LE (blob, pos);
- pos += 4;
-
- dsap.Seed = new byte [20];
- Buffer.BlockCopy (blob, pos, dsap.Seed, 0, 20);
- Array.Reverse (dsap.Seed);
- pos += 20;
-
- DSA dsa = (DSA)DSA.Create ();
- dsa.ImportParameters (dsap);
- return dsa;
- }
- catch (Exception e) {
- throw new CryptographicException ("Invalid blob.", e);
- }
- }
-
- static public byte[] ToCapiPublicKeyBlob (RSA rsa)
- {
- RSAParameters p = rsa.ExportParameters (false);
- int keyLength = p.Modulus.Length; // in bytes
- byte[] blob = new byte [20 + keyLength];
-
- blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
- blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
- // [2], [3] // RESERVED - Always 0
- blob [5] = 0x24; // ALGID - Always 00 24 00 00 (for CALG_RSA_SIGN)
- blob [8] = 0x52; // Magic - RSA1 (ASCII in hex)
- blob [9] = 0x53;
- blob [10] = 0x41;
- blob [11] = 0x31;
-
- byte[] bitlen = GetBytesLE (keyLength << 3);
- blob [12] = bitlen [0]; // bitlen
- blob [13] = bitlen [1];
- blob [14] = bitlen [2];
- blob [15] = bitlen [3];
-
- // public exponent (DWORD)
- int pos = 16;
- int n = p.Exponent.Length;
- while (n > 0)
- blob [pos++] = p.Exponent [--n];
- // modulus
- pos = 20;
- byte[] part = p.Modulus;
- int len = part.Length;
- Array.Reverse (part, 0, len);
- Buffer.BlockCopy (part, 0, blob, pos, len);
- pos += len;
- return blob;
- }
-
- static public byte[] ToCapiPublicKeyBlob (DSA dsa)
- {
- DSAParameters p = dsa.ExportParameters (false);
- int keyLength = p.P.Length; // in bytes
-
- // header + P + Q + G + Y + count + seed
- byte[] blob = new byte [16 + keyLength + 20 + keyLength + keyLength + 4 + 20];
-
- blob [0] = 0x06; // Type - PUBLICKEYBLOB (0x06)
- blob [1] = 0x02; // Version - Always CUR_BLOB_VERSION (0x02)
- // [2], [3] // RESERVED - Always 0
- blob [5] = 0x22; // ALGID
- blob [8] = 0x44; // Magic
- blob [9] = 0x53;
- blob [10] = 0x53;
- blob [11] = 0x31;
-
- byte[] bitlen = GetBytesLE (keyLength << 3);
- blob [12] = bitlen [0];
- blob [13] = bitlen [1];
- blob [14] = bitlen [2];
- blob [15] = bitlen [3];
-
- int pos = 16;
- byte[] part;
-
- part = p.P;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, keyLength);
- pos += keyLength;
-
- part = p.Q;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, 20);
- pos += 20;
-
- part = p.G;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, keyLength);
- pos += keyLength;
-
- part = p.Y;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, keyLength);
- pos += keyLength;
-
- Buffer.BlockCopy (GetBytesLE (p.Counter), 0, blob, pos, 4);
- pos += 4;
-
- part = p.Seed;
- Array.Reverse (part);
- Buffer.BlockCopy (part, 0, blob, pos, 20);
-
- return blob;
- }
-
- // PRIVATEKEYBLOB
- // PUBLICKEYBLOB
- static public RSA FromCapiKeyBlob (byte[] blob)
- {
- return FromCapiKeyBlob (blob, 0);
- }
-
- static public RSA FromCapiKeyBlob (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- switch (blob [offset]) {
- case 0x00:
- // this could be a public key inside an header
- // like "sn -e" would produce
- if (blob [offset + 12] == 0x06) {
- return FromCapiPublicKeyBlob (blob, offset + 12);
- }
- break;
- case 0x06:
- return FromCapiPublicKeyBlob (blob, offset);
- case 0x07:
- return FromCapiPrivateKeyBlob (blob, offset);
- }
- throw new CryptographicException ("Unknown blob format.");
- }
-
- static public DSA FromCapiKeyBlobDSA (byte[] blob)
- {
- return FromCapiKeyBlobDSA (blob, 0);
- }
-
- static public DSA FromCapiKeyBlobDSA (byte[] blob, int offset)
- {
- if (blob == null)
- throw new ArgumentNullException ("blob");
- if (offset >= blob.Length)
- throw new ArgumentException ("blob is too small.");
-
- switch (blob [offset]) {
- case 0x06:
- return FromCapiPublicKeyBlobDSA (blob, offset);
- case 0x07:
- return FromCapiPrivateKeyBlobDSA (blob, offset);
- }
- throw new CryptographicException ("Unknown blob format.");
- }
-
- static public byte[] ToCapiKeyBlob (AsymmetricAlgorithm keypair, bool includePrivateKey)
- {
- if (keypair == null)
- throw new ArgumentNullException ("keypair");
-
- // check between RSA and DSA (and potentially others like DH)
- if (keypair is RSA)
- return ToCapiKeyBlob ((RSA)keypair, includePrivateKey);
- else if (keypair is DSA)
- return ToCapiKeyBlob ((DSA)keypair, includePrivateKey);
- else
- return null; // TODO
- }
-
- static public byte[] ToCapiKeyBlob (RSA rsa, bool includePrivateKey)
- {
- if (rsa == null)
- throw new ArgumentNullException ("rsa");
-
- if (includePrivateKey)
- return ToCapiPrivateKeyBlob (rsa);
- else
- return ToCapiPublicKeyBlob (rsa);
- }
-
- static public byte[] ToCapiKeyBlob (DSA dsa, bool includePrivateKey)
- {
- if (dsa == null)
- throw new ArgumentNullException ("dsa");
-
- if (includePrivateKey)
- return ToCapiPrivateKeyBlob (dsa);
- else
- return ToCapiPublicKeyBlob (dsa);
- }
-
- static public string ToHex (byte[] input)
- {
- if (input == null)
- return null;
-
- StringBuilder sb = new StringBuilder (input.Length * 2);
- foreach (byte b in input) {
- sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
- }
- return sb.ToString ();
- }
-
- static private byte FromHexChar (char c)
- {
- if ((c >= 'a') && (c <= 'f'))
- return (byte) (c - 'a' + 10);
- if ((c >= 'A') && (c <= 'F'))
- return (byte) (c - 'A' + 10);
- if ((c >= '0') && (c <= '9'))
- return (byte) (c - '0');
- throw new ArgumentException ("invalid hex char");
- }
-
- static public byte[] FromHex (string hex)
- {
- if (hex == null)
- return null;
- if ((hex.Length & 0x1) == 0x1)
- throw new ArgumentException ("Length must be a multiple of 2");
-
- byte[] result = new byte [hex.Length >> 1];
- int n = 0;
- int i = 0;
- while (n < result.Length) {
- result [n] = (byte) (FromHexChar (hex [i++]) << 4);
- result [n++] += FromHexChar (hex [i++]);
- }
- return result;
- }
- }
-}
+++ /dev/null
-//
-// Mono.Security.Cryptography.CryptoTools
-// Shared class for common cryptographic functionalities
-//
-// Authors:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004, 2008 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 {
-
-#if INSIDE_CORLIB || INSIDE_SYSCORE
- internal
-#else
- public
-#endif
- sealed class KeyBuilder {
-
- static private RandomNumberGenerator rng;
-
- private KeyBuilder ()
- {
- }
-
- static RandomNumberGenerator Rng {
- get {
- if (rng == null)
- rng = RandomNumberGenerator.Create ();
- return rng;
- }
- }
-
- static public byte[] Key (int size)
- {
- byte[] key = new byte [size];
- Rng.GetBytes (key);
- return key;
- }
-
- static public byte[] IV (int size)
- {
- byte[] iv = new byte [size];
- Rng.GetBytes (iv);
- return iv;
- }
- }
-
- // Process an array as a sequence of blocks
-#if INSIDE_CORLIB || INSIDE_SYSCORE
- internal
-#else
- public
-#endif
- class BlockProcessor {
- private ICryptoTransform transform;
- private byte[] block;
- private int blockSize; // in bytes (not in bits)
- private int blockCount;
-
- public BlockProcessor (ICryptoTransform transform)
- : this (transform, transform.InputBlockSize) {}
-
- // some Transforms (like HashAlgorithm descendant) return 1 for
- // block size (which isn't their real internal block size)
- public BlockProcessor (ICryptoTransform transform, int blockSize)
- {
- this.transform = transform;
- this.blockSize = blockSize;
- block = new byte [blockSize];
- }
-
- ~BlockProcessor ()
- {
- // zeroize our block (so we don't retain any information)
- Array.Clear (block, 0, blockSize);
- }
-
- public void Initialize ()
- {
- Array.Clear (block, 0, blockSize);
- blockCount = 0;
- }
-
- public void Core (byte[] rgb)
- {
- Core (rgb, 0, rgb.Length);
- }
-
- public void Core (byte[] rgb, int ib, int cb)
- {
- // 1. fill the rest of the "block"
- int n = System.Math.Min (blockSize - blockCount, cb);
- Buffer.BlockCopy (rgb, ib, block, blockCount, n);
- blockCount += n;
-
- // 2. if block is full then transform it
- if (blockCount == blockSize) {
- transform.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++) {
- transform.TransformBlock (rgb, n + ib, blockSize, block, 0);
- n += blockSize;
- }
-
- // 4. if data is still present fill the "block" with the remainder
- blockCount = cb - n;
- if (blockCount > 0)
- Buffer.BlockCopy (rgb, n + ib, block, 0, blockCount);
- }
- }
-
- public byte[] Final ()
- {
- return transform.TransformFinalBlock (block, 0, blockCount);
- }
- }
-}
+++ /dev/null
-//
-// KeyPairPersistence.cs: Keypair persistence
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.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.Globalization;
-using System.IO;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Security;
-using System.Security.Cryptography;
-using System.Security.Permissions;
-using System.Text;
-
-using Mono.Xml;
-
-namespace Mono.Security.Cryptography {
-
- /* File name
- * [type][unique name][key number].xml
- *
- * where
- * type CspParameters.ProviderType
- * unique name A unique name for the keypair, which is
- * a. default (for a provider default keypair)
- * b. a GUID derived from
- * i. random if no container name was
- * specified at generation time
- * ii. the MD5 hash of the container
- * name (CspParameters.KeyContainerName)
- * key number CspParameters.KeyNumber
- *
- * File format
- * <KeyPair>
- * <Properties>
- * <Provider Name="" Type=""/>
- * <Container Name=""/>
- * </Properties>
- * <KeyValue Id="">
- * RSAKeyValue, DSAKeyValue ...
- * </KeyValue>
- * </KeyPair>
- */
-
- /* NOTES
- *
- * - There's NO confidentiality / integrity built in this
- * persistance mechanism. The container directories (both user and
- * machine) are created with restrited ACL. The ACL is also checked
- * when a key is accessed (so totally public keys won't be used).
- * see /mono/mono/metadata/security.c for implementation
- *
- * - As we do not use CSP we limit ourselves to provider types (not
- * names). This means that for a same type and container type, but
- * two different provider names) will return the same keypair. This
- * should work as CspParameters always requires a csp type in its
- * constructors.
- *
- * - Assert (CAS) are used so only the OS permission will limit access
- * to the keypair files. I.e. this will work even in high-security
- * scenarios where users do not have access to file system (e.g. web
- * application). We can allow this because the filename used is
- * TOTALLY under our control (no direct user input is used).
- *
- * - You CAN'T changes properties of the keypair once it's been
- * created (saved). You must remove the container than save it
- * back. This is the same behaviour as CSP under Windows.
- */
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class KeyPairPersistence {
-
- private static bool _userPathExists; // check at 1st use
- private static string _userPath;
-
- private static bool _machinePathExists; // check at 1st use
- private static string _machinePath;
-
- private CspParameters _params;
- private string _keyvalue;
- private string _filename;
- private string _container;
-
- // constructors
-
- public KeyPairPersistence (CspParameters parameters)
- : this (parameters, null)
- {
- }
-
- public KeyPairPersistence (CspParameters parameters, string keyPair)
- {
- if (parameters == null)
- throw new ArgumentNullException ("parameters");
-
- _params = Copy (parameters);
- _keyvalue = keyPair;
- }
-
- // properties
-
- public string Filename {
- get {
- if (_filename == null) {
- _filename = String.Format (CultureInfo.InvariantCulture,
- "[{0}][{1}][{2}].xml",
- _params.ProviderType,
- this.ContainerName,
- _params.KeyNumber);
- if (UseMachineKeyStore)
- _filename = Path.Combine (MachinePath, _filename);
- else
- _filename = Path.Combine (UserPath, _filename);
- }
- return _filename;
- }
- }
-
- public string KeyValue {
- get { return _keyvalue; }
- set {
- if (this.CanChange)
- _keyvalue = value;
- }
- }
-
- // return a (read-only) copy
- public CspParameters Parameters {
- get { return Copy (_params); }
- }
-
- // methods
-
- public bool Load ()
- {
- // see NOTES
-// FIXME new FileIOPermission (FileIOPermissionAccess.Read, this.Filename).Assert ();
-
- bool result = File.Exists (this.Filename);
- if (result) {
- using (StreamReader sr = File.OpenText (this.Filename)) {
- FromXml (sr.ReadToEnd ());
- }
- }
- return result;
- }
-
- public void Save ()
- {
- // see NOTES
-// FIXME new FileIOPermission (FileIOPermissionAccess.Write, this.Filename).Assert ();
-
- using (FileStream fs = File.Open (this.Filename, FileMode.Create)) {
- StreamWriter sw = new StreamWriter (fs, Encoding.UTF8);
- sw.Write (this.ToXml ());
- sw.Close ();
- }
- // apply protection to newly created files
- if (UseMachineKeyStore)
- ProtectMachine (Filename);
- else
- ProtectUser (Filename);
- }
-
- public void Remove ()
- {
- // see NOTES
-// FIXME new FileIOPermission (FileIOPermissionAccess.Write, this.Filename).Assert ();
-
- File.Delete (this.Filename);
- // it's now possible to change the keypair un the container
- }
-
- // private static stuff
-
- static object lockobj = new object ();
-
- private static string UserPath {
- get {
- lock (lockobj) {
- if ((_userPath == null) || (!_userPathExists)) {
- _userPath = Path.Combine (
- Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
- ".mono");
- _userPath = Path.Combine (_userPath, "keypairs");
-
- _userPathExists = Directory.Exists (_userPath);
- if (!_userPathExists) {
- try {
- Directory.CreateDirectory (_userPath);
- ProtectUser (_userPath);
- _userPathExists = true;
- }
- catch (Exception e) {
- string msg = Locale.GetText ("Could not create user key store '{0}'.");
- throw new CryptographicException (String.Format (msg, _userPath), e);
- }
- }
- }
- }
- // is it properly protected ?
- if (!IsUserProtected (_userPath)) {
- string msg = Locale.GetText ("Improperly protected user's key pairs in '{0}'.");
- throw new CryptographicException (String.Format (msg, _userPath));
- }
- return _userPath;
- }
- }
-
- private static string MachinePath {
- get {
- lock (lockobj) {
- if ((_machinePath == null) || (!_machinePathExists)) {
- _machinePath = Path.Combine (
- Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData),
- ".mono");
- _machinePath = Path.Combine (_machinePath, "keypairs");
-
- _machinePathExists = Directory.Exists (_machinePath);
- if (!_machinePathExists) {
- try {
- Directory.CreateDirectory (_machinePath);
- ProtectMachine (_machinePath);
- _machinePathExists = true;
- }
- catch (Exception e) {
- string msg = Locale.GetText ("Could not create machine key store '{0}'.");
- throw new CryptographicException (String.Format (msg, _machinePath), e);
- }
- }
- }
- }
- // is it properly protected ?
- if (!IsMachineProtected (_machinePath)) {
- string msg = Locale.GetText ("Improperly protected machine's key pairs in '{0}'.");
- throw new CryptographicException (String.Format (msg, _machinePath));
- }
- return _machinePath;
- }
- }
-
-#if INSIDE_CORLIB
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern bool _CanSecure (string root);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern bool _ProtectUser (string path);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern bool _ProtectMachine (string path);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern bool _IsUserProtected (string path);
-
- [MethodImplAttribute (MethodImplOptions.InternalCall)]
- internal static extern bool _IsMachineProtected (string path);
-#else
- // Mono.Security.dll assembly can't use the internal
- // call (and still run with other runtimes)
-
- // Note: Class is only available in Mono.Security.dll as
- // a management helper (e.g. build a GUI app)
-
- internal static bool _CanSecure (string root)
- {
- return true;
- }
-
- internal static bool _ProtectUser (string path)
- {
- return true;
- }
-
- internal static bool _ProtectMachine (string path)
- {
- return true;
- }
-
- internal static bool _IsUserProtected (string path)
- {
- return true;
- }
-
- internal static bool _IsMachineProtected (string path)
- {
- return true;
- }
-#endif
- // private stuff
-
- private static bool CanSecure (string path)
- {
- // we assume POSIX filesystems can always be secured
-
- // check for Unix platforms - see FAQ for more details
- // http://www.mono-project.com/FAQ:_Technical#How_to_detect_the_execution_platform_.3F
- int platform = (int) Environment.OSVersion.Platform;
- if ((platform == 4) || (platform == 128) || (platform == 6))
- return true;
-
- // while we ask the runtime for Windows OS
- return _CanSecure (Path.GetPathRoot (path));
- }
-
- private static bool ProtectUser (string path)
- {
- // we cannot protect on some filsystem (like FAT)
- if (CanSecure (path)) {
- return _ProtectUser (path);
- }
- // but Mono still needs to run on them :(
- return true;
- }
-
- private static bool ProtectMachine (string path)
- {
- // we cannot protect on some filsystem (like FAT)
- if (CanSecure (path)) {
- return _ProtectMachine (path);
- }
- // but Mono still needs to run on them :(
- return true;
- }
-
- private static bool IsUserProtected (string path)
- {
- // we cannot protect on some filsystem (like FAT)
- if (CanSecure (path)) {
- return _IsUserProtected (path);
- }
- // but Mono still needs to run on them :(
- return true;
- }
-
- private static bool IsMachineProtected (string path)
- {
- // we cannot protect on some filsystem (like FAT)
- if (CanSecure (path)) {
- return _IsMachineProtected (path);
- }
- // but Mono still needs to run on them :(
- return true;
- }
-
- private bool CanChange {
- get { return (_keyvalue == null); }
- }
-
- private bool UseDefaultKeyContainer {
- get { return ((_params.Flags & CspProviderFlags.UseDefaultKeyContainer) == CspProviderFlags.UseDefaultKeyContainer); }
- }
-
- private bool UseMachineKeyStore {
- get { return ((_params.Flags & CspProviderFlags.UseMachineKeyStore) == CspProviderFlags.UseMachineKeyStore); }
- }
-
- private string ContainerName {
- get {
- if (_container == null) {
- if (UseDefaultKeyContainer) {
- // easy to spot
- _container = "default";
- }
- else if ((_params.KeyContainerName == null) || (_params.KeyContainerName.Length == 0)) {
- _container = Guid.NewGuid ().ToString ();
- }
- else {
- // we don't want to trust the key container name as we don't control it
- // anyway some characters may not be compatible with the file system
- byte[] data = Encoding.UTF8.GetBytes (_params.KeyContainerName);
- // Note: We use MD5 as it is faster than SHA1 and has the same length
- // as a GUID. Recent problems found in MD5 (like collisions) aren't a
- // problem in this case.
- MD5 hash = MD5.Create ();
- byte[] result = hash.ComputeHash (data);
- _container = new Guid (result).ToString ();
- }
- }
- return _container;
- }
- }
-
- // we do not want any changes after receiving the csp informations
- private CspParameters Copy (CspParameters p)
- {
- CspParameters copy = new CspParameters (p.ProviderType, p.ProviderName, p.KeyContainerName);
- copy.KeyNumber = p.KeyNumber;
- copy.Flags = p.Flags;
- return copy;
- }
-
- private void FromXml (string xml)
- {
- SecurityParser sp = new SecurityParser ();
- sp.LoadXml (xml);
-
- SecurityElement root = sp.ToXml ();
- if (root.Tag == "KeyPair") {
- //SecurityElement prop = root.SearchForChildByTag ("Properties");
- SecurityElement keyv = root.SearchForChildByTag ("KeyValue");
- if (keyv.Children.Count > 0)
- _keyvalue = keyv.Children [0].ToString ();
- // Note: we do not read other stuff because
- // it can't be changed after key creation
- }
- }
-
- private string ToXml ()
- {
- // note: we do not use SecurityElement here because the
- // keypair is a XML string (requiring parsing)
- StringBuilder xml = new StringBuilder ();
- xml.AppendFormat ("<KeyPair>{0}\t<Properties>{0}\t\t<Provider ", Environment.NewLine);
- if ((_params.ProviderName != null) && (_params.ProviderName.Length != 0)) {
- xml.AppendFormat ("Name=\"{0}\" ", _params.ProviderName);
- }
- xml.AppendFormat ("Type=\"{0}\" />{1}\t\t<Container ", _params.ProviderType, Environment.NewLine);
- xml.AppendFormat ("Name=\"{0}\" />{1}\t</Properties>{1}\t<KeyValue", this.ContainerName, Environment.NewLine);
- if (_params.KeyNumber != -1) {
- xml.AppendFormat (" Id=\"{0}\" ", _params.KeyNumber);
- }
- xml.AppendFormat (">{1}\t\t{0}{1}\t</KeyValue>{1}</KeyPair>{1}", this.KeyValue, Environment.NewLine);
- return xml.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// PKCS1.cs - Implements PKCS#1 primitives.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.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. PKCS#1: RSA Cryptography Standard
- // http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/index.html
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class PKCS1 {
-
- private PKCS1 ()
- {
- }
-
- private static bool Compare (byte[] array1, byte[] array2)
- {
- bool result = (array1.Length == array2.Length);
- if (result) {
- for (int i=0; i < array1.Length; i++)
- if (array1[i] != array2[i])
- return false;
- }
- return result;
- }
-
- private static byte[] xor (byte[] array1, byte[] array2)
- {
- byte[] result = new byte [array1.Length];
- for (int i=0; i < result.Length; i++)
- result[i] = (byte) (array1[i] ^ array2[i]);
- return result;
- }
-
- private static byte[] emptySHA1 = { 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, 0xaf, 0xd8, 0x07, 0x09 };
- private static byte[] emptySHA256 = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 };
- private static byte[] emptySHA384 = { 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b };
- private static byte[] emptySHA512 = { 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e };
-
- private static byte[] GetEmptyHash (HashAlgorithm hash)
- {
- if (hash is SHA1)
- return emptySHA1;
- else if (hash is SHA256)
- return emptySHA256;
- else if (hash is SHA384)
- return emptySHA384;
- else if (hash is SHA512)
- return emptySHA512;
- else
- return hash.ComputeHash ((byte[])null);
- }
-
- // PKCS #1 v.2.1, Section 4.1
- // I2OSP converts a non-negative integer to an octet string of a specified length.
- public static byte[] I2OSP (int x, int size)
- {
- byte[] array = BitConverterLE.GetBytes (x);
- Array.Reverse (array, 0, array.Length);
- return I2OSP (array, size);
- }
-
- public static byte[] I2OSP (byte[] x, int size)
- {
- byte[] result = new byte [size];
- Buffer.BlockCopy (x, 0, result, (result.Length - x.Length), x.Length);
- return result;
- }
-
- // PKCS #1 v.2.1, Section 4.2
- // OS2IP converts an octet string to a nonnegative integer.
- public static byte[] OS2IP (byte[] x)
- {
- int i = 0;
- while ((x [i++] == 0x00) && (i < x.Length)) {
- // confuse compiler into reporting a warning with {}
- }
- i--;
- if (i > 0) {
- byte[] result = new byte [x.Length - i];
- Buffer.BlockCopy (x, i, result, 0, result.Length);
- return result;
- }
- else
- return x;
- }
-
- // PKCS #1 v.2.1, Section 5.1.1
- public static byte[] RSAEP (RSA rsa, byte[] m)
- {
- // c = m^e mod n
- return rsa.EncryptValue (m);
- }
-
- // PKCS #1 v.2.1, Section 5.1.2
- public static byte[] RSADP (RSA rsa, byte[] c)
- {
- // m = c^d mod n
- // Decrypt value may apply CRT optimizations
- return rsa.DecryptValue (c);
- }
-
- // PKCS #1 v.2.1, Section 5.2.1
- public static byte[] RSASP1 (RSA rsa, byte[] m)
- {
- // first form: s = m^d mod n
- // Decrypt value may apply CRT optimizations
- return rsa.DecryptValue (m);
- }
-
- // PKCS #1 v.2.1, Section 5.2.2
- public static byte[] RSAVP1 (RSA rsa, byte[] s)
- {
- // m = s^e mod n
- return rsa.EncryptValue (s);
- }
-
- // PKCS #1 v.2.1, Section 7.1.1
- // RSAES-OAEP-ENCRYPT ((n, e), M, L)
- public static byte[] Encrypt_OAEP (RSA rsa, HashAlgorithm hash, RandomNumberGenerator rng, byte[] M)
- {
- int size = rsa.KeySize / 8;
- int hLen = hash.HashSize / 8;
- if (M.Length > size - 2 * hLen - 2)
- throw new CryptographicException ("message too long");
- // empty label L SHA1 hash
- byte[] lHash = GetEmptyHash (hash);
- int PSLength = (size - M.Length - 2 * hLen - 2);
- // DB = lHash || PS || 0x01 || M
- byte[] DB = new byte [lHash.Length + PSLength + 1 + M.Length];
- Buffer.BlockCopy (lHash, 0, DB, 0, lHash.Length);
- DB [(lHash.Length + PSLength)] = 0x01;
- Buffer.BlockCopy (M, 0, DB, (DB.Length - M.Length), M.Length);
-
- byte[] seed = new byte [hLen];
- rng.GetBytes (seed);
-
- byte[] dbMask = MGF1 (hash, seed, size - hLen - 1);
- byte[] maskedDB = xor (DB, dbMask);
- byte[] seedMask = MGF1 (hash, maskedDB, hLen);
- byte[] maskedSeed = xor (seed, seedMask);
- // EM = 0x00 || maskedSeed || maskedDB
- byte[] EM = new byte [maskedSeed.Length + maskedDB.Length + 1];
- Buffer.BlockCopy (maskedSeed, 0, EM, 1, maskedSeed.Length);
- Buffer.BlockCopy (maskedDB, 0, EM, maskedSeed.Length + 1, maskedDB.Length);
-
- byte[] m = OS2IP (EM);
- byte[] c = RSAEP (rsa, m);
- return I2OSP (c, size);
- }
-
- // PKCS #1 v.2.1, Section 7.1.2
- // RSAES-OAEP-DECRYPT (K, C, L)
- public static byte[] Decrypt_OAEP (RSA rsa, HashAlgorithm hash, byte[] C)
- {
- int size = rsa.KeySize / 8;
- int hLen = hash.HashSize / 8;
- if ((size < (2 * hLen + 2)) || (C.Length != size))
- throw new CryptographicException ("decryption error");
-
- byte[] c = OS2IP (C);
- byte[] m = RSADP (rsa, c);
- byte[] EM = I2OSP (m, size);
-
- // split EM = Y || maskedSeed || maskedDB
- byte[] maskedSeed = new byte [hLen];
- Buffer.BlockCopy (EM, 1, maskedSeed, 0, maskedSeed.Length);
- byte[] maskedDB = new byte [size - hLen - 1];
- Buffer.BlockCopy (EM, (EM.Length - maskedDB.Length), maskedDB, 0, maskedDB.Length);
-
- byte[] seedMask = MGF1 (hash, maskedDB, hLen);
- byte[] seed = xor (maskedSeed, seedMask);
- byte[] dbMask = MGF1 (hash, seed, size - hLen - 1);
- byte[] DB = xor (maskedDB, dbMask);
-
- byte[] lHash = GetEmptyHash (hash);
- // split DB = lHash' || PS || 0x01 || M
- byte[] dbHash = new byte [lHash.Length];
- Buffer.BlockCopy (DB, 0, dbHash, 0, dbHash.Length);
- bool h = Compare (lHash, dbHash);
-
- // find separator 0x01
- int nPos = lHash.Length;
- while (DB[nPos] == 0)
- nPos++;
-
- int Msize = DB.Length - nPos - 1;
- byte[] M = new byte [Msize];
- Buffer.BlockCopy (DB, (nPos + 1), M, 0, Msize);
-
- // we could have returned EM[0] sooner but would be helping a timing attack
- if ((EM[0] != 0) || (!h) || (DB[nPos] != 0x01))
- return null;
- return M;
- }
-
- // PKCS #1 v.2.1, Section 7.2.1
- // RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M)
- public static byte[] Encrypt_v15 (RSA rsa, RandomNumberGenerator rng, byte[] M)
- {
- int size = rsa.KeySize / 8;
- if (M.Length > size - 11)
- throw new CryptographicException ("message too long");
- int PSLength = System.Math.Max (8, (size - M.Length - 3));
- byte[] PS = new byte [PSLength];
- rng.GetNonZeroBytes (PS);
- byte[] EM = new byte [size];
- EM [1] = 0x02;
- Buffer.BlockCopy (PS, 0, EM, 2, PSLength);
- Buffer.BlockCopy (M, 0, EM, (size - M.Length), M.Length);
-
- byte[] m = OS2IP (EM);
- byte[] c = RSAEP (rsa, m);
- byte[] C = I2OSP (c, size);
- return C;
- }
-
- // PKCS #1 v.2.1, Section 7.2.2
- // RSAES-PKCS1-V1_5-DECRYPT (K, C)
- public static byte[] Decrypt_v15 (RSA rsa, byte[] C)
- {
- int size = rsa.KeySize >> 3; // div by 8
- if ((size < 11) || (C.Length > size))
- throw new CryptographicException ("decryption error");
- byte[] c = OS2IP (C);
- byte[] m = RSADP (rsa, c);
- byte[] EM = I2OSP (m, size);
-
- if ((EM [0] != 0x00) || (EM [1] != 0x02))
- return null;
-
- int mPos = 10;
- // PS is a minimum of 8 bytes + 2 bytes for header
- while ((EM [mPos] != 0x00) && (mPos < EM.Length))
- mPos++;
- if (EM [mPos] != 0x00)
- return null;
- mPos++;
- byte[] M = new byte [EM.Length - mPos];
- Buffer.BlockCopy (EM, mPos, M, 0, M.Length);
- return M;
- }
-
- // PKCS #1 v.2.1, Section 8.2.1
- // RSASSA-PKCS1-V1_5-SIGN (K, M)
- public static byte[] Sign_v15 (RSA rsa, HashAlgorithm hash, byte[] hashValue)
- {
- int size = (rsa.KeySize >> 3); // div 8
- byte[] EM = Encode_v15 (hash, hashValue, size);
- byte[] m = OS2IP (EM);
- byte[] s = RSASP1 (rsa, m);
- byte[] S = I2OSP (s, size);
- return S;
- }
-
- // PKCS #1 v.2.1, Section 8.2.2
- // RSASSA-PKCS1-V1_5-VERIFY ((n, e), M, S)
- public static bool Verify_v15 (RSA rsa, HashAlgorithm hash, byte[] hashValue, byte[] signature)
- {
- return Verify_v15 (rsa, hash, hashValue, signature, false);
- }
-
- // DO NOT USE WITHOUT A VERY GOOD REASON
- public static bool Verify_v15 (RSA rsa, HashAlgorithm hash, byte [] hashValue, byte [] signature, bool tryNonStandardEncoding)
- {
- int size = (rsa.KeySize >> 3); // div 8
- byte[] s = OS2IP (signature);
- byte[] m = RSAVP1 (rsa, s);
- byte[] EM2 = I2OSP (m, size);
- byte[] EM = Encode_v15 (hash, hashValue, size);
- bool result = Compare (EM, EM2);
- if (result || !tryNonStandardEncoding)
- return result;
-
- // NOTE: some signatures don't include the hash OID (pretty lame but real)
- // and compatible with MS implementation. E.g. Verisign Authenticode Timestamps
-
- // we're making this "as safe as possible"
- if ((EM2 [0] != 0x00) || (EM2 [1] != 0x01))
- return false;
- int i;
- for (i = 2; i < EM2.Length - hashValue.Length - 1; i++) {
- if (EM2 [i] != 0xFF)
- return false;
- }
- if (EM2 [i++] != 0x00)
- return false;
-
- byte [] decryptedHash = new byte [hashValue.Length];
- Buffer.BlockCopy (EM2, i, decryptedHash, 0, decryptedHash.Length);
- return Compare (decryptedHash, hashValue);
- }
-
- // PKCS #1 v.2.1, Section 9.2
- // EMSA-PKCS1-v1_5-Encode
- public static byte[] Encode_v15 (HashAlgorithm hash, byte[] hashValue, int emLength)
- {
- if (hashValue.Length != (hash.HashSize >> 3))
- throw new CryptographicException ("bad hash length for " + hash.ToString ());
-
- // DigestInfo ::= SEQUENCE {
- // digestAlgorithm AlgorithmIdentifier,
- // digest OCTET STRING
- // }
-
- byte[] t = null;
-
- string oid = CryptoConfig.MapNameToOID (hash.ToString ());
- if (oid != null)
- {
- ASN1 digestAlgorithm = new ASN1 (0x30);
- digestAlgorithm.Add (new ASN1 (CryptoConfig.EncodeOID (oid)));
- digestAlgorithm.Add (new ASN1 (0x05)); // NULL
- ASN1 digest = new ASN1 (0x04, hashValue);
- ASN1 digestInfo = new ASN1 (0x30);
- digestInfo.Add (digestAlgorithm);
- digestInfo.Add (digest);
-
- t = digestInfo.GetBytes ();
- }
- else
- {
- // There are no valid OID, in this case t = hashValue
- // This is the case of the MD5SHA hash algorithm
- t = hashValue;
- }
-
- Buffer.BlockCopy (hashValue, 0, t, t.Length - hashValue.Length, hashValue.Length);
-
- int PSLength = System.Math.Max (8, emLength - t.Length - 3);
- // PS = PSLength of 0xff
-
- // EM = 0x00 | 0x01 | PS | 0x00 | T
- byte[] EM = new byte [PSLength + t.Length + 3];
- EM [1] = 0x01;
- for (int i=2; i < PSLength + 2; i++)
- EM[i] = 0xff;
- Buffer.BlockCopy (t, 0, EM, PSLength + 3, t.Length);
-
- return EM;
- }
-
- // PKCS #1 v.2.1, Section B.2.1
- public static byte[] MGF1 (HashAlgorithm hash, byte[] mgfSeed, int maskLen)
- {
- // 1. If maskLen > 2^32 hLen, output "mask too long" and stop.
- // easy - this is impossible by using a int (31bits) as parameter ;-)
- // BUT with a signed int we do have to check for negative values!
- if (maskLen < 0)
- throw new OverflowException();
-
- int mgfSeedLength = mgfSeed.Length;
- int hLen = (hash.HashSize >> 3); // from bits to bytes
- int iterations = (maskLen / hLen);
- if (maskLen % hLen != 0)
- iterations++;
- // 2. Let T be the empty octet string.
- byte[] T = new byte [iterations * hLen];
-
- byte[] toBeHashed = new byte [mgfSeedLength + 4];
- int pos = 0;
- // 3. For counter from 0 to \ceil (maskLen / hLen) - 1, do the following:
- for (int counter = 0; counter < iterations; counter++) {
- // a. Convert counter to an octet string C of length 4 octets
- byte[] C = I2OSP (counter, 4);
-
- // b. Concatenate the hash of the seed mgfSeed and C to the octet string T:
- // T = T || Hash (mgfSeed || C)
- Buffer.BlockCopy (mgfSeed, 0, toBeHashed, 0, mgfSeedLength);
- Buffer.BlockCopy (C, 0, toBeHashed, mgfSeedLength, 4);
- byte[] output = hash.ComputeHash (toBeHashed);
- Buffer.BlockCopy (output, 0, T, pos, hLen);
- pos += hLen;
- }
-
- // 4. Output the leading maskLen octets of T as the octet string mask.
- byte[] mask = new byte [maskLen];
- Buffer.BlockCopy (T, 0, mask, 0, maskLen);
- return mask;
- }
- }
-}
+++ /dev/null
-//
-// PKCS8.cs: PKCS #8 - Private-Key Information Syntax Standard
-// ftp://ftp.rsasecurity.com/pub/pkcs/doc/pkcs-8.doc
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2006 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.Collections;
-using System.Security.Cryptography;
-using System.Text;
-
-using Mono.Security.X509;
-
-namespace Mono.Security.Cryptography {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class PKCS8 {
-
- public enum KeyInfo {
- PrivateKey,
- EncryptedPrivateKey,
- Unknown
- }
-
- private PKCS8 ()
- {
- }
-
- static public KeyInfo GetType (byte[] data)
- {
- if (data == null)
- throw new ArgumentNullException ("data");
-
- KeyInfo ki = KeyInfo.Unknown;
- try {
- ASN1 top = new ASN1 (data);
- if ((top.Tag == 0x30) && (top.Count > 0)) {
- ASN1 firstLevel = top [0];
- switch (firstLevel.Tag) {
- case 0x02:
- ki = KeyInfo.PrivateKey;
- break;
- case 0x30:
- ki = KeyInfo.EncryptedPrivateKey;
- break;
- }
- }
- }
- catch {
- throw new CryptographicException ("invalid ASN.1 data");
- }
- return ki;
- }
-
- /*
- * PrivateKeyInfo ::= SEQUENCE {
- * version Version,
- * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier,
- * privateKey PrivateKey,
- * attributes [0] IMPLICIT Attributes OPTIONAL
- * }
- *
- * Version ::= INTEGER
- *
- * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * PrivateKey ::= OCTET STRING
- *
- * Attributes ::= SET OF Attribute
- */
- public class PrivateKeyInfo {
-
- private int _version;
- private string _algorithm;
- private byte[] _key;
- private ArrayList _list;
-
- public PrivateKeyInfo ()
- {
- _version = 0;
- _list = new ArrayList ();
- }
-
- public PrivateKeyInfo (byte[] data) : this ()
- {
- Decode (data);
- }
-
- // properties
-
- public string Algorithm {
- get { return _algorithm; }
- set { _algorithm = value; }
- }
-
- public ArrayList Attributes {
- get { return _list; }
- }
-
- public byte[] PrivateKey {
- get {
- if (_key == null)
- return null;
- return (byte[]) _key.Clone ();
- }
- set {
- if (value == null)
- throw new ArgumentNullException ("PrivateKey");
- _key = (byte[]) value.Clone ();
- }
- }
-
- public int Version {
- get { return _version; }
- set {
- if (value < 0)
- throw new ArgumentOutOfRangeException ("negative version");
- _version = value;
- }
- }
-
- // methods
-
- private void Decode (byte[] data)
- {
- ASN1 privateKeyInfo = new ASN1 (data);
- if (privateKeyInfo.Tag != 0x30)
- throw new CryptographicException ("invalid PrivateKeyInfo");
-
- ASN1 version = privateKeyInfo [0];
- if (version.Tag != 0x02)
- throw new CryptographicException ("invalid version");
- _version = version.Value [0];
-
- ASN1 privateKeyAlgorithm = privateKeyInfo [1];
- if (privateKeyAlgorithm.Tag != 0x30)
- throw new CryptographicException ("invalid algorithm");
-
- ASN1 algorithm = privateKeyAlgorithm [0];
- if (algorithm.Tag != 0x06)
- throw new CryptographicException ("missing algorithm OID");
- _algorithm = ASN1Convert.ToOid (algorithm);
-
- ASN1 privateKey = privateKeyInfo [2];
- _key = privateKey.Value;
-
- // attributes [0] IMPLICIT Attributes OPTIONAL
- if (privateKeyInfo.Count > 3) {
- ASN1 attributes = privateKeyInfo [3];
- for (int i=0; i < attributes.Count; i++) {
- _list.Add (attributes [i]);
- }
- }
- }
-
- public byte[] GetBytes ()
- {
- ASN1 privateKeyAlgorithm = new ASN1 (0x30);
- privateKeyAlgorithm.Add (ASN1Convert.FromOid (_algorithm));
- privateKeyAlgorithm.Add (new ASN1 (0x05)); // ASN.1 NULL
-
- ASN1 pki = new ASN1 (0x30);
- pki.Add (new ASN1 (0x02, new byte [1] { (byte) _version }));
- pki.Add (privateKeyAlgorithm);
- pki.Add (new ASN1 (0x04, _key));
-
- if (_list.Count > 0) {
- ASN1 attributes = new ASN1 (0xA0);
- foreach (ASN1 attribute in _list) {
- attributes.Add (attribute);
- }
- pki.Add (attributes);
- }
-
- return pki.GetBytes ();
- }
-
- // static methods
-
- static private byte[] RemoveLeadingZero (byte[] bigInt)
- {
- int start = 0;
- int length = bigInt.Length;
- if (bigInt [0] == 0x00) {
- start = 1;
- length--;
- }
- byte[] bi = new byte [length];
- Buffer.BlockCopy (bigInt, start, bi, 0, length);
- return bi;
- }
-
- static private byte[] Normalize (byte[] bigInt, int length)
- {
- if (bigInt.Length == length)
- return bigInt;
- else if (bigInt.Length > length)
- return RemoveLeadingZero (bigInt);
- else {
- // pad with 0
- byte[] bi = new byte [length];
- Buffer.BlockCopy (bigInt, 0, bi, (length - bigInt.Length), bigInt.Length);
- return bi;
- }
- }
-
- /*
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- static public RSA DecodeRSA (byte[] keypair)
- {
- ASN1 privateKey = new ASN1 (keypair);
- if (privateKey.Tag != 0x30)
- throw new CryptographicException ("invalid private key format");
-
- ASN1 version = privateKey [0];
- if (version.Tag != 0x02)
- throw new CryptographicException ("missing version");
-
- if (privateKey.Count < 9)
- throw new CryptographicException ("not enough key parameters");
-
- RSAParameters param = new RSAParameters ();
- // note: MUST remove leading 0 - else MS wont import the key
- param.Modulus = RemoveLeadingZero (privateKey [1].Value);
- int keysize = param.Modulus.Length;
- int keysize2 = (keysize >> 1); // half-size
- // size must be normalized - else MS wont import the key
- param.D = Normalize (privateKey [3].Value, keysize);
- param.DP = Normalize (privateKey [6].Value, keysize2);
- param.DQ = Normalize (privateKey [7].Value, keysize2);
- param.Exponent = RemoveLeadingZero (privateKey [2].Value);
- param.InverseQ = Normalize (privateKey [8].Value, keysize2);
- param.P = Normalize (privateKey [4].Value, keysize2);
- param.Q = Normalize (privateKey [5].Value, keysize2);
- RSA rsa = null;
- try {
- rsa = RSA.Create ();
- rsa.ImportParameters (param);
- }
- catch (CryptographicException) {
- // this may cause problem when this code is run under
- // the SYSTEM identity on Windows (e.g. ASP.NET). See
- // http://bugzilla.ximian.com/show_bug.cgi?id=77559
- CspParameters csp = new CspParameters ();
- csp.Flags = CspProviderFlags.UseMachineKeyStore;
- rsa = new RSACryptoServiceProvider (csp);
- rsa.ImportParameters (param);
- }
- return rsa;
- }
-
- /*
- * RSAPrivateKey ::= SEQUENCE {
- * version Version,
- * modulus INTEGER, -- n
- * publicExponent INTEGER, -- e
- * privateExponent INTEGER, -- d
- * prime1 INTEGER, -- p
- * prime2 INTEGER, -- q
- * exponent1 INTEGER, -- d mod (p-1)
- * exponent2 INTEGER, -- d mod (q-1)
- * coefficient INTEGER, -- (inverse of q) mod p
- * otherPrimeInfos OtherPrimeInfos OPTIONAL
- * }
- */
- static public byte[] Encode (RSA rsa)
- {
- RSAParameters param = rsa.ExportParameters (true);
-
- ASN1 rsaPrivateKey = new ASN1 (0x30);
- rsaPrivateKey.Add (new ASN1 (0x02, new byte [1] { 0x00 }));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Modulus));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Exponent));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.D));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.P));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.Q));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.DP));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.DQ));
- rsaPrivateKey.Add (ASN1Convert.FromUnsignedBigInteger (param.InverseQ));
-
- return rsaPrivateKey.GetBytes ();
- }
-
- // DSA only encode it's X private key inside an ASN.1 INTEGER (Hint: Tag == 0x02)
- // which isn't enough for rebuilding the keypair. The other parameters
- // can be found (98% of the time) in the X.509 certificate associated
- // with the private key or (2% of the time) the parameters are in it's
- // issuer X.509 certificate (not supported in the .NET framework).
- static public DSA DecodeDSA (byte[] privateKey, DSAParameters dsaParameters)
- {
- ASN1 pvk = new ASN1 (privateKey);
- if (pvk.Tag != 0x02)
- throw new CryptographicException ("invalid private key format");
-
- // X is ALWAYS 20 bytes (no matter if the key length is 512 or 1024 bits)
- dsaParameters.X = Normalize (pvk.Value, 20);
- DSA dsa = DSA.Create ();
- dsa.ImportParameters (dsaParameters);
- return dsa;
- }
-
- static public byte[] Encode (DSA dsa)
- {
- DSAParameters param = dsa.ExportParameters (true);
- return ASN1Convert.FromUnsignedBigInteger (param.X).GetBytes ();
- }
-
- static public byte[] Encode (AsymmetricAlgorithm aa)
- {
- if (aa is RSA)
- return Encode ((RSA)aa);
- else if (aa is DSA)
- return Encode ((DSA)aa);
- else
- throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());
- }
- }
-
- /*
- * EncryptedPrivateKeyInfo ::= SEQUENCE {
- * encryptionAlgorithm EncryptionAlgorithmIdentifier,
- * encryptedData EncryptedData
- * }
- *
- * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * EncryptedData ::= OCTET STRING
- *
- * --
- * AlgorithmIdentifier ::= SEQUENCE {
- * algorithm OBJECT IDENTIFIER,
- * parameters ANY DEFINED BY algorithm OPTIONAL
- * }
- *
- * -- from PKCS#5
- * PBEParameter ::= SEQUENCE {
- * salt OCTET STRING SIZE(8),
- * iterationCount INTEGER
- * }
- */
- public class EncryptedPrivateKeyInfo {
-
- private string _algorithm;
- private byte[] _salt;
- private int _iterations;
- private byte[] _data;
-
- public EncryptedPrivateKeyInfo () {}
-
- public EncryptedPrivateKeyInfo (byte[] data) : this ()
- {
- Decode (data);
- }
-
- // properties
-
- public string Algorithm {
- get { return _algorithm; }
- set { _algorithm = value; }
- }
-
- public byte[] EncryptedData {
- get { return (_data == null) ? null : (byte[]) _data.Clone (); }
- set { _data = (value == null) ? null : (byte[]) value.Clone (); }
- }
-
- public byte[] Salt {
- get {
- if (_salt == null) {
- RandomNumberGenerator rng = RandomNumberGenerator.Create ();
- _salt = new byte [8];
- rng.GetBytes (_salt);
- }
- return (byte[]) _salt.Clone ();
- }
- set { _salt = (byte[]) value.Clone (); }
- }
-
- public int IterationCount {
- get { return _iterations; }
- set {
- if (value < 0)
- throw new ArgumentOutOfRangeException ("IterationCount", "Negative");
- _iterations = value;
- }
- }
-
- // methods
-
- private void Decode (byte[] data)
- {
- ASN1 encryptedPrivateKeyInfo = new ASN1 (data);
- if (encryptedPrivateKeyInfo.Tag != 0x30)
- throw new CryptographicException ("invalid EncryptedPrivateKeyInfo");
-
- ASN1 encryptionAlgorithm = encryptedPrivateKeyInfo [0];
- if (encryptionAlgorithm.Tag != 0x30)
- throw new CryptographicException ("invalid encryptionAlgorithm");
- ASN1 algorithm = encryptionAlgorithm [0];
- if (algorithm.Tag != 0x06)
- throw new CryptographicException ("invalid algorithm");
- _algorithm = ASN1Convert.ToOid (algorithm);
- // parameters ANY DEFINED BY algorithm OPTIONAL
- if (encryptionAlgorithm.Count > 1) {
- ASN1 parameters = encryptionAlgorithm [1];
- if (parameters.Tag != 0x30)
- throw new CryptographicException ("invalid parameters");
-
- ASN1 salt = parameters [0];
- if (salt.Tag != 0x04)
- throw new CryptographicException ("invalid salt");
- _salt = salt.Value;
-
- ASN1 iterationCount = parameters [1];
- if (iterationCount.Tag != 0x02)
- throw new CryptographicException ("invalid iterationCount");
- _iterations = ASN1Convert.ToInt32 (iterationCount);
- }
-
- ASN1 encryptedData = encryptedPrivateKeyInfo [1];
- if (encryptedData.Tag != 0x04)
- throw new CryptographicException ("invalid EncryptedData");
- _data = encryptedData.Value;
- }
-
- // Note: PKCS#8 doesn't define how to generate the key required for encryption
- // so you're on your own. Just don't try to copy the big guys too much ;)
- // Netscape: http://www.cs.auckland.ac.nz/~pgut001/pubs/netscape.txt
- // Microsoft: http://www.cs.auckland.ac.nz/~pgut001/pubs/breakms.txt
- public byte[] GetBytes ()
- {
- if (_algorithm == null)
- throw new CryptographicException ("No algorithm OID specified");
-
- ASN1 encryptionAlgorithm = new ASN1 (0x30);
- encryptionAlgorithm.Add (ASN1Convert.FromOid (_algorithm));
-
- // parameters ANY DEFINED BY algorithm OPTIONAL
- if ((_iterations > 0) || (_salt != null)) {
- ASN1 salt = new ASN1 (0x04, _salt);
- ASN1 iterations = ASN1Convert.FromInt32 (_iterations);
-
- ASN1 parameters = new ASN1 (0x30);
- parameters.Add (salt);
- parameters.Add (iterations);
- encryptionAlgorithm.Add (parameters);
- }
-
- // encapsulates EncryptedData into an OCTET STRING
- ASN1 encryptedData = new ASN1 (0x04, _data);
-
- ASN1 encryptedPrivateKeyInfo = new ASN1 (0x30);
- encryptedPrivateKeyInfo.Add (encryptionAlgorithm);
- encryptedPrivateKeyInfo.Add (encryptedData);
-
- return encryptedPrivateKeyInfo.GetBytes ();
- }
- }
- }
-}
+++ /dev/null
-//
-// RSAManaged.cs - Implements the RSA algorithm.
-//
-// Authors:
-// Sebastien Pouliot (sebastien@ximian.com)
-// Ben Maurer (bmaurer@users.sf.net)
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Portions (C) 2003 Ben Maurer
-// Copyright (C) 2004,2006 Novell, Inc (http://www.novell.com)
-//
-// Key generation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
-// See bouncycastle.txt for license.
-//
-// 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 System.Text;
-
-using Mono.Math;
-
-// Big chunks of code are coming from the original RSACryptoServiceProvider class.
-// The class was refactored to :
-// a. ease integration of new hash algorithm (like MD2, RIPEMD160, ...);
-// b. provide better support for the coming SSL implementation (requires
-// EncryptValue/DecryptValue) with, or without, Mono runtime/corlib;
-// c. provide an alternative RSA implementation for all Windows (like using
-// OAEP without Windows XP).
-
-namespace Mono.Security.Cryptography {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class RSAManaged : RSA {
-
- private const int defaultKeySize = 1024;
-
- private bool isCRTpossible = false;
- private bool keyBlinding = true;
- private bool keypairGenerated = false;
- private bool m_disposed = false;
-
- private BigInteger d;
- private BigInteger p;
- private BigInteger q;
- private BigInteger dp;
- private BigInteger dq;
- private BigInteger qInv;
- private BigInteger n; // modulus
- private BigInteger e;
-
- public RSAManaged () : this (defaultKeySize)
- {
- }
-
- public RSAManaged (int keySize)
- {
- LegalKeySizesValue = new KeySizes [1];
- LegalKeySizesValue [0] = new KeySizes (384, 16384, 8);
- base.KeySize = keySize;
- }
-
- ~RSAManaged ()
- {
- // Zeroize private key
- Dispose (false);
- }
-
- private void GenerateKeyPair ()
- {
- // p and q values should have a length of half the strength in bits
- int pbitlength = ((KeySize + 1) >> 1);
- int qbitlength = (KeySize - pbitlength);
- const uint uint_e = 17;
- e = uint_e; // fixed
-
- // generate p, prime and (p-1) relatively prime to e
- for (;;) {
- p = BigInteger.GeneratePseudoPrime (pbitlength);
- if (p % uint_e != 1)
- break;
- }
- // generate a modulus of the required length
- for (;;) {
- // generate q, prime and (q-1) relatively prime to e,
- // and not equal to p
- for (;;) {
- q = BigInteger.GeneratePseudoPrime (qbitlength);
- if ((q % uint_e != 1) && (p != q))
- break;
- }
-
- // calculate the modulus
- n = p * q;
- if (n.BitCount () == KeySize)
- break;
-
- // if we get here our primes aren't big enough, make the largest
- // of the two p and try again
- if (p < q)
- p = q;
- }
-
- BigInteger pSub1 = (p - 1);
- BigInteger qSub1 = (q - 1);
- BigInteger phi = pSub1 * qSub1;
-
- // calculate the private exponent
- d = e.ModInverse (phi);
-
- // calculate the CRT factors
- dp = d % pSub1;
- dq = d % qSub1;
- qInv = q.ModInverse (p);
-
- keypairGenerated = true;
- isCRTpossible = true;
-
- if (KeyGenerated != null)
- KeyGenerated (this, null);
- }
-
- // overrides from RSA class
-
- public override int KeySize {
- get {
- // in case keypair hasn't been (yet) generated
- if (keypairGenerated) {
- int ks = n.BitCount ();
- if ((ks & 7) != 0)
- ks = ks + (8 - (ks & 7));
- return ks;
- }
- else
- return base.KeySize;
- }
- }
- public override string KeyExchangeAlgorithm {
- get { return "RSA-PKCS1-KeyEx"; }
- }
-
- // note: when (if) we generate a keypair then it will have both
- // the public and private keys
- public bool PublicOnly {
- get { return (keypairGenerated && ((d == null) || (n == null))); }
- }
-
- public override string SignatureAlgorithm {
- get { return "http://www.w3.org/2000/09/xmldsig#rsa-sha1"; }
- }
-
- public override byte[] DecryptValue (byte[] rgb)
- {
- if (m_disposed)
- throw new ObjectDisposedException ("private key");
-
- // decrypt operation is used for signature
- if (!keypairGenerated)
- GenerateKeyPair ();
-
- BigInteger input = new BigInteger (rgb);
- BigInteger r = null;
-
- // we use key blinding (by default) against timing attacks
- if (keyBlinding) {
- // x = (r^e * g) mod n
- // *new* random number (so it's timing is also random)
- r = BigInteger.GenerateRandom (n.BitCount ());
- input = r.ModPow (e, n) * input % n;
- }
-
- BigInteger output;
- // decrypt (which uses the private key) can be
- // optimized by using CRT (Chinese Remainder Theorem)
- if (isCRTpossible) {
- // m1 = c^dp mod p
- BigInteger m1 = input.ModPow (dp, p);
- // m2 = c^dq mod q
- BigInteger m2 = input.ModPow (dq, q);
- BigInteger h;
- if (m2 > m1) {
- // thanks to benm!
- h = p - ((m2 - m1) * qInv % p);
- output = m2 + q * h;
- } else {
- // h = (m1 - m2) * qInv mod p
- h = (m1 - m2) * qInv % p;
- // m = m2 + q * h;
- output = m2 + q * h;
- }
- } else if (!PublicOnly) {
- // m = c^d mod n
- output = input.ModPow (d, n);
- } else {
- throw new CryptographicException (Locale.GetText ("Missing private key to decrypt value."));
- }
-
- if (keyBlinding) {
- // Complete blinding
- // x^e / r mod n
- output = output * r.ModInverse (n) % n;
- r.Clear ();
- }
-
- // it's sometimes possible for the results to be a byte short
- // and this can break some software (see #79502) so we 0x00 pad the result
- byte[] result = GetPaddedValue (output, (KeySize >> 3));
- // zeroize values
- input.Clear ();
- output.Clear ();
- return result;
- }
-
- public override byte[] EncryptValue (byte[] rgb)
- {
- if (m_disposed)
- throw new ObjectDisposedException ("public key");
-
- if (!keypairGenerated)
- GenerateKeyPair ();
-
- BigInteger input = new BigInteger (rgb);
- BigInteger output = input.ModPow (e, n);
- // it's sometimes possible for the results to be a byte short
- // and this can break some software (see #79502) so we 0x00 pad the result
- byte[] result = GetPaddedValue (output, (KeySize >> 3));
- // zeroize value
- input.Clear ();
- output.Clear ();
- return result;
- }
-
-
-
- public override RSAParameters ExportParameters (bool includePrivateParameters)
- {
- if (m_disposed)
- throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
-
- if (!keypairGenerated)
- GenerateKeyPair ();
-
- RSAParameters param = new RSAParameters ();
- param.Exponent = e.GetBytes ();
- param.Modulus = n.GetBytes ();
- if (includePrivateParameters) {
- // some parameters are required for exporting the private key
- if (d == null)
- throw new CryptographicException ("Missing private key");
- param.D = d.GetBytes ();
- // hack for bugzilla #57941 where D wasn't provided
- if (param.D.Length != param.Modulus.Length) {
- byte[] normalizedD = new byte [param.Modulus.Length];
- Buffer.BlockCopy (param.D, 0, normalizedD, (normalizedD.Length - param.D.Length), param.D.Length);
- param.D = normalizedD;
- }
- // but CRT parameters are optionals
- if ((p != null) && (q != null) && (dp != null) && (dq != null) && (qInv != null)) {
- // and we include them only if we have them all
- int length = (KeySize >> 4);
- param.P = GetPaddedValue (p, length);
- param.Q = GetPaddedValue (q, length);
- param.DP = GetPaddedValue (dp, length);
- param.DQ = GetPaddedValue (dq, length);
- param.InverseQ = GetPaddedValue (qInv, length);
- }
- }
- return param;
- }
-
- public override void ImportParameters (RSAParameters parameters)
- {
- if (m_disposed)
- throw new ObjectDisposedException (Locale.GetText ("Keypair was disposed"));
-
- // if missing "mandatory" parameters
- if (parameters.Exponent == null)
- throw new CryptographicException (Locale.GetText ("Missing Exponent"));
- if (parameters.Modulus == null)
- throw new CryptographicException (Locale.GetText ("Missing Modulus"));
-
- e = new BigInteger (parameters.Exponent);
- n = new BigInteger (parameters.Modulus);
- // only if the private key is present
- if (parameters.D != null)
- d = new BigInteger (parameters.D);
- if (parameters.DP != null)
- dp = new BigInteger (parameters.DP);
- if (parameters.DQ != null)
- dq = new BigInteger (parameters.DQ);
- if (parameters.InverseQ != null)
- qInv = new BigInteger (parameters.InverseQ);
- if (parameters.P != null)
- p = new BigInteger (parameters.P);
- if (parameters.Q != null)
- q = new BigInteger (parameters.Q);
-
- // we now have a keypair
- keypairGenerated = true;
- bool privateKey = ((p != null) && (q != null) && (dp != null));
- isCRTpossible = (privateKey && (dq != null) && (qInv != null));
-
- // check if the public/private keys match
- // the way the check is made allows a bad D to work if CRT is available (like MS does, see unit tests)
- if (!privateKey)
- return;
-
- // always check n == p * q
- bool ok = (n == (p * q));
- if (ok) {
- // we now know that p and q are correct, so (p - 1), (q - 1) and phi will be ok too
- BigInteger pSub1 = (p - 1);
- BigInteger qSub1 = (q - 1);
- BigInteger phi = pSub1 * qSub1;
- // e is fairly static but anyway we can ensure it makes sense by recomputing d
- BigInteger dcheck = e.ModInverse (phi);
-
- // now if our new d(check) is different than the d we're provided then we cannot
- // be sure if 'd' or 'e' is invalid... (note that, from experience, 'd' is more
- // likely to be invalid since it's twice as large as DP (or DQ) and sits at the
- // end of the structure (e.g. truncation).
- ok = (d == dcheck);
-
- // ... unless we have the pre-computed CRT parameters
- if (!ok && isCRTpossible) {
- // we can override the previous decision since Mono always prefer, for
- // performance reasons, using the CRT algorithm
- ok = (dp == (dcheck % pSub1)) && (dq == (dcheck % qSub1)) &&
- (qInv == q.ModInverse (p));
- }
- }
-
- if (!ok)
- throw new CryptographicException (Locale.GetText ("Private/public key mismatch"));
- }
-
- protected override void Dispose (bool disposing)
- {
- if (!m_disposed) {
- // Always zeroize private key
- if (d != null) {
- d.Clear ();
- d = null;
- }
- if (p != null) {
- p.Clear ();
- p = null;
- }
- if (q != null) {
- q.Clear ();
- q = null;
- }
- if (dp != null) {
- dp.Clear ();
- dp = null;
- }
- if (dq != null) {
- dq.Clear ();
- dq = null;
- }
- if (qInv != null) {
- qInv.Clear ();
- qInv = null;
- }
-
- if (disposing) {
- // clear public key
- if (e != null) {
- e.Clear ();
- e = null;
- }
- if (n != null) {
- n.Clear ();
- n = 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;
-
- public override string ToXmlString (bool includePrivateParameters)
- {
- StringBuilder sb = new StringBuilder ();
- RSAParameters rsaParams = ExportParameters (includePrivateParameters);
- try {
- sb.Append ("<RSAKeyValue>");
-
- sb.Append ("<Modulus>");
- sb.Append (Convert.ToBase64String (rsaParams.Modulus));
- sb.Append ("</Modulus>");
-
- sb.Append ("<Exponent>");
- sb.Append (Convert.ToBase64String (rsaParams.Exponent));
- sb.Append ("</Exponent>");
-
- if (includePrivateParameters) {
- if (rsaParams.P != null) {
- sb.Append ("<P>");
- sb.Append (Convert.ToBase64String (rsaParams.P));
- sb.Append ("</P>");
- }
- if (rsaParams.Q != null) {
- sb.Append ("<Q>");
- sb.Append (Convert.ToBase64String (rsaParams.Q));
- sb.Append ("</Q>");
- }
- if (rsaParams.DP != null) {
- sb.Append ("<DP>");
- sb.Append (Convert.ToBase64String (rsaParams.DP));
- sb.Append ("</DP>");
- }
- if (rsaParams.DQ != null) {
- sb.Append ("<DQ>");
- sb.Append (Convert.ToBase64String (rsaParams.DQ));
- sb.Append ("</DQ>");
- }
- if (rsaParams.InverseQ != null) {
- sb.Append ("<InverseQ>");
- sb.Append (Convert.ToBase64String (rsaParams.InverseQ));
- sb.Append ("</InverseQ>");
- }
- sb.Append ("<D>");
- sb.Append (Convert.ToBase64String (rsaParams.D));
- sb.Append ("</D>");
- }
-
- sb.Append ("</RSAKeyValue>");
- }
- catch {
- if (rsaParams.P != null)
- Array.Clear (rsaParams.P, 0, rsaParams.P.Length);
- if (rsaParams.Q != null)
- Array.Clear (rsaParams.Q, 0, rsaParams.Q.Length);
- if (rsaParams.DP != null)
- Array.Clear (rsaParams.DP, 0, rsaParams.DP.Length);
- if (rsaParams.DQ != null)
- Array.Clear (rsaParams.DQ, 0, rsaParams.DQ.Length);
- if (rsaParams.InverseQ != null)
- Array.Clear (rsaParams.InverseQ, 0, rsaParams.InverseQ.Length);
- if (rsaParams.D != null)
- Array.Clear (rsaParams.D, 0, rsaParams.D.Length);
- throw;
- }
-
- return sb.ToString ();
- }
-
- // internal for Mono 1.0.x in order to preserve public contract
- // they are public for Mono 1.1.x (for 1.2) as the API isn't froze ATM
-
- public bool UseKeyBlinding {
- get { return keyBlinding; }
- // you REALLY shoudn't touch this (true is fine ;-)
- set { keyBlinding = value; }
- }
-
- public bool IsCrtPossible {
- // either the key pair isn't generated (and will be
- // generated with CRT parameters) or CRT is (or isn't)
- // possible (in case the key was imported)
- get { return (!keypairGenerated || isCRTpossible); }
- }
-
- private byte[] GetPaddedValue (BigInteger value, int length)
- {
- byte[] result = value.GetBytes ();
- if (result.Length >= length)
- return result;
-
- // left-pad 0x00 value on the result (same integer, correct length)
- byte[] padded = new byte[length];
- Buffer.BlockCopy (result, 0, padded, (length - result.Length), result.Length);
- // temporary result may contain decrypted (plaintext) data, clear it
- Array.Clear (result, 0, result.Length);
- return padded;
- }
- }
-}
+++ /dev/null
-//
-// Mono.Security.Cryptography.SymmetricTransform implementation
-//
-// Authors:
-// Thomas Neidhart (tome@sbox.tugraz.at)
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Portions (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2008 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 {
-
- // This class implement most of the common code required for symmetric
- // algorithm transforms, like:
- // - CipherMode: Builds CBC and CFB on top of (descendant supplied) ECB
- // - PaddingMode, transform properties, multiple blocks, reuse...
- //
- // Descendants MUST:
- // - intialize themselves (like key expansion, ...)
- // - override the ECB (Electronic Code Book) method which will only be
- // called using BlockSize byte[] array.
- internal abstract class SymmetricTransform : ICryptoTransform {
- protected SymmetricAlgorithm algo;
- protected bool encrypt;
- protected int BlockSizeByte;
- protected byte[] temp;
- protected byte[] temp2;
- private byte[] workBuff;
- private byte[] workout;
- protected PaddingMode padmode;
- // Silverlight 2.0 does not support any feedback mode
- protected int FeedBackByte;
- private bool m_disposed = false;
- protected bool lastBlock;
-
- public SymmetricTransform (SymmetricAlgorithm symmAlgo, bool encryption, byte[] rgbIV)
- {
- algo = symmAlgo;
- encrypt = encryption;
- BlockSizeByte = (algo.BlockSize >> 3);
-
- if (rgbIV == null) {
- rgbIV = KeyBuilder.IV (BlockSizeByte);
- } else {
- rgbIV = (byte[]) rgbIV.Clone ();
- }
- // compare the IV length with the "currently selected" block size and *ignore* IV that are too big
- if (rgbIV.Length < BlockSizeByte) {
- string msg = Locale.GetText ("IV is too small ({0} bytes), it should be {1} bytes long.",
- rgbIV.Length, BlockSizeByte);
- throw new CryptographicException (msg);
- }
- padmode = algo.Padding;
- // mode buffers
- temp = new byte [BlockSizeByte];
- Buffer.BlockCopy (rgbIV, 0, temp, 0, System.Math.Min (BlockSizeByte, rgbIV.Length));
- temp2 = new byte [BlockSizeByte];
- FeedBackByte = (algo.FeedbackSize >> 3);
- // transform buffers
- workBuff = new byte [BlockSizeByte];
- workout = new byte [BlockSizeByte];
- }
-
- ~SymmetricTransform ()
- {
- Dispose (false);
- }
-
- void IDisposable.Dispose ()
- {
- Dispose (true);
- GC.SuppressFinalize (this); // Finalization is now unnecessary
- }
-
- // MUST be overriden by classes using unmanaged ressources
- // the override method must call the base class
- protected virtual void Dispose (bool disposing)
- {
- if (!m_disposed) {
- if (disposing) {
- // dispose managed object: zeroize and free
- Array.Clear (temp, 0, BlockSizeByte);
- temp = null;
- Array.Clear (temp2, 0, BlockSizeByte);
- temp2 = null;
- }
- m_disposed = true;
- }
- }
-
- public virtual bool CanTransformMultipleBlocks {
- get { return true; }
- }
-
- public virtual bool CanReuseTransform {
- get { return false; }
- }
-
- public virtual int InputBlockSize {
- get { return BlockSizeByte; }
- }
-
- public virtual int OutputBlockSize {
- get { return BlockSizeByte; }
- }
-
- // note: Each block MUST be BlockSizeValue in size!!!
- // i.e. Any padding must be done before calling this method
- protected virtual void Transform (byte[] input, byte[] output)
- {
- switch (algo.Mode) {
- case CipherMode.ECB:
- ECB (input, output);
- break;
- case CipherMode.CBC:
- CBC (input, output);
- break;
- case CipherMode.CFB:
- CFB (input, output);
- break;
- case CipherMode.OFB:
- OFB (input, output);
- break;
- case CipherMode.CTS:
- CTS (input, output);
- break;
- default:
- throw new NotImplementedException ("Unkown CipherMode" + algo.Mode.ToString ());
- }
- }
-
- // Electronic Code Book (ECB)
- protected abstract void ECB (byte[] input, byte[] output);
-
- // Cipher-Block-Chaining (CBC)
- protected virtual void CBC (byte[] input, byte[] output)
- {
- if (encrypt) {
- for (int i = 0; i < BlockSizeByte; i++)
- temp[i] ^= input[i];
- ECB (temp, output);
- Buffer.BlockCopy (output, 0, temp, 0, BlockSizeByte);
- }
- else {
- Buffer.BlockCopy (input, 0, temp2, 0, BlockSizeByte);
- ECB (input, output);
- for (int i = 0; i < BlockSizeByte; i++)
- output[i] ^= temp[i];
- Buffer.BlockCopy (temp2, 0, temp, 0, BlockSizeByte);
- }
- }
-
- // Cipher-FeedBack (CFB)
- // this is how *CryptoServiceProvider implements CFB
- // only AesCryptoServiceProvider support CFB > 8
- // RijndaelManaged is incompatible with this implementation (and overrides it in it's own transform)
- protected virtual void CFB (byte[] input, byte[] output)
- {
- if (encrypt) {
- for (int x = 0; x < BlockSizeByte; x++) {
- // temp is first initialized with the IV
- ECB (temp, temp2);
- output [x] = (byte) (temp2 [0] ^ input [x]);
- Buffer.BlockCopy (temp, 1, temp, 0, BlockSizeByte - 1);
- Buffer.BlockCopy (output, x, temp, BlockSizeByte - 1, 1);
- }
- }
- else {
- for (int x = 0; x < BlockSizeByte; x++) {
- // we do not really decrypt this data!
- encrypt = true;
- // temp is first initialized with the IV
- ECB (temp, temp2);
- encrypt = false;
-
- Buffer.BlockCopy (temp, 1, temp, 0, BlockSizeByte - 1);
- Buffer.BlockCopy (input, x, temp, BlockSizeByte - 1, 1);
- output [x] = (byte) (temp2 [0] ^ input [x]);
- }
- }
- }
-
- // Output-FeedBack (OFB)
- protected virtual void OFB (byte[] input, byte[] output)
- {
- throw new CryptographicException ("OFB isn't supported by the framework");
- }
-
- // Cipher Text Stealing (CTS)
- protected virtual void CTS (byte[] input, byte[] output)
- {
- throw new CryptographicException ("CTS isn't supported by the framework");
- }
-
- private void CheckInput (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- if (inputBuffer == null)
- throw new ArgumentNullException ("inputBuffer");
- if (inputOffset < 0)
- throw new ArgumentOutOfRangeException ("inputOffset", "< 0");
- if (inputCount < 0)
- throw new ArgumentOutOfRangeException ("inputCount", "< 0");
- // ordered to avoid possible integer overflow
- if (inputOffset > inputBuffer.Length - inputCount)
- throw new ArgumentException ("inputBuffer", Locale.GetText ("Overflow"));
- }
-
- // this method may get called MANY times so this is the one to optimize
- public virtual int TransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- if (m_disposed)
- throw new ObjectDisposedException ("Object is disposed");
- CheckInput (inputBuffer, inputOffset, inputCount);
- // check output parameters
- if (outputBuffer == null)
- throw new ArgumentNullException ("outputBuffer");
- if (outputOffset < 0)
- throw new ArgumentOutOfRangeException ("outputOffset", "< 0");
-
- // ordered to avoid possible integer overflow
- int len = outputBuffer.Length - inputCount - outputOffset;
- if (!encrypt && (0 > len) && ((padmode == PaddingMode.None) || (padmode == PaddingMode.Zeros))) {
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- } else if (KeepLastBlock) {
- if (0 > len + BlockSizeByte) {
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- }
- } else {
- if (0 > len) {
- // there's a special case if this is the end of the decryption process
- if (inputBuffer.Length - inputOffset - outputBuffer.Length == BlockSizeByte)
- inputCount = outputBuffer.Length - outputOffset;
- else
- throw new CryptographicException ("outputBuffer", Locale.GetText ("Overflow"));
- }
- }
- return InternalTransformBlock (inputBuffer, inputOffset, inputCount, outputBuffer, outputOffset);
- }
-
- private bool KeepLastBlock {
- get {
- return ((!encrypt) && (padmode != PaddingMode.None) && (padmode != PaddingMode.Zeros));
- }
- }
-
- private int InternalTransformBlock (byte[] inputBuffer, int inputOffset, int inputCount, byte[] outputBuffer, int outputOffset)
- {
- int offs = inputOffset;
- int full;
-
- // this way we don't do a modulo every time we're called
- // and we may save a division
- if (inputCount != BlockSizeByte) {
- if ((inputCount % BlockSizeByte) != 0)
- throw new CryptographicException ("Invalid input block size.");
-
- full = inputCount / BlockSizeByte;
- }
- else
- full = 1;
-
- if (KeepLastBlock)
- full--;
-
- int total = 0;
-
- if (lastBlock) {
- Transform (workBuff, workout);
- Buffer.BlockCopy (workout, 0, outputBuffer, outputOffset, BlockSizeByte);
- outputOffset += BlockSizeByte;
- total += BlockSizeByte;
- lastBlock = false;
- }
-
- for (int i = 0; i < full; i++) {
- Buffer.BlockCopy (inputBuffer, offs, workBuff, 0, BlockSizeByte);
- Transform (workBuff, workout);
- Buffer.BlockCopy (workout, 0, outputBuffer, outputOffset, BlockSizeByte);
- offs += BlockSizeByte;
- outputOffset += BlockSizeByte;
- total += BlockSizeByte;
- }
-
- if (KeepLastBlock) {
- Buffer.BlockCopy (inputBuffer, offs, workBuff, 0, BlockSizeByte);
- lastBlock = true;
- }
-
- return total;
- }
-
- RandomNumberGenerator _rng;
-
- private void Random (byte[] buffer, int start, int length)
- {
- if (_rng == null) {
- _rng = RandomNumberGenerator.Create ();
- }
- byte[] random = new byte [length];
- _rng.GetBytes (random);
- Buffer.BlockCopy (random, 0, buffer, start, length);
- }
-
- private void ThrowBadPaddingException (PaddingMode padding, int length, int position)
- {
- string msg = String.Format (Locale.GetText ("Bad {0} padding."), padding);
- if (length >= 0)
- msg += String.Format (Locale.GetText (" Invalid length {0}."), length);
- if (position >= 0)
- msg += String.Format (Locale.GetText (" Error found at position {0}."), position);
- throw new CryptographicException (msg);
- }
-
- protected virtual byte[] FinalEncrypt (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- // are there still full block to process ?
- int full = (inputCount / BlockSizeByte) * BlockSizeByte;
- int rem = inputCount - full;
- int total = full;
-
- switch (padmode) {
- case PaddingMode.ANSIX923:
- case PaddingMode.ISO10126:
- case PaddingMode.PKCS7:
- // we need to add an extra block for padding
- total += BlockSizeByte;
- break;
- default:
- if (inputCount == 0)
- return new byte [0];
- if (rem != 0) {
- if (padmode == PaddingMode.None)
- throw new CryptographicException ("invalid block length");
- // zero padding the input (by adding a block for the partial data)
- byte[] paddedInput = new byte [full + BlockSizeByte];
- Buffer.BlockCopy (inputBuffer, inputOffset, paddedInput, 0, inputCount);
- inputBuffer = paddedInput;
- inputOffset = 0;
- inputCount = paddedInput.Length;
- total = inputCount;
- }
- break;
- }
-
- byte[] res = new byte [total];
- int outputOffset = 0;
-
- // process all blocks except the last (final) block
- while (total > BlockSizeByte) {
- InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
- inputOffset += BlockSizeByte;
- outputOffset += BlockSizeByte;
- total -= BlockSizeByte;
- }
-
- // now we only have a single last block to encrypt
- byte padding = (byte) (BlockSizeByte - rem);
- switch (padmode) {
- case PaddingMode.ANSIX923:
- // XX 00 00 00 00 00 00 07 (zero + padding length)
- res [res.Length - 1] = padding;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- case PaddingMode.ISO10126:
- // XX 3F 52 2A 81 AB F7 07 (random + padding length)
- Random (res, res.Length - padding, padding - 1);
- res [res.Length - 1] = padding;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- case PaddingMode.PKCS7:
- // XX 07 07 07 07 07 07 07 (padding length)
- for (int i = res.Length; --i >= (res.Length - padding);)
- res [i] = padding;
- Buffer.BlockCopy (inputBuffer, inputOffset, res, full, rem);
- // the last padded block will be transformed in-place
- InternalTransformBlock (res, full, BlockSizeByte, res, full);
- break;
- default:
- InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
- break;
- }
- return res;
- }
-
- protected virtual byte[] FinalDecrypt (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- int full = inputCount;
- int total = inputCount;
- if (lastBlock)
- total += BlockSizeByte;
-
- byte[] res = new byte [total];
- int outputOffset = 0;
-
- while (full > 0) {
- int len = InternalTransformBlock (inputBuffer, inputOffset, BlockSizeByte, res, outputOffset);
- inputOffset += BlockSizeByte;
- outputOffset += len;
- full -= BlockSizeByte;
- }
-
- if (lastBlock) {
- Transform (workBuff, workout);
- Buffer.BlockCopy (workout, 0, res, outputOffset, BlockSizeByte);
- outputOffset += BlockSizeByte;
- lastBlock = false;
- }
-
- // total may be 0 (e.g. PaddingMode.None)
- byte padding = ((total > 0) ? res [total - 1] : (byte) 0);
- switch (padmode) {
- case PaddingMode.ANSIX923:
- if ((padding == 0) || (padding > BlockSizeByte))
- ThrowBadPaddingException (padmode, padding, -1);
- for (int i = padding - 1; i > 0; i--) {
- if (res [total - 1 - i] != 0x00)
- ThrowBadPaddingException (padmode, -1, i);
- }
- total -= padding;
- break;
- case PaddingMode.ISO10126:
- if ((padding == 0) || (padding > BlockSizeByte))
- ThrowBadPaddingException (padmode, padding, -1);
- total -= padding;
- break;
- case PaddingMode.PKCS7:
- if ((padding == 0) || (padding > BlockSizeByte))
- ThrowBadPaddingException (padmode, padding, -1);
- for (int i = padding - 1; i > 0; i--) {
- if (res [total - 1 - i] != padding)
- ThrowBadPaddingException (padmode, -1, i);
- }
- total -= padding;
- break;
- case PaddingMode.None: // nothing to do - it's a multiple of block size
- case PaddingMode.Zeros: // nothing to do - user must unpad himself
- break;
- }
-
- // return output without padding
- if (total > 0) {
- byte[] data = new byte [total];
- Buffer.BlockCopy (res, 0, data, 0, total);
- // zeroize decrypted data (copy with padding)
- Array.Clear (res, 0, res.Length);
- return data;
- }
- else
- return new byte [0];
- }
-
- public virtual byte[] TransformFinalBlock (byte[] inputBuffer, int inputOffset, int inputCount)
- {
- if (m_disposed)
- throw new ObjectDisposedException ("Object is disposed");
- CheckInput (inputBuffer, inputOffset, inputCount);
-
- if (encrypt)
- return FinalEncrypt (inputBuffer, inputOffset, inputCount);
- else
- return FinalDecrypt (inputBuffer, inputOffset, inputCount);
- }
- }
-}
+++ /dev/null
-//
-// BasicConstraintsExtension.cs: Handles X.509 BasicConstrains extensions.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 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.Globalization;
-using System.Text;
-
-using Mono.Security;
-using Mono.Security.X509;
-
-namespace Mono.Security.X509.Extensions {
-
- // References:
- // 1. RFC 3280: Internet X.509 Public Key Infrastructure, Section 4.2.1.10
- // http://www.ietf.org/rfc/rfc3280.txt
-
- /* id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 }
- *
- * BasicConstraints ::= SEQUENCE {
- * cA BOOLEAN DEFAULT FALSE,
- * pathLenConstraint INTEGER (0..MAX) OPTIONAL
- * }
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class BasicConstraintsExtension : X509Extension {
-
- public const int NoPathLengthConstraint = -1;
-
- private bool cA;
- private int pathLenConstraint;
-
- public BasicConstraintsExtension () : base ()
- {
- extnOid = "2.5.29.19";
- pathLenConstraint = NoPathLengthConstraint;
- }
-
- public BasicConstraintsExtension (ASN1 asn1) : base (asn1) {}
-
- public BasicConstraintsExtension (X509Extension extension) : base (extension) {}
-
- protected override void Decode ()
- {
- // default values
- cA = false;
- pathLenConstraint = NoPathLengthConstraint;
-
- ASN1 sequence = new ASN1 (extnValue.Value);
- if (sequence.Tag != 0x30)
- throw new ArgumentException ("Invalid BasicConstraints extension");
- int n = 0;
- ASN1 a = sequence [n++];
- if ((a != null) && (a.Tag == 0x01)) {
- cA = (a.Value [0] == 0xFF);
- a = sequence [n++];
- }
- if ((a != null) && (a.Tag == 0x02))
- pathLenConstraint = ASN1Convert.ToInt32 (a);
- }
-
- protected override void Encode ()
- {
- ASN1 seq = new ASN1 (0x30);
- if (cA)
- seq.Add (new ASN1 (0x01, new byte[] { 0xFF }));
- // CAs MUST NOT include the pathLenConstraint field unless the cA boolean is asserted
- if (cA && (pathLenConstraint >= 0))
- seq.Add (ASN1Convert.FromInt32 (pathLenConstraint));
-
- extnValue = new ASN1 (0x04);
- extnValue.Add (seq);
- }
-
- public bool CertificateAuthority {
- get { return cA; }
- set { cA = value; }
- }
-
- public override string Name {
- get { return "Basic Constraints"; }
- }
-
- public int PathLenConstraint {
- get { return pathLenConstraint; }
- set {
- if (value < NoPathLengthConstraint) {
- string msg = Locale.GetText ("PathLenConstraint must be positive or -1 for none ({0}).", value);
- throw new ArgumentOutOfRangeException (msg);
- }
- pathLenConstraint = value;
- }
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder ();
- sb.Append ("Subject Type=");
- sb.Append ((cA) ? "CA" : "End Entity");
- sb.Append (Environment.NewLine);
- sb.Append ("Path Length Constraint=");
- if (pathLenConstraint == NoPathLengthConstraint)
- sb.Append ("None");
- else
- sb.Append (pathLenConstraint.ToString (CultureInfo.InvariantCulture));
- sb.Append (Environment.NewLine);
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-2006-01-04 Sebastien Pouliot <sebastien@ximian.com>
-
- * BasicConstraintsExtension.cs: Keep in sync with Mono.Security.dll.
- * KeyUsageExtension.cs: Keep in sync with Mono.Security.dll.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * BasicConstaintExtension.cs: New in corlib. In sync with
- Mono.Security.dll version.
- * KeyUsageExtension.cs: New in corlib. In sync with Mono.Security.dll
- version.
- * SubjectKeyIdentifierExtension.cs: New in corlib. In sync with
- Mono.Security.dll version.
+++ /dev/null
-//
-// KeyUsageExtension.cs: Handles X.509 KeyUsage extensions.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 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.Globalization;
-using System.Text;
-
-using Mono.Security;
-using Mono.Security.X509;
-
-namespace Mono.Security.X509.Extensions {
-
- /*
- * id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 }
- *
- * KeyUsage ::= BIT STRING {
- * digitalSignature (0),
- * nonRepudiation (1),
- * keyEncipherment (2),
- * dataEncipherment (3),
- * keyAgreement (4),
- * keyCertSign (5),
- * cRLSign (6),
- * encipherOnly (7),
- * decipherOnly (8)
- * }
- */
- // note: because nothing is simple in ASN.1 bits are reversed
- [Flags]
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- enum KeyUsages {
- digitalSignature = 0x80,
- nonRepudiation = 0x40,
- keyEncipherment = 0x20,
- dataEncipherment = 0x10,
- keyAgreement = 0x08,
- keyCertSign = 0x04,
- cRLSign = 0x02,
- encipherOnly = 0x01,
- decipherOnly = 0x800,
- none = 0x0
- }
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class KeyUsageExtension : X509Extension {
-
- private int kubits;
-
- public KeyUsageExtension (ASN1 asn1) : base (asn1) {}
-
- public KeyUsageExtension (X509Extension extension) : base (extension) {}
-
- public KeyUsageExtension () : base ()
- {
- extnOid = "2.5.29.15";
- }
-
- protected override void Decode ()
- {
- ASN1 bitString = new ASN1 (extnValue.Value);
- if (bitString.Tag != 0x03)
- throw new ArgumentException ("Invalid KeyUsage extension");
- int i = 1; // byte zero has the number of unused bits (ASN1's BITSTRING)
- while (i < bitString.Value.Length)
- kubits = (kubits << 8) + bitString.Value [i++];
- }
-
- protected override void Encode ()
- {
- extnValue = new ASN1 (0x04);
-
- ushort ku = (ushort) kubits;
- byte unused = 16;
- if (ku > 0) {
- // count the unused bits
- for (unused = 15; unused > 0; unused--) {
- if ((ku & 0x8000) == 0x8000)
- break;
- ku <<= 1;
- }
-
- if (kubits > Byte.MaxValue) {
- unused -= 8;
- extnValue.Add (new ASN1 (0x03, new byte[] { unused, (byte) kubits, (byte) (kubits >> 8) }));
- } else {
- extnValue.Add (new ASN1 (0x03, new byte[] { unused, (byte) kubits }));
- }
- } else {
- // note: a BITSTRING with a 0 length is invalid (in ASN.1), so would an
- // empty OCTETSTRING (at the parent level) so we're encoding a 0
- extnValue.Add (new ASN1 (0x03, new byte[] { 7, 0 }));
- }
- }
-
- public KeyUsages KeyUsage {
- get { return (KeyUsages) kubits; }
- set { kubits = Convert.ToInt32 (value, CultureInfo.InvariantCulture); }
- }
-
- public override string Name {
- get { return "Key Usage"; }
- }
-
- public bool Support (KeyUsages usage)
- {
- int x = Convert.ToInt32 (usage, CultureInfo.InvariantCulture);
- return ((x & kubits) == x);
- }
-
- public override string ToString ()
- {
- const string separator = " , ";
- StringBuilder sb = new StringBuilder ();
- if (Support (KeyUsages.digitalSignature))
- sb.Append ("Digital Signature");
- if (Support (KeyUsages.nonRepudiation)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Non-Repudiation");
- }
- if (Support (KeyUsages.keyEncipherment)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Key Encipherment");
- }
- if (Support (KeyUsages.dataEncipherment)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Data Encipherment");
- }
- if (Support (KeyUsages.keyAgreement)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Key Agreement");
- }
- if (Support (KeyUsages.keyCertSign)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Certificate Signing");
- }
- if (Support (KeyUsages.cRLSign)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("CRL Signing");
- }
- if (Support (KeyUsages.encipherOnly)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Encipher Only "); // ???
- }
- if (Support (KeyUsages.decipherOnly)) {
- if (sb.Length > 0)
- sb.Append (separator);
- sb.Append ("Decipher Only"); // ???
- }
- sb.Append ("(");
- sb.Append (kubits.ToString ("X2", CultureInfo.InvariantCulture));
- sb.Append (")");
- sb.Append (Environment.NewLine);
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// SubjectKeyIdentifierExtension.cs: Handles X.509 SubjectKeyIdentifier extensions.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2004 Novell (http://www.novell.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.Globalization;
-using System.Text;
-
-using Mono.Security;
-using Mono.Security.X509;
-
-namespace Mono.Security.X509.Extensions {
-
- /*
- * id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 }
- *
- * SubjectKeyIdentifier ::= KeyIdentifier
- *
- * KeyIdentifier ::= OCTET STRING
- */
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class SubjectKeyIdentifierExtension : X509Extension {
-
- private byte[] ski;
-
- public SubjectKeyIdentifierExtension () : base ()
- {
- extnOid = "2.5.29.14";
- }
-
- public SubjectKeyIdentifierExtension (ASN1 asn1) : base (asn1)
- {
- }
-
- public SubjectKeyIdentifierExtension (X509Extension extension) : base (extension)
- {
- }
-
- protected override void Decode ()
- {
- ASN1 sequence = new ASN1 (extnValue.Value);
- if (sequence.Tag != 0x04)
- throw new ArgumentException ("Invalid SubjectKeyIdentifier extension");
- ski = sequence.Value;
- }
-
- public override string Name {
- get { return "Subject Key Identifier"; }
- }
-
- public byte[] Identifier {
- get {
- if (ski == null)
- return null;
- return (byte[]) ski.Clone ();
- }
- }
-
- public override string ToString ()
- {
- if (ski == null)
- return null;
-
- StringBuilder sb = new StringBuilder ();
- int x = 0;
- while (x < ski.Length) {
- sb.Append (ski [x].ToString ("X2", CultureInfo.InvariantCulture));
- if (x % 2 == 1)
- sb.Append (" ");
- x++;
- }
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-2010-05-10 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509CertificateCollection.cs:
- * X509Certificate.cs:
- * X509Extension.cs:
- * X509Extensions.cs:
- Keep them public for Moonlight. Other types in other
- assemblies needs it and the linker will eventually
- internalize everything.
-
-2010-03-16 Jb Evain <jbevain@novell.com>
-
- * X509Certificate.cs: use MOONLIGHT symbol to disambiguate
- MonoTouch and Moonlight code.
-
-2009-04-30 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Adapt to work with only [DSA|RSA]Managed when
- built for NET_2_1, i.e. remove use of [DSA|RSA]CryptoServiceProvider
-
-2008-09-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS12.cs, X509Store.cs: Use File.Create instead of OpenWrite to
- make sure nothing else if left at the end of the file. Issue reported
- by Christophe Chevalier.
-
-2008-06-03 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Accept text before the PEM certificate itself.
- [Fix bug #396486]
-
-2008-01-10 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS12.cs, X509Certificate.cs, X509Chain.cs, X509Extension.cs:
- Synchronize/update with Mono.Security assembly
-
-2006-12-14 Sebastien Pouliot <sebastien@ximian.com>
-
- * X501Name.cs: Added support for (some cases of) T.61 strings, like
- the latin-1 encoded accentued characters founds in some DN. Fix bug
- #77295.
-
-2006-12-11 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS12.cs: Synchronize source with Mono.Security.dll
- * X501Name.cs: Synchronize source with Mono.Security.dll
- * X509Certificate.cs: Synchronize source with Mono.Security.dll
- * X509CRL.cs: Synchronize source with Mono.Security.dll
- * X509Store.cs: Synchronize source with Mono.Security.dll
- * X509Stores.cs: Synchronize source with Mono.Security.dll
- * X520Attributes.cs: Synchronize source with Mono.Security.dll
-
-2006-11-13 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Add support for PEM encoded (base64) x.509
- certificates (supported in 2.0).
-
-2006-11-08 Sebastien Pouliot <sebastien@ximian.com>
-
- * X501Name.cs: Refactor ToString method to allow most options available
- when using fx 2.0.
- * X509Certificate.cs: Add methods to retrieve the Issuer and Subject
- Distinguished Names in binary (ASN.1) form. Reverse (actually correct)
- the text representation of Issuer and Subject for 2.0.
- * X520Attributes.cs: Keep in sync with latest version from
- Mono.Security.dll assembly (required for X501Name update).
-
-2006-10-08 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS12.cs: Synch implementation with Mono.Security.dll. Fix bug
- #79617.
-
-2006-09-05 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Keep in sync with Mono.Security.dll (#79262).
-
-2006-01-04 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Extension.cs: Keep in sync with Mono.Security.dll.
-
-2005-11-18 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Extension.cs: Keep in sync with Mono.Security.dll.
-
-2005-10-11 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Fixed bug #76407. ValidFrom and ValidUntil are
- local date/time so IsCurrent most also use a local date/time.
- * X509CRL.cs: Updated from Mono.Security.dll (same IsCurrent problem
- and another previously fixed bug).
-
-2005-09-09 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Fixed version property (bug #76012). Added
- ISerializable (for 2.0 so we're not breaking current compatibility).
-
-2005-04-27 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS12.cs: New. Copied from Mono.Security.dll to allow support of
- PKCS#12 files in X509Certificate for 2.0.
- * X509Certificate.cs: Added new features required to support 2.0.
-
-2005-02-25 Sebastien Pouliot <sebastien@ximian.com>
-
- * X501Name.cs: In sync with Mono.Security.dll version.
- * X520Attributes.cs: In sync with Mono.Security.dll version.
-
-2005-01-10 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Fixed NullReferenceException when asking for
- data that wasn't a proper X.509 certificate.
-
-2004-09-16 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Fixed warning (l4) for unused variable.
- * X509Extension.cs: Fixed warning (l4) for unused variable.
-
-2004-09-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Chain.cs: Merge from Mono.Security. Fix two bugs (chain
- construction from collection) and Reset-ing empty chain.
-
-2004-05-27 Sebastien Pouliot <sebastien@ximian.com>
-
- * X509Certificate.cs: Rethrow original exception when parsing X.509
- certificates (inside a CryptographicException) so people can see if
- their changes affects certificate decoding.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * X501Name.cs: In sync with Mono.Security.dll version.
- * X509CRL.cs: New in corlib. In sync with Mono.Security.dll version.
- * X509Certificate.cs: In sync with Mono.Security.dll version.
- * X509CertificateCollection.cs: In sync with Mono.Security.dll version.
- * X509Chain.cs: In sync with Mono.Security.dll version.
- * X509ChainStatusFlag.cs: New in corlib. In sync with Mono.Security.dll
- version.
- * X509Extension.cs: In sync with Mono.Security.dll version.
- * X509Extensions.cs: In sync with Mono.Security.dll version.
- * X509Store.cs: New in corlib. In sync with Mono.Security.dll version.
- * X509StoreManager.cs: New in corlib. In sync with Mono.Security.dll version.
- * X509Stores.cs: New in corlib. In sync with Mono.Security.dll version.
- * X520Attributes.cs: In sync with Mono.Security.dll version.
-
-2003-12-15 Sebastien Pouliot <spouliot@videotron.ca>
-
- * TrustAnchors.cs: Added a new trusted root, Thawte, for code signing.
-
-2003-10-12 Sebastien Pouliot <spouliot@videotron.ca>
-
- * ITrustAnchors.cs: Added from Mono.Security assembly to
- support Authenticode in X509Certificate.CreateFromSignedFile
- * TestAnchors.cs: Added from Mono.Security assembly to
- support Authenticode in X509Certificate.CreateFromSignedFile
- * TrustAnchors.cs: Added from Mono.Security assembly to
- support Authenticode in X509Certificate.CreateFromSignedFile
- * X509CertificateCollection.cs: Added from Mono.Security assembly to
- support Authenticode in X509Certificate.CreateFromSignedFile
- * X509Chain.cs: Added from Mono.Security assembly to
- support Authenticode in X509Certificate.CreateFromSignedFile
-
-2003-05-16 Sebastien Pouliot <spouliot@videotron.ca>
-
- * X509Certificate.cs: Added support for "really" NULL key parameters
- (i.e. not ASN.1 encoded NULL).
-
-2003-03-15 Sebastien Pouliot <spouliot@videotron.ca>
-
- * X501Name.cs: New. X.501 Distinguished Names stuff
- * X509Certificate.cs: New. A more complete class to handle X.509
- certificates.
- * X509Extension.cs: New. A base class for all X.509 extensions.
- * X509Extensions.cs: New. X509Extension collection.
- * X520Attributes.cs: New. X.520 attributes (mainly for X501 names)
+++ /dev/null
-//
-// ITrustAnchors.cs: Trust Anchors Interface
-//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
-//
-// (C) 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;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- interface ITrustAnchors
- {
- X509CertificateCollection Anchors { get; }
- }
-}
+++ /dev/null
-//
-// PKCS12.cs: PKCS 12 - Personal Information Exchange Syntax
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004,2005,2006 Novell Inc. (http://www.novell.com)
-//
-// Key derivation translated from Bouncy Castle JCE (http://www.bouncycastle.org/)
-// See bouncycastle.txt for license.
-//
-// 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.Collections;
-using System.IO;
-using System.Security.Cryptography;
-using System.Text;
-
-using Mono.Security;
-using Mono.Security.Cryptography;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class PKCS5 {
-
- public const string pbeWithMD2AndDESCBC = "1.2.840.113549.1.5.1";
- public const string pbeWithMD5AndDESCBC = "1.2.840.113549.1.5.3";
- public const string pbeWithMD2AndRC2CBC = "1.2.840.113549.1.5.4";
- public const string pbeWithMD5AndRC2CBC = "1.2.840.113549.1.5.6";
- public const string pbeWithSHA1AndDESCBC = "1.2.840.113549.1.5.10";
- public const string pbeWithSHA1AndRC2CBC = "1.2.840.113549.1.5.11";
-
- public PKCS5 () {}
- }
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class PKCS9 {
-
- public const string friendlyName = "1.2.840.113549.1.9.20";
- public const string localKeyId = "1.2.840.113549.1.9.21";
-
- public PKCS9 () {}
- }
-
-
- internal class SafeBag {
- private string _bagOID;
- private ASN1 _asn1;
-
- public SafeBag(string bagOID, ASN1 asn1) {
- _bagOID = bagOID;
- _asn1 = asn1;
- }
-
- public string BagOID {
- get { return _bagOID; }
- }
-
- public ASN1 ASN1 {
- get { return _asn1; }
- }
- }
-
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class PKCS12 : ICloneable {
-
- public const string pbeWithSHAAnd128BitRC4 = "1.2.840.113549.1.12.1.1";
- public const string pbeWithSHAAnd40BitRC4 = "1.2.840.113549.1.12.1.2";
- public const string pbeWithSHAAnd3KeyTripleDESCBC = "1.2.840.113549.1.12.1.3";
- public const string pbeWithSHAAnd2KeyTripleDESCBC = "1.2.840.113549.1.12.1.4";
- public const string pbeWithSHAAnd128BitRC2CBC = "1.2.840.113549.1.12.1.5";
- public const string pbeWithSHAAnd40BitRC2CBC = "1.2.840.113549.1.12.1.6";
-
- // bags
- public const string keyBag = "1.2.840.113549.1.12.10.1.1";
- public const string pkcs8ShroudedKeyBag = "1.2.840.113549.1.12.10.1.2";
- public const string certBag = "1.2.840.113549.1.12.10.1.3";
- public const string crlBag = "1.2.840.113549.1.12.10.1.4";
- public const string secretBag = "1.2.840.113549.1.12.10.1.5";
- public const string safeContentsBag = "1.2.840.113549.1.12.10.1.6";
-
- // types
- public const string x509Certificate = "1.2.840.113549.1.9.22.1";
- public const string sdsiCertificate = "1.2.840.113549.1.9.22.2";
- public const string x509Crl = "1.2.840.113549.1.9.23.1";
-
- // Adapted from BouncyCastle PKCS12ParametersGenerator.java
- public class DeriveBytes {
-
- public enum Purpose {
- Key,
- IV,
- MAC
- }
-
- static private byte[] keyDiversifier = { 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
- static private byte[] ivDiversifier = { 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2 };
- static private byte[] macDiversifier = { 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3 };
-
- private string _hashName;
- private int _iterations;
- private byte[] _password;
- private byte[] _salt;
-
- public DeriveBytes () {}
-
- public string HashName {
- get { return _hashName; }
- set { _hashName = value; }
- }
-
- public int IterationCount {
- get { return _iterations; }
- set { _iterations = value; }
- }
-
- public byte[] Password {
- get { return (byte[]) _password.Clone (); }
- set {
- if (value == null)
- _password = new byte [0];
- else
- _password = (byte[]) value.Clone ();
- }
- }
-
- public byte[] Salt {
- get { return (byte[]) _salt.Clone (); }
- set {
- if (value != null)
- _salt = (byte[]) value.Clone ();
- else
- _salt = null;
- }
- }
-
- private void Adjust (byte[] a, int aOff, byte[] b)
- {
- int x = (b[b.Length - 1] & 0xff) + (a [aOff + b.Length - 1] & 0xff) + 1;
-
- a [aOff + b.Length - 1] = (byte) x;
- x >>= 8;
-
- for (int i = b.Length - 2; i >= 0; i--) {
- x += (b [i] & 0xff) + (a [aOff + i] & 0xff);
- a [aOff + i] = (byte) x;
- x >>= 8;
- }
- }
-
- private byte[] Derive (byte[] diversifier, int n)
- {
- HashAlgorithm digest = HashAlgorithm.Create (_hashName);
- int u = (digest.HashSize >> 3); // div 8
- int v = 64;
- byte[] dKey = new byte [n];
-
- byte[] S;
- if ((_salt != null) && (_salt.Length != 0)) {
- S = new byte[v * ((_salt.Length + v - 1) / v)];
-
- for (int i = 0; i != S.Length; i++) {
- S[i] = _salt[i % _salt.Length];
- }
- }
- else {
- S = new byte[0];
- }
-
- byte[] P;
- if ((_password != null) && (_password.Length != 0)) {
- P = new byte[v * ((_password.Length + v - 1) / v)];
-
- for (int i = 0; i != P.Length; i++) {
- P[i] = _password[i % _password.Length];
- }
- }
- else {
- P = new byte[0];
- }
-
- byte[] I = new byte [S.Length + P.Length];
-
- Buffer.BlockCopy (S, 0, I, 0, S.Length);
- Buffer.BlockCopy (P, 0, I, S.Length, P.Length);
-
- byte[] B = new byte[v];
- int c = (n + u - 1) / u;
-
- for (int i = 1; i <= c; i++) {
- digest.TransformBlock (diversifier, 0, diversifier.Length, diversifier, 0);
- digest.TransformFinalBlock (I, 0, I.Length);
- byte[] A = digest.Hash;
- digest.Initialize ();
- for (int j = 1; j != _iterations; j++) {
- A = digest.ComputeHash (A, 0, A.Length);
- }
-
- for (int j = 0; j != B.Length; j++) {
- B [j] = A [j % A.Length];
- }
-
- for (int j = 0; j != I.Length / v; j++) {
- Adjust (I, j * v, B);
- }
-
- if (i == c) {
- Buffer.BlockCopy(A, 0, dKey, (i - 1) * u, dKey.Length - ((i - 1) * u));
- }
- else {
- Buffer.BlockCopy(A, 0, dKey, (i - 1) * u, A.Length);
- }
- }
-
- return dKey;
- }
-
- public byte[] DeriveKey (int size)
- {
- return Derive (keyDiversifier, size);
- }
-
- public byte[] DeriveIV (int size)
- {
- return Derive (ivDiversifier, size);
- }
-
- public byte[] DeriveMAC (int size)
- {
- return Derive (macDiversifier, size);
- }
- }
-
- const int recommendedIterationCount = 2000;
-
- //private int _version;
- private byte[] _password;
- private ArrayList _keyBags;
- private ArrayList _secretBags;
- private X509CertificateCollection _certs;
- private bool _keyBagsChanged;
- private bool _secretBagsChanged;
- private bool _certsChanged;
- private int _iterations;
- private ArrayList _safeBags;
- private RandomNumberGenerator _rng;
-
- // constructors
-
- public PKCS12 ()
- {
- _iterations = recommendedIterationCount;
- _keyBags = new ArrayList ();
- _secretBags = new ArrayList ();
- _certs = new X509CertificateCollection ();
- _keyBagsChanged = false;
- _secretBagsChanged = false;
- _certsChanged = false;
- _safeBags = new ArrayList ();
- }
-
- public PKCS12 (byte[] data)
- : this ()
- {
- Password = null;
- Decode (data);
- }
-
- /*
- * PFX ::= SEQUENCE {
- * version INTEGER {v3(3)}(v3,...),
- * authSafe ContentInfo,
- * macData MacData OPTIONAL
- * }
- *
- * MacData ::= SEQUENCE {
- * mac DigestInfo,
- * macSalt OCTET STRING,
- * iterations INTEGER DEFAULT 1
- * -- Note: The default is for historical reasons and its use is deprecated. A higher
- * -- value, like 1024 is recommended.
- * }
- *
- * SafeContents ::= SEQUENCE OF SafeBag
- *
- * SafeBag ::= SEQUENCE {
- * bagId BAG-TYPE.&id ({PKCS12BagSet}),
- * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
- * bagAttributes SET OF PKCS12Attribute OPTIONAL
- * }
- */
- public PKCS12 (byte[] data, string password)
- : this ()
- {
- Password = password;
- Decode (data);
- }
-
- public PKCS12 (byte[] data, byte[] password)
- : this ()
- {
- _password = password;
- Decode (data);
- }
-
- private void Decode (byte[] data)
- {
- ASN1 pfx = new ASN1 (data);
- if (pfx.Tag != 0x30)
- throw new ArgumentException ("invalid data");
-
- ASN1 version = pfx [0];
- if (version.Tag != 0x02)
- throw new ArgumentException ("invalid PFX version");
- //_version = version.Value [0];
-
- PKCS7.ContentInfo authSafe = new PKCS7.ContentInfo (pfx [1]);
- if (authSafe.ContentType != PKCS7.Oid.data)
- throw new ArgumentException ("invalid authenticated safe");
-
- // now that we know it's a PKCS#12 file, check the (optional) MAC
- // before decoding anything else in the file
- if (pfx.Count > 2) {
- ASN1 macData = pfx [2];
- if (macData.Tag != 0x30)
- throw new ArgumentException ("invalid MAC");
-
- ASN1 mac = macData [0];
- if (mac.Tag != 0x30)
- throw new ArgumentException ("invalid MAC");
- ASN1 macAlgorithm = mac [0];
- string macOid = ASN1Convert.ToOid (macAlgorithm [0]);
- if (macOid != "1.3.14.3.2.26")
- throw new ArgumentException ("unsupported HMAC");
- byte[] macValue = mac [1].Value;
-
- ASN1 macSalt = macData [1];
- if (macSalt.Tag != 0x04)
- throw new ArgumentException ("missing MAC salt");
-
- _iterations = 1; // default value
- if (macData.Count > 2) {
- ASN1 iters = macData [2];
- if (iters.Tag != 0x02)
- throw new ArgumentException ("invalid MAC iteration");
- _iterations = ASN1Convert.ToInt32 (iters);
- }
-
- byte[] authSafeData = authSafe.Content [0].Value;
- byte[] calculatedMac = MAC (_password, macSalt.Value, _iterations, authSafeData);
- if (!Compare (macValue, calculatedMac))
- throw new CryptographicException ("Invalid MAC - file may have been tampered!");
- }
-
- // we now returns to our original presentation - PFX
- ASN1 authenticatedSafe = new ASN1 (authSafe.Content [0].Value);
- for (int i=0; i < authenticatedSafe.Count; i++) {
- PKCS7.ContentInfo ci = new PKCS7.ContentInfo (authenticatedSafe [i]);
- switch (ci.ContentType) {
- case PKCS7.Oid.data:
- // unencrypted (by PKCS#12)
- ASN1 safeContents = new ASN1 (ci.Content [0].Value);
- for (int j=0; j < safeContents.Count; j++) {
- ASN1 safeBag = safeContents [j];
- ReadSafeBag (safeBag);
- }
- break;
- case PKCS7.Oid.encryptedData:
- // password encrypted
- PKCS7.EncryptedData ed = new PKCS7.EncryptedData (ci.Content [0]);
- ASN1 decrypted = new ASN1 (Decrypt (ed));
- for (int j=0; j < decrypted.Count; j++) {
- ASN1 safeBag = decrypted [j];
- ReadSafeBag (safeBag);
- }
- break;
- case PKCS7.Oid.envelopedData:
- // public key encrypted
- throw new NotImplementedException ("public key encrypted");
- default:
- throw new ArgumentException ("unknown authenticatedSafe");
- }
- }
- }
-
- ~PKCS12 ()
- {
- if (_password != null) {
- Array.Clear (_password, 0, _password.Length);
- }
- _password = null;
- }
-
- // properties
-
- public string Password {
- set {
- if (value != null) {
- if (value.Length > 0) {
- int size = value.Length;
- int nul = 0;
- if (size < MaximumPasswordLength) {
- // if not present, add space for a NULL (0x00) character
- if (value[size - 1] != 0x00)
- nul = 1;
- } else {
- size = MaximumPasswordLength;
- }
- _password = new byte[(size + nul) << 1]; // double for unicode
- Encoding.BigEndianUnicode.GetBytes (value, 0, size, _password, 0);
- } else {
- // double-byte (Unicode) NULL (0x00) - see bug #79617
- _password = new byte[2];
- }
- } else {
- // no password
- _password = null;
- }
- }
- }
-
- public int IterationCount {
- get { return _iterations; }
- set { _iterations = value; }
- }
-
- public ArrayList Keys {
- get {
- if (_keyBagsChanged) {
- _keyBags.Clear ();
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (keyBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
- break;
- case 0x30:
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
-
- } else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
- break;
- case 0x30:
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- Array.Clear (decrypted, 0, decrypted.Length);
- }
- }
- _keyBagsChanged = false;
- }
- return ArrayList.ReadOnly(_keyBags);
- }
- }
-
- public ArrayList Secrets {
- get {
- if (_secretBagsChanged) {
- _secretBags.Clear ();
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (secretBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- byte[] secret = bagValue.Value;
- _secretBags.Add(secret);
- }
- }
- _secretBagsChanged = false;
- }
- return ArrayList.ReadOnly(_secretBags);
- }
- }
-
- public X509CertificateCollection Certificates {
- get {
- if (_certsChanged) {
- _certs.Clear ();
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
- _certs.Add (new X509Certificate (cert.Content [0].Value));
- }
- }
- _certsChanged = false;
- }
- return _certs;
- }
- }
-
- internal RandomNumberGenerator RNG {
- get {
- if (_rng == null)
- _rng = RandomNumberGenerator.Create ();
- return _rng;
- }
- }
-
- // private methods
-
- private bool Compare (byte[] expected, byte[] actual)
- {
- bool compare = false;
- if (expected.Length == actual.Length) {
- for (int i=0; i < expected.Length; i++) {
- if (expected [i] != actual [i])
- return false;
- }
- compare = true;
- }
- return compare;
- }
-
- private SymmetricAlgorithm GetSymmetricAlgorithm (string algorithmOid, byte[] salt, int iterationCount)
- {
- string algorithm = null;
- int keyLength = 8; // 64 bits (default)
- int ivLength = 8; // 64 bits (default)
-
- PKCS12.DeriveBytes pd = new PKCS12.DeriveBytes ();
- pd.Password = _password;
- pd.Salt = salt;
- pd.IterationCount = iterationCount;
-
- switch (algorithmOid) {
- case PKCS5.pbeWithMD2AndDESCBC: // no unit test available
- pd.HashName = "MD2";
- algorithm = "DES";
- break;
- case PKCS5.pbeWithMD5AndDESCBC: // no unit test available
- pd.HashName = "MD5";
- algorithm = "DES";
- break;
- case PKCS5.pbeWithMD2AndRC2CBC: // no unit test available
- // TODO - RC2-CBC-Parameter (PKCS5)
- // if missing default to 32 bits !!!
- pd.HashName = "MD2";
- algorithm = "RC2";
- keyLength = 4; // default
- break;
- case PKCS5.pbeWithMD5AndRC2CBC: // no unit test available
- // TODO - RC2-CBC-Parameter (PKCS5)
- // if missing default to 32 bits !!!
- pd.HashName = "MD5";
- algorithm = "RC2";
- keyLength = 4; // default
- break;
- case PKCS5.pbeWithSHA1AndDESCBC: // no unit test available
- pd.HashName = "SHA1";
- algorithm = "DES";
- break;
- case PKCS5.pbeWithSHA1AndRC2CBC: // no unit test available
- // TODO - RC2-CBC-Parameter (PKCS5)
- // if missing default to 32 bits !!!
- pd.HashName = "SHA1";
- algorithm = "RC2";
- keyLength = 4; // default
- break;
- case PKCS12.pbeWithSHAAnd128BitRC4: // no unit test available
- pd.HashName = "SHA1";
- algorithm = "RC4";
- keyLength = 16;
- ivLength = 0; // N/A
- break;
- case PKCS12.pbeWithSHAAnd40BitRC4: // no unit test available
- pd.HashName = "SHA1";
- algorithm = "RC4";
- keyLength = 5;
- ivLength = 0; // N/A
- break;
- case PKCS12.pbeWithSHAAnd3KeyTripleDESCBC:
- pd.HashName = "SHA1";
- algorithm = "TripleDES";
- keyLength = 24;
- break;
- case PKCS12.pbeWithSHAAnd2KeyTripleDESCBC: // no unit test available
- pd.HashName = "SHA1";
- algorithm = "TripleDES";
- keyLength = 16;
- break;
- case PKCS12.pbeWithSHAAnd128BitRC2CBC: // no unit test available
- pd.HashName = "SHA1";
- algorithm = "RC2";
- keyLength = 16;
- break;
- case PKCS12.pbeWithSHAAnd40BitRC2CBC:
- pd.HashName = "SHA1";
- algorithm = "RC2";
- keyLength = 5;
- break;
- default:
- throw new NotSupportedException ("unknown oid " + algorithm);
- }
-
- SymmetricAlgorithm sa = SymmetricAlgorithm.Create (algorithm);
- sa.Key = pd.DeriveKey (keyLength);
- // IV required only for block ciphers (not stream ciphers)
- if (ivLength > 0) {
- sa.IV = pd.DeriveIV (ivLength);
- sa.Mode = CipherMode.CBC;
- }
- return sa;
- }
-
- public byte[] Decrypt (string algorithmOid, byte[] salt, int iterationCount, byte[] encryptedData)
- {
- SymmetricAlgorithm sa = null;
- byte[] result = null;
- try {
- sa = GetSymmetricAlgorithm (algorithmOid, salt, iterationCount);
- ICryptoTransform ct = sa.CreateDecryptor ();
- result = ct.TransformFinalBlock (encryptedData, 0, encryptedData.Length);
- }
- finally {
- if (sa != null)
- sa.Clear ();
- }
- return result;
- }
-
- public byte[] Decrypt (PKCS7.EncryptedData ed)
- {
- return Decrypt (ed.EncryptionAlgorithm.ContentType,
- ed.EncryptionAlgorithm.Content [0].Value,
- ASN1Convert.ToInt32 (ed.EncryptionAlgorithm.Content [1]),
- ed.EncryptedContent);
- }
-
- public byte[] Encrypt (string algorithmOid, byte[] salt, int iterationCount, byte[] data)
- {
- byte[] result = null;
- using (SymmetricAlgorithm sa = GetSymmetricAlgorithm (algorithmOid, salt, iterationCount)) {
- ICryptoTransform ct = sa.CreateEncryptor ();
- result = ct.TransformFinalBlock (data, 0, data.Length);
- }
- return result;
- }
-
- private DSAParameters GetExistingParameters (out bool found)
- {
- foreach (X509Certificate cert in Certificates) {
- // FIXME: that won't work if parts of the parameters are missing
- if (cert.KeyAlgorithmParameters != null) {
- DSA dsa = cert.DSA;
- if (dsa != null) {
- found = true;
- return dsa.ExportParameters (false);
- }
- }
- }
- found = false;
- return new DSAParameters ();
- }
-
- private void AddPrivateKey (PKCS8.PrivateKeyInfo pki)
- {
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- bool found;
- DSAParameters p = GetExistingParameters (out found);
- if (found) {
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p));
- }
- break;
- case 0x30:
- _keyBags.Add (PKCS8.PrivateKeyInfo.DecodeRSA (privateKey));
- break;
- default:
- Array.Clear (privateKey, 0, privateKey.Length);
- throw new CryptographicException ("Unknown private key format");
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- }
-
- private void ReadSafeBag (ASN1 safeBag)
- {
- if (safeBag.Tag != 0x30)
- throw new ArgumentException ("invalid safeBag");
-
- ASN1 bagId = safeBag [0];
- if (bagId.Tag != 0x06)
- throw new ArgumentException ("invalid safeBag id");
-
- ASN1 bagValue = safeBag [1];
- string oid = ASN1Convert.ToOid (bagId);
- switch (oid) {
- case keyBag:
- // NEED UNIT TEST
- AddPrivateKey (new PKCS8.PrivateKeyInfo (bagValue.Value));
- break;
- case pkcs8ShroudedKeyBag:
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- AddPrivateKey (new PKCS8.PrivateKeyInfo (decrypted));
- Array.Clear (decrypted, 0, decrypted.Length);
- break;
- case certBag:
- PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
- if (cert.ContentType != x509Certificate)
- throw new NotSupportedException ("unsupport certificate type");
- X509Certificate x509 = new X509Certificate (cert.Content [0].Value);
- _certs.Add (x509);
- break;
- case crlBag:
- // TODO
- break;
- case secretBag:
- byte[] secret = bagValue.Value;
- _secretBags.Add(secret);
- break;
- case safeContentsBag:
- // TODO - ? recurse ?
- break;
- default:
- throw new ArgumentException ("unknown safeBag oid");
- }
-
- if (safeBag.Count > 2) {
- ASN1 bagAttributes = safeBag [2];
- if (bagAttributes.Tag != 0x31)
- throw new ArgumentException ("invalid safeBag attributes id");
-
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes[i];
-
- if (pkcs12Attribute.Tag != 0x30)
- throw new ArgumentException ("invalid PKCS12 attributes id");
-
- ASN1 attrId = pkcs12Attribute [0];
- if (attrId.Tag != 0x06)
- throw new ArgumentException ("invalid attribute id");
-
- string attrOid = ASN1Convert.ToOid (attrId);
-
- ASN1 attrValues = pkcs12Attribute[1];
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues[j];
-
- switch (attrOid) {
- case PKCS9.friendlyName:
- if (attrValue.Tag != 0x1e)
- throw new ArgumentException ("invalid attribute value id");
- break;
- case PKCS9.localKeyId:
- if (attrValue.Tag != 0x04)
- throw new ArgumentException ("invalid attribute value id");
- break;
- default:
- // Unknown OID -- don't check Tag
- break;
- }
- }
- }
- }
-
- _safeBags.Add (new SafeBag(oid, safeBag));
- }
-
- private ASN1 Pkcs8ShroudedKeyBagSafeBag (AsymmetricAlgorithm aa, IDictionary attributes)
- {
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo ();
- if (aa is RSA) {
- pki.Algorithm = "1.2.840.113549.1.1.1";
- pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((RSA)aa);
- }
- else if (aa is DSA) {
- pki.Algorithm = null;
- pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((DSA)aa);
- }
- else
- throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());
-
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo ();
- epki.Algorithm = pbeWithSHAAnd3KeyTripleDESCBC;
- epki.IterationCount = _iterations;
- epki.EncryptedData = Encrypt (pbeWithSHAAnd3KeyTripleDESCBC, epki.Salt, _iterations, pki.GetBytes ());
-
- ASN1 safeBag = new ASN1 (0x30);
- safeBag.Add (ASN1Convert.FromOid (pkcs8ShroudedKeyBag));
- ASN1 bagValue = new ASN1 (0xA0);
- bagValue.Add (new ASN1 (epki.GetBytes ()));
- safeBag.Add (bagValue);
-
- if (attributes != null) {
- ASN1 bagAttributes = new ASN1 (0x31);
- IDictionaryEnumerator de = attributes.GetEnumerator ();
-
- while (de.MoveNext ()) {
- string oid = (string)de.Key;
- switch (oid) {
- case PKCS9.friendlyName:
- ArrayList names = (ArrayList)de.Value;
- if (names.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] name in names) {
- ASN1 attrValue = new ASN1 (0x1e);
- attrValue.Value = name;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- case PKCS9.localKeyId:
- ArrayList keys = (ArrayList)de.Value;
- if (keys.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] key in keys) {
- ASN1 attrValue = new ASN1 (0x04);
- attrValue.Value = key;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- default:
- break;
- }
- }
-
- if (bagAttributes.Count > 0) {
- safeBag.Add (bagAttributes);
- }
- }
-
- return safeBag;
- }
-
- private ASN1 KeyBagSafeBag (AsymmetricAlgorithm aa, IDictionary attributes)
- {
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo ();
- if (aa is RSA) {
- pki.Algorithm = "1.2.840.113549.1.1.1";
- pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((RSA)aa);
- }
- else if (aa is DSA) {
- pki.Algorithm = null;
- pki.PrivateKey = PKCS8.PrivateKeyInfo.Encode ((DSA)aa);
- }
- else
- throw new CryptographicException ("Unknown asymmetric algorithm {0}", aa.ToString ());
-
- ASN1 safeBag = new ASN1 (0x30);
- safeBag.Add (ASN1Convert.FromOid (keyBag));
- ASN1 bagValue = new ASN1 (0xA0);
- bagValue.Add (new ASN1 (pki.GetBytes ()));
- safeBag.Add (bagValue);
-
- if (attributes != null) {
- ASN1 bagAttributes = new ASN1 (0x31);
- IDictionaryEnumerator de = attributes.GetEnumerator ();
-
- while (de.MoveNext ()) {
- string oid = (string)de.Key;
- switch (oid) {
- case PKCS9.friendlyName:
- ArrayList names = (ArrayList)de.Value;
- if (names.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] name in names) {
- ASN1 attrValue = new ASN1 (0x1e);
- attrValue.Value = name;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- case PKCS9.localKeyId:
- ArrayList keys = (ArrayList)de.Value;
- if (keys.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] key in keys) {
- ASN1 attrValue = new ASN1 (0x04);
- attrValue.Value = key;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- default:
- break;
- }
- }
-
- if (bagAttributes.Count > 0) {
- safeBag.Add (bagAttributes);
- }
- }
-
- return safeBag;
- }
-
- private ASN1 SecretBagSafeBag (byte[] secret, IDictionary attributes)
- {
- ASN1 safeBag = new ASN1 (0x30);
- safeBag.Add (ASN1Convert.FromOid (secretBag));
- ASN1 bagValue = new ASN1 (0x80, secret);
- safeBag.Add (bagValue);
-
- if (attributes != null) {
- ASN1 bagAttributes = new ASN1 (0x31);
- IDictionaryEnumerator de = attributes.GetEnumerator ();
-
- while (de.MoveNext ()) {
- string oid = (string)de.Key;
- switch (oid) {
- case PKCS9.friendlyName:
- ArrayList names = (ArrayList)de.Value;
- if (names.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] name in names) {
- ASN1 attrValue = new ASN1 (0x1e);
- attrValue.Value = name;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- case PKCS9.localKeyId:
- ArrayList keys = (ArrayList)de.Value;
- if (keys.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] key in keys) {
- ASN1 attrValue = new ASN1 (0x04);
- attrValue.Value = key;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- default:
- break;
- }
- }
-
- if (bagAttributes.Count > 0) {
- safeBag.Add (bagAttributes);
- }
- }
-
- return safeBag;
- }
-
- private ASN1 CertificateSafeBag (X509Certificate x509, IDictionary attributes)
- {
- ASN1 encapsulatedCertificate = new ASN1 (0x04, x509.RawData);
-
- PKCS7.ContentInfo ci = new PKCS7.ContentInfo ();
- ci.ContentType = x509Certificate;
- ci.Content.Add (encapsulatedCertificate);
-
- ASN1 bagValue = new ASN1 (0xA0);
- bagValue.Add (ci.ASN1);
-
- ASN1 safeBag = new ASN1 (0x30);
- safeBag.Add (ASN1Convert.FromOid (certBag));
- safeBag.Add (bagValue);
-
- if (attributes != null) {
- ASN1 bagAttributes = new ASN1 (0x31);
- IDictionaryEnumerator de = attributes.GetEnumerator ();
-
- while (de.MoveNext ()) {
- string oid = (string)de.Key;
- switch (oid) {
- case PKCS9.friendlyName:
- ArrayList names = (ArrayList)de.Value;
- if (names.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.friendlyName));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] name in names) {
- ASN1 attrValue = new ASN1 (0x1e);
- attrValue.Value = name;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- case PKCS9.localKeyId:
- ArrayList keys = (ArrayList)de.Value;
- if (keys.Count > 0) {
- ASN1 pkcs12Attribute = new ASN1 (0x30);
- pkcs12Attribute.Add (ASN1Convert.FromOid (PKCS9.localKeyId));
- ASN1 attrValues = new ASN1 (0x31);
- foreach (byte[] key in keys) {
- ASN1 attrValue = new ASN1 (0x04);
- attrValue.Value = key;
- attrValues.Add (attrValue);
- }
- pkcs12Attribute.Add (attrValues);
- bagAttributes.Add (pkcs12Attribute);
- }
- break;
- default:
- break;
- }
- }
-
- if (bagAttributes.Count > 0) {
- safeBag.Add (bagAttributes);
- }
- }
-
- return safeBag;
- }
-
- private byte[] MAC (byte[] password, byte[] salt, int iterations, byte[] data)
- {
- PKCS12.DeriveBytes pd = new PKCS12.DeriveBytes ();
- pd.HashName = "SHA1";
- pd.Password = password;
- pd.Salt = salt;
- pd.IterationCount = iterations;
-
- HMACSHA1 hmac = (HMACSHA1) HMACSHA1.Create ();
- hmac.Key = pd.DeriveMAC (20);
- return hmac.ComputeHash (data, 0, data.Length);
- }
-
- /*
- * SafeContents ::= SEQUENCE OF SafeBag
- *
- * SafeBag ::= SEQUENCE {
- * bagId BAG-TYPE.&id ({PKCS12BagSet}),
- * bagValue [0] EXPLICIT BAG-TYPE.&Type({PKCS12BagSet}{@bagId}),
- * bagAttributes SET OF PKCS12Attribute OPTIONAL
- * }
- */
- public byte[] GetBytes ()
- {
- // TODO (incomplete)
- ASN1 safeBagSequence = new ASN1 (0x30);
-
- // Sync Safe Bag list since X509CertificateCollection may be updated
- ArrayList scs = new ArrayList ();
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo cert = new PKCS7.ContentInfo (bagValue.Value);
- scs.Add (new X509Certificate (cert.Content [0].Value));
- }
- }
-
- ArrayList addcerts = new ArrayList ();
- ArrayList removecerts = new ArrayList ();
-
- foreach (X509Certificate c in Certificates) {
- bool found = false;
-
- foreach (X509Certificate lc in scs) {
- if (Compare (c.RawData, lc.RawData)) {
- found = true;
- }
- }
-
- if (!found) {
- addcerts.Add (c);
- }
- }
- foreach (X509Certificate c in scs) {
- bool found = false;
-
- foreach (X509Certificate lc in Certificates) {
- if (Compare (c.RawData, lc.RawData)) {
- found = true;
- }
- }
-
- if (!found) {
- removecerts.Add (c);
- }
- }
-
- foreach (X509Certificate c in removecerts) {
- RemoveCertificate (c);
- }
-
- foreach (X509Certificate c in addcerts) {
- AddCertificate (c);
- }
- // Sync done
-
- if (_safeBags.Count > 0) {
- ASN1 certsSafeBag = new ASN1 (0x30);
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (certBag)) {
- certsSafeBag.Add (sb.ASN1);
- }
- }
-
- if (certsSafeBag.Count > 0) {
- PKCS7.ContentInfo contentInfo = EncryptedContentInfo (certsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
- safeBagSequence.Add (contentInfo.ASN1);
- }
- }
-
- if (_safeBags.Count > 0) {
- ASN1 safeContents = new ASN1 (0x30);
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (keyBag) ||
- sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- safeContents.Add (sb.ASN1);
- }
- }
- if (safeContents.Count > 0) {
- ASN1 content = new ASN1 (0xA0);
- content.Add (new ASN1 (0x04, safeContents.GetBytes ()));
-
- PKCS7.ContentInfo keyBag = new PKCS7.ContentInfo (PKCS7.Oid.data);
- keyBag.Content = content;
- safeBagSequence.Add (keyBag.ASN1);
- }
- }
-
- // Doing SecretBags separately in case we want to change their encryption independently.
- if (_safeBags.Count > 0) {
- ASN1 secretsSafeBag = new ASN1 (0x30);
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (secretBag)) {
- secretsSafeBag.Add (sb.ASN1);
- }
- }
-
- if (secretsSafeBag.Count > 0) {
- PKCS7.ContentInfo contentInfo = EncryptedContentInfo (secretsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
- safeBagSequence.Add (contentInfo.ASN1);
- }
- }
-
-
- ASN1 encapsulates = new ASN1 (0x04, safeBagSequence.GetBytes ());
- ASN1 ci = new ASN1 (0xA0);
- ci.Add (encapsulates);
- PKCS7.ContentInfo authSafe = new PKCS7.ContentInfo (PKCS7.Oid.data);
- authSafe.Content = ci;
-
- ASN1 macData = new ASN1 (0x30);
- if (_password != null) {
- // only for password based encryption
- byte[] salt = new byte [20];
- RNG.GetBytes (salt);
- byte[] macValue = MAC (_password, salt, _iterations, authSafe.Content [0].Value);
- ASN1 oidSeq = new ASN1 (0x30);
- oidSeq.Add (ASN1Convert.FromOid ("1.3.14.3.2.26")); // SHA1
- oidSeq.Add (new ASN1 (0x05));
-
- ASN1 mac = new ASN1 (0x30);
- mac.Add (oidSeq);
- mac.Add (new ASN1 (0x04, macValue));
-
- macData.Add (mac);
- macData.Add (new ASN1 (0x04, salt));
- macData.Add (ASN1Convert.FromInt32 (_iterations));
- }
-
- ASN1 version = new ASN1 (0x02, new byte [1] { 0x03 });
-
- ASN1 pfx = new ASN1 (0x30);
- pfx.Add (version);
- pfx.Add (authSafe.ASN1);
- if (macData.Count > 0) {
- // only for password based encryption
- pfx.Add (macData);
- }
-
- return pfx.GetBytes ();
- }
-
- // Creates an encrypted PKCS#7 ContentInfo with safeBags as its SafeContents. Used in GetBytes(), above.
- private PKCS7.ContentInfo EncryptedContentInfo(ASN1 safeBags, string algorithmOid)
- {
- byte[] salt = new byte [8];
- RNG.GetBytes (salt);
-
- ASN1 seqParams = new ASN1 (0x30);
- seqParams.Add (new ASN1 (0x04, salt));
- seqParams.Add (ASN1Convert.FromInt32 (_iterations));
-
- ASN1 seqPbe = new ASN1 (0x30);
- seqPbe.Add (ASN1Convert.FromOid (algorithmOid));
- seqPbe.Add (seqParams);
-
- byte[] encrypted = Encrypt (algorithmOid, salt, _iterations, safeBags.GetBytes ());
- ASN1 encryptedContent = new ASN1 (0x80, encrypted);
-
- ASN1 seq = new ASN1 (0x30);
- seq.Add (ASN1Convert.FromOid (PKCS7.Oid.data));
- seq.Add (seqPbe);
- seq.Add (encryptedContent);
-
- ASN1 version = new ASN1 (0x02, new byte [1] { 0x00 });
- ASN1 encData = new ASN1 (0x30);
- encData.Add (version);
- encData.Add (seq);
-
- ASN1 finalContent = new ASN1 (0xA0);
- finalContent.Add (encData);
-
- PKCS7.ContentInfo bag = new PKCS7.ContentInfo (PKCS7.Oid.encryptedData);
- bag.Content = finalContent;
- return bag;
- }
-
- public void AddCertificate (X509Certificate cert)
- {
- AddCertificate (cert, null);
- }
-
- public void AddCertificate (X509Certificate cert, IDictionary attributes)
- {
- bool found = false;
-
- for (int i = 0; !found && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
- X509Certificate c = new X509Certificate (crt.Content [0].Value);
- if (Compare (cert.RawData, c.RawData)) {
- found = true;
- }
- }
- }
-
- if (!found) {
- _safeBags.Add (new SafeBag (certBag, CertificateSafeBag (cert, attributes)));
- _certsChanged = true;
- }
- }
-
- public void RemoveCertificate (X509Certificate cert)
- {
- RemoveCertificate (cert, null);
- }
-
- public void RemoveCertificate (X509Certificate cert, IDictionary attrs)
- {
- int certIndex = -1;
-
- for (int i = 0; certIndex == -1 && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
- X509Certificate c = new X509Certificate (crt.Content [0].Value);
- if (Compare (cert.RawData, c.RawData)) {
- if (attrs != null) {
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
- int bagAttributesFound = 0;
- for (int j = 0; j < bagAttributes.Count; j++) {
- ASN1 pkcs12Attribute = bagAttributes [j];
- ASN1 attrId = pkcs12Attribute [0];
- string ao = ASN1Convert.ToOid (attrId);
- ArrayList dattrValues = (ArrayList)attrs [ao];
-
- if (dattrValues != null) {
- ASN1 attrValues = pkcs12Attribute [1];
-
- if (dattrValues.Count == attrValues.Count) {
- int attrValuesFound = 0;
- for (int k = 0; k < attrValues.Count; k++) {
- ASN1 attrValue = attrValues [k];
- byte[] value = (byte[])dattrValues [k];
-
- if (Compare (value, attrValue.Value)) {
- attrValuesFound += 1;
- }
- }
- if (attrValuesFound == attrValues.Count) {
- bagAttributesFound += 1;
- }
- }
- }
- }
- if (bagAttributesFound == bagAttributes.Count) {
- certIndex = i;
- }
- }
- } else {
- certIndex = i;
- }
- }
- }
- }
-
- if (certIndex != -1) {
- _safeBags.RemoveAt (certIndex);
- _certsChanged = true;
- }
- }
-
- private bool CompareAsymmetricAlgorithm (AsymmetricAlgorithm a1, AsymmetricAlgorithm a2)
- {
- // fast path
- if (a1.KeySize != a2.KeySize)
- return false;
- // compare public keys - if they match we can assume the private match too
- return (a1.ToXmlString (false) == a2.ToXmlString (false));
- }
-
- public void AddPkcs8ShroudedKeyBag (AsymmetricAlgorithm aa)
- {
- AddPkcs8ShroudedKeyBag (aa, null);
- }
-
- public void AddPkcs8ShroudedKeyBag (AsymmetricAlgorithm aa, IDictionary attributes)
- {
- bool found = false;
-
- for (int i = 0; !found && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
- byte[] privateKey = pki.PrivateKey;
-
- AsymmetricAlgorithm saa = null;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- Array.Clear (decrypted, 0, decrypted.Length);
- Array.Clear (privateKey, 0, privateKey.Length);
- throw new CryptographicException ("Unknown private key format");
- }
-
- Array.Clear (decrypted, 0, decrypted.Length);
- Array.Clear (privateKey, 0, privateKey.Length);
-
- if (CompareAsymmetricAlgorithm (aa , saa)) {
- found = true;
- }
- }
- }
-
- if (!found) {
- _safeBags.Add (new SafeBag (pkcs8ShroudedKeyBag, Pkcs8ShroudedKeyBagSafeBag (aa, attributes)));
- _keyBagsChanged = true;
- }
- }
-
- public void RemovePkcs8ShroudedKeyBag (AsymmetricAlgorithm aa)
- {
- int aaIndex = -1;
-
- for (int i = 0; aaIndex == -1 && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
- byte[] privateKey = pki.PrivateKey;
-
- AsymmetricAlgorithm saa = null;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- Array.Clear (decrypted, 0, decrypted.Length);
- Array.Clear (privateKey, 0, privateKey.Length);
- throw new CryptographicException ("Unknown private key format");
- }
-
- Array.Clear (decrypted, 0, decrypted.Length);
- Array.Clear (privateKey, 0, privateKey.Length);
-
- if (CompareAsymmetricAlgorithm (aa, saa)) {
- aaIndex = i;
- }
- }
- }
-
- if (aaIndex != -1) {
- _safeBags.RemoveAt (aaIndex);
- _keyBagsChanged = true;
- }
- }
-
- public void AddKeyBag (AsymmetricAlgorithm aa)
- {
- AddKeyBag (aa, null);
- }
-
- public void AddKeyBag (AsymmetricAlgorithm aa, IDictionary attributes)
- {
- bool found = false;
-
- for (int i = 0; !found && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (keyBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
- byte[] privateKey = pki.PrivateKey;
-
- AsymmetricAlgorithm saa = null;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- Array.Clear (privateKey, 0, privateKey.Length);
- throw new CryptographicException ("Unknown private key format");
- }
-
- Array.Clear (privateKey, 0, privateKey.Length);
-
- if (CompareAsymmetricAlgorithm (aa, saa)) {
- found = true;
- }
- }
- }
-
- if (!found) {
- _safeBags.Add (new SafeBag (keyBag, KeyBagSafeBag (aa, attributes)));
- _keyBagsChanged = true;
- }
- }
-
- public void RemoveKeyBag (AsymmetricAlgorithm aa)
- {
- int aaIndex = -1;
-
- for (int i = 0; aaIndex == -1 && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (keyBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
- byte[] privateKey = pki.PrivateKey;
-
- AsymmetricAlgorithm saa = null;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- Array.Clear (privateKey, 0, privateKey.Length);
- throw new CryptographicException ("Unknown private key format");
- }
-
- Array.Clear (privateKey, 0, privateKey.Length);
-
- if (CompareAsymmetricAlgorithm (aa, saa)) {
- aaIndex = i;
- }
- }
- }
-
- if (aaIndex != -1) {
- _safeBags.RemoveAt (aaIndex);
- _keyBagsChanged = true;
- }
- }
-
- public void AddSecretBag (byte[] secret)
- {
- AddSecretBag (secret, null);
- }
-
- public void AddSecretBag (byte[] secret, IDictionary attributes)
- {
- bool found = false;
-
- for (int i = 0; !found && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (secretBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- byte[] ssecret = bagValue.Value;
-
- if (Compare (secret, ssecret)) {
- found = true;
- }
- }
- }
-
- if (!found) {
- _safeBags.Add (new SafeBag (secretBag, SecretBagSafeBag (secret, attributes)));
- _secretBagsChanged = true;
- }
- }
-
- public void RemoveSecretBag (byte[] secret)
- {
- int sIndex = -1;
-
- for (int i = 0; sIndex == -1 && i < _safeBags.Count; i++) {
- SafeBag sb = (SafeBag)_safeBags [i];
-
- if (sb.BagOID.Equals (secretBag)) {
- ASN1 bagValue = sb.ASN1 [1];
- byte[] ssecret = bagValue.Value;
-
- if (Compare (secret, ssecret)) {
- sIndex = i;
- }
- }
- }
-
- if (sIndex != -1) {
- _safeBags.RemoveAt (sIndex);
- _secretBagsChanged = true;
- }
- }
-
- public AsymmetricAlgorithm GetAsymmetricAlgorithm (IDictionary attrs)
- {
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- ASN1 safeBag = sb.ASN1;
-
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
-
- int bagAttributesFound = 0;
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes [i];
- ASN1 attrId = pkcs12Attribute [0];
- string ao = ASN1Convert.ToOid (attrId);
- ArrayList dattrValues = (ArrayList)attrs [ao];
-
- if (dattrValues != null) {
- ASN1 attrValues = pkcs12Attribute [1];
-
- if (dattrValues.Count == attrValues.Count) {
- int attrValuesFound = 0;
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues [j];
- byte[] value = (byte[])dattrValues [j];
-
- if (Compare (value, attrValue.Value)) {
- attrValuesFound += 1;
- }
- }
- if (attrValuesFound == attrValues.Count) {
- bagAttributesFound += 1;
- }
- }
- }
- }
- if (bagAttributesFound == bagAttributes.Count) {
- ASN1 bagValue = safeBag [1];
- AsymmetricAlgorithm aa = null;
- if (sb.BagOID.Equals (keyBag)) {
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- } else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- aa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- aa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- Array.Clear (decrypted, 0, decrypted.Length);
- }
- return aa;
- }
- }
- }
- }
-
- return null;
- }
-
- public byte[] GetSecret (IDictionary attrs)
- {
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (secretBag)) {
- ASN1 safeBag = sb.ASN1;
-
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
-
- int bagAttributesFound = 0;
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes [i];
- ASN1 attrId = pkcs12Attribute [0];
- string ao = ASN1Convert.ToOid (attrId);
- ArrayList dattrValues = (ArrayList)attrs [ao];
-
- if (dattrValues != null) {
- ASN1 attrValues = pkcs12Attribute [1];
-
- if (dattrValues.Count == attrValues.Count) {
- int attrValuesFound = 0;
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues [j];
- byte[] value = (byte[])dattrValues [j];
-
- if (Compare (value, attrValue.Value)) {
- attrValuesFound += 1;
- }
- }
- if (attrValuesFound == attrValues.Count) {
- bagAttributesFound += 1;
- }
- }
- }
- }
- if (bagAttributesFound == bagAttributes.Count) {
- ASN1 bagValue = safeBag [1];
- return bagValue.Value;
- }
- }
- }
- }
-
- return null;
- }
-
- public X509Certificate GetCertificate (IDictionary attrs)
- {
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
-
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
-
- int bagAttributesFound = 0;
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes [i];
- ASN1 attrId = pkcs12Attribute [0];
- string ao = ASN1Convert.ToOid (attrId);
- ArrayList dattrValues = (ArrayList)attrs [ao];
-
- if (dattrValues != null) {
- ASN1 attrValues = pkcs12Attribute [1];
-
- if (dattrValues.Count == attrValues.Count) {
- int attrValuesFound = 0;
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues [j];
- byte[] value = (byte[])dattrValues [j];
-
- if (Compare (value, attrValue.Value)) {
- attrValuesFound += 1;
- }
- }
- if (attrValuesFound == attrValues.Count) {
- bagAttributesFound += 1;
- }
- }
- }
- }
- if (bagAttributesFound == bagAttributes.Count) {
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
- return new X509Certificate (crt.Content [0].Value);
- }
- }
- }
- }
-
- return null;
- }
-
- public IDictionary GetAttributes (AsymmetricAlgorithm aa)
- {
- IDictionary result = new Hashtable ();
-
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (keyBag) || sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- ASN1 safeBag = sb.ASN1;
-
- ASN1 bagValue = safeBag [1];
- AsymmetricAlgorithm saa = null;
- if (sb.BagOID.Equals (keyBag)) {
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (bagValue.Value);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- } else if (sb.BagOID.Equals (pkcs8ShroudedKeyBag)) {
- PKCS8.EncryptedPrivateKeyInfo epki = new PKCS8.EncryptedPrivateKeyInfo (bagValue.Value);
- byte[] decrypted = Decrypt (epki.Algorithm, epki.Salt, epki.IterationCount, epki.EncryptedData);
- PKCS8.PrivateKeyInfo pki = new PKCS8.PrivateKeyInfo (decrypted);
- byte[] privateKey = pki.PrivateKey;
- switch (privateKey [0]) {
- case 0x02:
- DSAParameters p = new DSAParameters (); // FIXME
- saa = PKCS8.PrivateKeyInfo.DecodeDSA (privateKey, p);
- break;
- case 0x30:
- saa = PKCS8.PrivateKeyInfo.DecodeRSA (privateKey);
- break;
- default:
- break;
- }
- Array.Clear (privateKey, 0, privateKey.Length);
- Array.Clear (decrypted, 0, decrypted.Length);
- }
-
- if (saa != null && CompareAsymmetricAlgorithm (saa, aa)) {
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
-
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes [i];
- ASN1 attrId = pkcs12Attribute [0];
- string aOid = ASN1Convert.ToOid (attrId);
- ArrayList aValues = new ArrayList ();
-
- ASN1 attrValues = pkcs12Attribute [1];
-
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues [j];
- aValues.Add (attrValue.Value);
- }
- result.Add (aOid, aValues);
- }
- }
- }
- }
- }
-
- return result;
- }
-
- public IDictionary GetAttributes (X509Certificate cert)
- {
- IDictionary result = new Hashtable ();
-
- foreach (SafeBag sb in _safeBags) {
- if (sb.BagOID.Equals (certBag)) {
- ASN1 safeBag = sb.ASN1;
- ASN1 bagValue = safeBag [1];
- PKCS7.ContentInfo crt = new PKCS7.ContentInfo (bagValue.Value);
- X509Certificate xc = new X509Certificate (crt.Content [0].Value);
-
- if (Compare (cert.RawData, xc.RawData)) {
- if (safeBag.Count == 3) {
- ASN1 bagAttributes = safeBag [2];
-
- for (int i = 0; i < bagAttributes.Count; i++) {
- ASN1 pkcs12Attribute = bagAttributes [i];
- ASN1 attrId = pkcs12Attribute [0];
-
- string aOid = ASN1Convert.ToOid (attrId);
- ArrayList aValues = new ArrayList ();
-
- ASN1 attrValues = pkcs12Attribute [1];
-
- for (int j = 0; j < attrValues.Count; j++) {
- ASN1 attrValue = attrValues [j];
- aValues.Add (attrValue.Value);
- }
- result.Add (aOid, aValues);
- }
- }
- }
- }
- }
-
- return result;
- }
-
- public void SaveToFile (string filename)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
-
- using (FileStream fs = File.Create (filename)) {
- byte[] data = GetBytes ();
- fs.Write (data, 0, data.Length);
- }
- }
-
- public object Clone ()
- {
- PKCS12 clone = null;
- if (_password != null) {
- clone = new PKCS12 (GetBytes (), Encoding.BigEndianUnicode.GetString (_password));
- } else {
- clone = new PKCS12 (GetBytes ());
- }
- clone.IterationCount = this.IterationCount;
-
- return clone;
- }
-
- // static
-
- public const int CryptoApiPasswordLimit = 32;
-
- static private int password_max_length = Int32.MaxValue;
-
- // static properties
-
- // MS CryptoAPI limits the password to a maximum of 31 characters
- // other implementations, like OpenSSL, have no such limitation.
- // Setting a maximum value will truncate the password length to
- // ensure compatibility with MS's PFXImportCertStore API.
- static public int MaximumPasswordLength {
- get { return password_max_length; }
- set {
- if (value < CryptoApiPasswordLimit) {
- string msg = Locale.GetText ("Maximum password length cannot be less than {0}.", CryptoApiPasswordLimit);
- throw new ArgumentOutOfRangeException (msg);
- }
- password_max_length = value;
- }
- }
-
- // static methods
-
- static private byte[] LoadFile (string filename)
- {
- byte[] data = null;
- using (FileStream fs = File.OpenRead (filename)) {
- data = new byte [fs.Length];
- fs.Read (data, 0, data.Length);
- fs.Close ();
- }
- return data;
- }
-
- static public PKCS12 LoadFromFile (string filename)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
-
- return new PKCS12 (LoadFile (filename));
- }
-
- static public PKCS12 LoadFromFile (string filename, string password)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
-
- return new PKCS12 (LoadFile (filename), password);
- }
- }
-}
+++ /dev/null
-//
-// TestAnchors.cs: Trust Anchors for development and debugging
-// include test certificates for Microsoft (root agency) and Mono
-//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
-//
-// (C) 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;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class TestAnchors : TrustAnchors {
-
- static byte[] rootagency = {
- 0x30, 0x82, 0x01, 0xCA, 0x30, 0x82, 0x01, 0x74, 0xA0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x10, 0x06, 0x37, 0x6C, 0x00, 0xAA, 0x00, 0x64, 0x8A, 0x11,
- 0xCF, 0xB8, 0xD4, 0xAA, 0x5C, 0x35, 0xF4, 0x30, 0x0D, 0x06, 0x09, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x16,
- 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0B, 0x52,
- 0x6F, 0x6F, 0x74, 0x20, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x30, 0x1E,
- 0x17, 0x0D, 0x39, 0x36, 0x30, 0x35, 0x32, 0x38, 0x32, 0x32, 0x30, 0x32,
- 0x35, 0x39, 0x5A, 0x17, 0x0D, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32,
- 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12,
- 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0B, 0x52, 0x6F, 0x6F, 0x74, 0x20,
- 0x41, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x30, 0x5B, 0x30, 0x0D, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
- 0x4A, 0x00, 0x30, 0x47, 0x02, 0x40, 0x81, 0x55, 0x22, 0xB9, 0x8A, 0xA4,
- 0x6F, 0xED, 0xD6, 0xE7, 0xD9, 0x66, 0x0F, 0x55, 0xBC, 0xD7, 0xCD, 0xD5,
- 0xBC, 0x4E, 0x40, 0x02, 0x21, 0xA2, 0xB1, 0xF7, 0x87, 0x30, 0x85, 0x5E,
- 0xD2, 0xF2, 0x44, 0xB9, 0xDC, 0x9B, 0x75, 0xB6, 0xFB, 0x46, 0x5F, 0x42,
- 0xB6, 0x9D, 0x23, 0x36, 0x0B, 0xDE, 0x54, 0x0F, 0xCD, 0xBD, 0x1F, 0x99,
- 0x2A, 0x10, 0x58, 0x11, 0xCB, 0x40, 0xCB, 0xB5, 0xA7, 0x41, 0x02, 0x03,
- 0x01, 0x00, 0x01, 0xA3, 0x81, 0x9E, 0x30, 0x81, 0x9B, 0x30, 0x50, 0x06,
- 0x03, 0x55, 0x04, 0x03, 0x04, 0x49, 0x13, 0x47, 0x46, 0x6F, 0x72, 0x20,
- 0x54, 0x65, 0x73, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x50, 0x75, 0x72, 0x70,
- 0x6F, 0x73, 0x65, 0x73, 0x20, 0x4F, 0x6E, 0x6C, 0x79, 0x20, 0x53, 0x61,
- 0x6D, 0x70, 0x6C, 0x65, 0x20, 0x53, 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72,
- 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x73, 0x68, 0x69, 0x6E, 0x67,
- 0x20, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6E, 0x74, 0x69, 0x61, 0x6C, 0x73,
- 0x20, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x30, 0x47, 0x06, 0x03, 0x55,
- 0x1D, 0x01, 0x04, 0x40, 0x30, 0x3E, 0x80, 0x10, 0x12, 0xE4, 0x09, 0x2D,
- 0x06, 0x1D, 0x1D, 0x4F, 0x00, 0x8D, 0x61, 0x21, 0xDC, 0x16, 0x64, 0x63,
- 0xA1, 0x18, 0x30, 0x16, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x13, 0x0B, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x41, 0x67, 0x65, 0x6E,
- 0x63, 0x79, 0x82, 0x10, 0x06, 0x37, 0x6C, 0x00, 0xAA, 0x00, 0x64, 0x8A,
- 0x11, 0xCF, 0xB8, 0xD4, 0xAA, 0x5C, 0x35, 0xF4, 0x30, 0x0D, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03,
- 0x41, 0x00, 0x2D, 0x2E, 0x3E, 0x7B, 0x89, 0x42, 0x89, 0x3F, 0xA8, 0x21,
- 0x17, 0xFA, 0xF0, 0xF5, 0xC3, 0x95, 0xDB, 0x62, 0x69, 0x5B, 0xC9, 0xDC,
- 0xC1, 0xB3, 0xFA, 0xF0, 0xC4, 0x6F, 0x6F, 0x64, 0x9A, 0xBD, 0xE7, 0x1B,
- 0x25, 0x68, 0x72, 0x83, 0x67, 0xBD, 0x56, 0xB0, 0x8D, 0x01, 0xBD, 0x2A,
- 0xF7, 0xCC, 0x4B, 0xBD, 0x87, 0xA5, 0xBA, 0x87, 0x20, 0x4C, 0x42, 0x11,
- 0x41, 0xAD, 0x10, 0x17, 0x3B, 0x8C };
-
- static byte[] monoTestRoot = {
- 0x30, 0x82, 0x01, 0xC2, 0x30, 0x82, 0x01, 0x2B, 0xA0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x10, 0x28, 0xF4, 0x76, 0x38, 0x91, 0x74, 0x0E, 0x48, 0x85,
- 0xC7, 0x6E, 0x88, 0x4F, 0xE1, 0xB0, 0x69, 0x30, 0x0D, 0x06, 0x09, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x20,
- 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x15, 0x4D,
- 0x6F, 0x6E, 0x6F, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F,
- 0x74, 0x20, 0x41, 0x67, 0x65, 0x6E, 0x63, 0x79, 0x30, 0x1E, 0x17, 0x0D,
- 0x30, 0x33, 0x30, 0x39, 0x30, 0x31, 0x31, 0x35, 0x35, 0x35, 0x34, 0x38,
- 0x5A, 0x17, 0x0D, 0x33, 0x39, 0x31, 0x32, 0x33, 0x31, 0x31, 0x38, 0x35,
- 0x39, 0x35, 0x39, 0x5A, 0x30, 0x20, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03,
- 0x55, 0x04, 0x03, 0x13, 0x15, 0x4D, 0x6F, 0x6E, 0x6F, 0x20, 0x54, 0x65,
- 0x73, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x41, 0x67, 0x65, 0x6E,
- 0x63, 0x79, 0x30, 0x81, 0x9E, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8C, 0x00,
- 0x30, 0x81, 0x88, 0x02, 0x81, 0x80, 0xBF, 0xFE, 0x27, 0x00, 0xB0, 0x71,
- 0x08, 0x4F, 0xBD, 0x26, 0x01, 0x02, 0xD0, 0xB9, 0xC3, 0x52, 0xF2, 0xA1,
- 0xE9, 0xEF, 0x7A, 0x3F, 0x04, 0xE9, 0x37, 0x84, 0x63, 0xFA, 0xF5, 0xA7,
- 0xA8, 0xA4, 0xFB, 0x20, 0x0A, 0x75, 0x88, 0xAF, 0xC9, 0x8E, 0xEA, 0xAF,
- 0x02, 0x0E, 0x83, 0x43, 0x6B, 0xD3, 0x7E, 0xFD, 0x1D, 0x4E, 0x5A, 0x9F,
- 0x7E, 0x61, 0xC7, 0xE7, 0x53, 0xB2, 0x8A, 0x8A, 0x6B, 0x71, 0x3E, 0x67,
- 0xCF, 0x17, 0x12, 0x4E, 0xC6, 0x5B, 0xFF, 0xD8, 0xDC, 0x1D, 0x27, 0x06,
- 0xD2, 0xCD, 0xFF, 0x15, 0x12, 0x16, 0x9D, 0x77, 0x8B, 0x93, 0xF7, 0xE0,
- 0x9B, 0xB9, 0x92, 0x62, 0x18, 0xD4, 0x68, 0x73, 0x48, 0xD2, 0x6D, 0x7F,
- 0x35, 0x34, 0xE4, 0xB6, 0x2A, 0x62, 0x72, 0x32, 0xB1, 0xA3, 0xBD, 0x61,
- 0x18, 0x88, 0x3D, 0xAA, 0xE7, 0x02, 0x5A, 0x70, 0xEE, 0x9B, 0xE2, 0xAB,
- 0x87, 0xF9, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A,
- 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81,
- 0x81, 0x00, 0x8E, 0x08, 0xD7, 0x0F, 0x30, 0xB2, 0xFD, 0x3A, 0x5C, 0x94,
- 0xA9, 0x56, 0xBE, 0x44, 0x77, 0xE3, 0xA3, 0x92, 0xBC, 0xB9, 0xE4, 0x95,
- 0x68, 0xD4, 0xF4, 0xF9, 0x24, 0x4B, 0x2A, 0x79, 0x93, 0x57, 0x7E, 0x84,
- 0x50, 0x3F, 0xA9, 0xC8, 0xDA, 0x9E, 0x08, 0x9C, 0x21, 0xE1, 0x10, 0xFC,
- 0x1C, 0x5C, 0x4B, 0x60, 0x97, 0xBA, 0x55, 0xCB, 0x7C, 0xEA, 0xC3, 0x04,
- 0x2F, 0x55, 0xBB, 0x16, 0x26, 0xCD, 0x87, 0x90, 0x30, 0x7F, 0xE0, 0xCF,
- 0x24, 0x27, 0xB4, 0x3A, 0xD0, 0x9F, 0xC7, 0x55, 0xF8, 0x7C, 0xC9, 0xA0,
- 0x72, 0xE4, 0x06, 0xF1, 0x4A, 0x5B, 0xBB, 0x71, 0x84, 0x8B, 0x76, 0x23,
- 0x65, 0x1F, 0x1B, 0xEA, 0x96, 0x85, 0x13, 0x84, 0x0C, 0x8C, 0xCD, 0xDA,
- 0x3D, 0x1F, 0xEB, 0xA9, 0xA7, 0xDF, 0xE0, 0xD1, 0xDC, 0x93, 0x21, 0x7A,
- 0x10, 0xA7, 0x92, 0x63, 0x5D, 0xAB, 0xA2, 0x13, 0x37, 0xA4 };
-
- static TestAnchors ()
- {
- // add Microsoft Test Root for people who used MS makecert to create
- // their Authenticode(tm) test certificates
- coll.Add (new X509Certificate (rootagency));
-
- // add Mono Test Root for people who used Mono makecert to create
- // their Authenticode(tm) test certificates
- coll.Add (new X509Certificate (monoTestRoot));
- }
- }
-}
+++ /dev/null
-//
-// TrustAnchors.cs: "Official" default Trust Anchors for Mono
-//
-// Author:
-// Sebastien Pouliot (spouliot@motus.com)
-//
-// (C) 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;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class TrustAnchors : ITrustAnchors {
-
- static byte[] msroot = {
- 0x30, 0x82, 0x04, 0x12, 0x30, 0x82, 0x02, 0xFA, 0xA0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x0F, 0x00, 0xC1, 0x00, 0x8B, 0x3C, 0x3C, 0x88, 0x11, 0xD1,
- 0x3E, 0xF6, 0x63, 0xEC, 0xDF, 0x40, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86,
- 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x70, 0x31,
- 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22, 0x43, 0x6F,
- 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20,
- 0x31, 0x39, 0x39, 0x37, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
- 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x1E, 0x30, 0x1C,
- 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F,
- 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61,
- 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04,
- 0x03, 0x13, 0x18, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74,
- 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72,
- 0x69, 0x74, 0x79, 0x30, 0x1E, 0x17, 0x0D, 0x39, 0x37, 0x30, 0x31, 0x31,
- 0x30, 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30,
- 0x31, 0x32, 0x33, 0x31, 0x30, 0x37, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x30,
- 0x70, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x22,
- 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63,
- 0x29, 0x20, 0x31, 0x39, 0x39, 0x37, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F,
- 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x2E, 0x31, 0x1E,
- 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x15, 0x4D, 0x69, 0x63,
- 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F,
- 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x21, 0x30, 0x1F, 0x06, 0x03,
- 0x55, 0x04, 0x03, 0x13, 0x18, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F,
- 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x41, 0x75, 0x74, 0x68,
- 0x6F, 0x72, 0x69, 0x74, 0x79, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06,
- 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00,
- 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01,
- 0x01, 0x00, 0xA9, 0x02, 0xBD, 0xC1, 0x70, 0xE6, 0x3B, 0xF2, 0x4E, 0x1B,
- 0x28, 0x9F, 0x97, 0x78, 0x5E, 0x30, 0xEA, 0xA2, 0xA9, 0x8D, 0x25, 0x5F,
- 0xF8, 0xFE, 0x95, 0x4C, 0xA3, 0xB7, 0xFE, 0x9D, 0xA2, 0x20, 0x3E, 0x7C,
- 0x51, 0xA2, 0x9B, 0xA2, 0x8F, 0x60, 0x32, 0x6B, 0xD1, 0x42, 0x64, 0x79,
- 0xEE, 0xAC, 0x76, 0xC9, 0x54, 0xDA, 0xF2, 0xEB, 0x9C, 0x86, 0x1C, 0x8F,
- 0x9F, 0x84, 0x66, 0xB3, 0xC5, 0x6B, 0x7A, 0x62, 0x23, 0xD6, 0x1D, 0x3C,
- 0xDE, 0x0F, 0x01, 0x92, 0xE8, 0x96, 0xC4, 0xBF, 0x2D, 0x66, 0x9A, 0x9A,
- 0x68, 0x26, 0x99, 0xD0, 0x3A, 0x2C, 0xBF, 0x0C, 0xB5, 0x58, 0x26, 0xC1,
- 0x46, 0xE7, 0x0A, 0x3E, 0x38, 0x96, 0x2C, 0xA9, 0x28, 0x39, 0xA8, 0xEC,
- 0x49, 0x83, 0x42, 0xE3, 0x84, 0x0F, 0xBB, 0x9A, 0x6C, 0x55, 0x61, 0xAC,
- 0x82, 0x7C, 0xA1, 0x60, 0x2D, 0x77, 0x4C, 0xE9, 0x99, 0xB4, 0x64, 0x3B,
- 0x9A, 0x50, 0x1C, 0x31, 0x08, 0x24, 0x14, 0x9F, 0xA9, 0xE7, 0x91, 0x2B,
- 0x18, 0xE6, 0x3D, 0x98, 0x63, 0x14, 0x60, 0x58, 0x05, 0x65, 0x9F, 0x1D,
- 0x37, 0x52, 0x87, 0xF7, 0xA7, 0xEF, 0x94, 0x02, 0xC6, 0x1B, 0xD3, 0xBF,
- 0x55, 0x45, 0xB3, 0x89, 0x80, 0xBF, 0x3A, 0xEC, 0x54, 0x94, 0x4E, 0xAE,
- 0xFD, 0xA7, 0x7A, 0x6D, 0x74, 0x4E, 0xAF, 0x18, 0xCC, 0x96, 0x09, 0x28,
- 0x21, 0x00, 0x57, 0x90, 0x60, 0x69, 0x37, 0xBB, 0x4B, 0x12, 0x07, 0x3C,
- 0x56, 0xFF, 0x5B, 0xFB, 0xA4, 0x66, 0x0A, 0x08, 0xA6, 0xD2, 0x81, 0x56,
- 0x57, 0xEF, 0xB6, 0x3B, 0x5E, 0x16, 0x81, 0x77, 0x04, 0xDA, 0xF6, 0xBE,
- 0xAE, 0x80, 0x95, 0xFE, 0xB0, 0xCD, 0x7F, 0xD6, 0xA7, 0x1A, 0x72, 0x5C,
- 0x3C, 0xCA, 0xBC, 0xF0, 0x08, 0xA3, 0x22, 0x30, 0xB3, 0x06, 0x85, 0xC9,
- 0xB3, 0x20, 0x77, 0x13, 0x85, 0xDF, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3,
- 0x81, 0xA8, 0x30, 0x81, 0xA5, 0x30, 0x81, 0xA2, 0x06, 0x03, 0x55, 0x1D,
- 0x01, 0x04, 0x81, 0x9A, 0x30, 0x81, 0x97, 0x80, 0x10, 0x5B, 0xD0, 0x70,
- 0xEF, 0x69, 0x72, 0x9E, 0x23, 0x51, 0x7E, 0x14, 0xB2, 0x4D, 0x8E, 0xFF,
- 0xCB, 0xA1, 0x72, 0x30, 0x70, 0x31, 0x2B, 0x30, 0x29, 0x06, 0x03, 0x55,
- 0x04, 0x0B, 0x13, 0x22, 0x43, 0x6F, 0x70, 0x79, 0x72, 0x69, 0x67, 0x68,
- 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, 0x31, 0x39, 0x39, 0x37, 0x20, 0x4D,
- 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72,
- 0x70, 0x2E, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
- 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43,
- 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x21,
- 0x30, 0x1F, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x18, 0x4D, 0x69, 0x63,
- 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20,
- 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, 0x82, 0x0F, 0x00,
- 0xC1, 0x00, 0x8B, 0x3C, 0x3C, 0x88, 0x11, 0xD1, 0x3E, 0xF6, 0x63, 0xEC,
- 0xDF, 0x40, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x95, 0xE8,
- 0x0B, 0xC0, 0x8D, 0xF3, 0x97, 0x18, 0x35, 0xED, 0xB8, 0x01, 0x24, 0xD8,
- 0x77, 0x11, 0xF3, 0x5C, 0x60, 0x32, 0x9F, 0x9E, 0x0B, 0xCB, 0x3E, 0x05,
- 0x91, 0x88, 0x8F, 0xC9, 0x3A, 0xE6, 0x21, 0xF2, 0xF0, 0x57, 0x93, 0x2C,
- 0xB5, 0xA0, 0x47, 0xC8, 0x62, 0xEF, 0xFC, 0xD7, 0xCC, 0x3B, 0x3B, 0x5A,
- 0xA9, 0x36, 0x54, 0x69, 0xFE, 0x24, 0x6D, 0x3F, 0xC9, 0xCC, 0xAA, 0xDE,
- 0x05, 0x7C, 0xDD, 0x31, 0x8D, 0x3D, 0x9F, 0x10, 0x70, 0x6A, 0xBB, 0xFE,
- 0x12, 0x4F, 0x18, 0x69, 0xC0, 0xFC, 0xD0, 0x43, 0xE3, 0x11, 0x5A, 0x20,
- 0x4F, 0xEA, 0x62, 0x7B, 0xAF, 0xAA, 0x19, 0xC8, 0x2B, 0x37, 0x25, 0x2D,
- 0xBE, 0x65, 0xA1, 0x12, 0x8A, 0x25, 0x0F, 0x63, 0xA3, 0xF7, 0x54, 0x1C,
- 0xF9, 0x21, 0xC9, 0xD6, 0x15, 0xF3, 0x52, 0xAC, 0x6E, 0x43, 0x32, 0x07,
- 0xFD, 0x82, 0x17, 0xF8, 0xE5, 0x67, 0x6C, 0x0D, 0x51, 0xF6, 0xBD, 0xF1,
- 0x52, 0xC7, 0xBD, 0xE7, 0xC4, 0x30, 0xFC, 0x20, 0x31, 0x09, 0x88, 0x1D,
- 0x95, 0x29, 0x1A, 0x4D, 0xD5, 0x1D, 0x02, 0xA5, 0xF1, 0x80, 0xE0, 0x03,
- 0xB4, 0x5B, 0xF4, 0xB1, 0xDD, 0xC8, 0x57, 0xEE, 0x65, 0x49, 0xC7, 0x52,
- 0x54, 0xB6, 0xB4, 0x03, 0x28, 0x12, 0xFF, 0x90, 0xD6, 0xF0, 0x08, 0x8F,
- 0x7E, 0xB8, 0x97, 0xC5, 0xAB, 0x37, 0x2C, 0xE4, 0x7A, 0xE4, 0xA8, 0x77,
- 0xE3, 0x76, 0xA0, 0x00, 0xD0, 0x6A, 0x3F, 0xC1, 0xD2, 0x36, 0x8A, 0xE0,
- 0x41, 0x12, 0xA8, 0x35, 0x6A, 0x1B, 0x6A, 0xDB, 0x35, 0xE1, 0xD4, 0x1C,
- 0x04, 0xE4, 0xA8, 0x45, 0x04, 0xC8, 0x5A, 0x33, 0x38, 0x6E, 0x4D, 0x1C,
- 0x0D, 0x62, 0xB7, 0x0A, 0xA2, 0x8C, 0xD3, 0xD5, 0x54, 0x3F, 0x46, 0xCD,
- 0x1C, 0x55, 0xA6, 0x70, 0xDB, 0x12, 0x3A, 0x87, 0x93, 0x75, 0x9F, 0xA7,
- 0xD2, 0xA0 };
-
- static byte[] verisign = {
- 0x30, 0x82, 0x02, 0x40, 0x30, 0x82, 0x01, 0xA9, 0x02, 0x10, 0x03, 0xC7,
- 0x8F, 0x37, 0xDB, 0x92, 0x28, 0xDF, 0x3C, 0xBB, 0x1A, 0xAD, 0x82, 0xFA,
- 0x67, 0x10, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0F, 0x06,
- 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E,
- 0x65, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13,
- 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49,
- 0x6E, 0x63, 0x2E, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0B,
- 0x13, 0x2A, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43,
- 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x53, 0x6F,
- 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69,
- 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17, 0x0D,
- 0x39, 0x36, 0x30, 0x34, 0x30, 0x39, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
- 0x5A, 0x17, 0x0D, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33, 0x35,
- 0x39, 0x35, 0x39, 0x5A, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03,
- 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E, 0x65,
- 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x0E,
- 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E,
- 0x63, 0x2E, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13,
- 0x2A, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43, 0x6F,
- 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x53, 0x6F, 0x66,
- 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x73,
- 0x68, 0x65, 0x72, 0x73, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9F, 0x30, 0x0D,
- 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05,
- 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00,
- 0xC3, 0xD3, 0x69, 0x65, 0x52, 0x01, 0x94, 0x54, 0xAB, 0x28, 0xC6, 0x62,
- 0x18, 0xB3, 0x54, 0x55, 0xC5, 0x44, 0x87, 0x45, 0x4A, 0x3B, 0xC2, 0x7E,
- 0xD8, 0xD3, 0xD7, 0xC8, 0x80, 0x86, 0x8D, 0xD8, 0x0C, 0xF1, 0x16, 0x9C,
- 0xCC, 0x6B, 0xA9, 0x29, 0xB2, 0x8F, 0x76, 0x73, 0x92, 0xC8, 0xC5, 0x62,
- 0xA6, 0x3C, 0xED, 0x1E, 0x05, 0x75, 0xF0, 0x13, 0x00, 0x6C, 0x14, 0x4D,
- 0xD4, 0x98, 0x90, 0x07, 0xBE, 0x69, 0x73, 0x81, 0xB8, 0x62, 0x4E, 0x31,
- 0x1E, 0xD1, 0xFC, 0xC9, 0x0C, 0xEB, 0x7D, 0x90, 0xBF, 0xAE, 0xB4, 0x47,
- 0x51, 0xEC, 0x6F, 0xCE, 0x64, 0x35, 0x02, 0xD6, 0x7D, 0x67, 0x05, 0x77,
- 0xE2, 0x8F, 0xD9, 0x51, 0xD7, 0xFB, 0x97, 0x19, 0xBC, 0x3E, 0xD7, 0x77,
- 0x81, 0xC6, 0x43, 0xDD, 0xF2, 0xDD, 0xDF, 0xCA, 0xA3, 0x83, 0x8B, 0xCB,
- 0x41, 0xC1, 0x3D, 0x22, 0x48, 0x48, 0xA6, 0x19, 0x02, 0x03, 0x01, 0x00,
- 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
- 0x01, 0x02, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xB5, 0xBC, 0xB0, 0x75,
- 0x6A, 0x89, 0xA2, 0x86, 0xBD, 0x64, 0x78, 0xC3, 0xA7, 0x32, 0x75, 0x72,
- 0x11, 0xAA, 0x26, 0x02, 0x17, 0x60, 0x30, 0x4C, 0xE3, 0x48, 0x34, 0x19,
- 0xB9, 0x52, 0x4A, 0x51, 0x18, 0x80, 0xFE, 0x53, 0x2D, 0x7B, 0xD5, 0x31,
- 0x8C, 0xC5, 0x65, 0x99, 0x41, 0x41, 0x2F, 0xF2, 0xAE, 0x63, 0x7A, 0xE8,
- 0x73, 0x99, 0x15, 0x90, 0x1A, 0x1F, 0x7A, 0x8B, 0x41, 0xD0, 0x8E, 0x3A,
- 0xD0, 0xCD, 0x38, 0x34, 0x44, 0xD0, 0x75, 0xF8, 0xEA, 0x71, 0xC4, 0x81,
- 0x19, 0x38, 0x17, 0x35, 0x4A, 0xAE, 0xC5, 0x3E, 0x32, 0xE6, 0x21, 0xB8,
- 0x05, 0xC0, 0x93, 0xE1, 0xC7, 0x38, 0x5C, 0xD8, 0xF7, 0x93, 0x38, 0x64,
- 0x90, 0xED, 0x54, 0xCE, 0xCA, 0xD3, 0xD3, 0xD0, 0x5F, 0xEF, 0x04, 0x9B,
- 0xDE, 0x02, 0x82, 0xDD, 0x88, 0x29, 0xB1, 0xC3, 0x4F, 0xA5, 0xCD, 0x71,
- 0x64, 0x31, 0x3C, 0x3C };
-
- static byte[] verisign_ts_root = {
- 0x30, 0x82, 0x02, 0xBC, 0x30, 0x82, 0x02, 0x25, 0x02, 0x10, 0x4A, 0x19,
- 0xD2, 0x38, 0x8C, 0x82, 0x59, 0x1C, 0xA5, 0x5D, 0x73, 0x5F, 0x15, 0x5D,
- 0xDC, 0xA3, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x81, 0x9E, 0x31, 0x1F, 0x30, 0x1D,
- 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69, 0x53,
- 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E, 0x65,
- 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55,
- 0x04, 0x0B, 0x13, 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E,
- 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2C, 0x30, 0x2A, 0x06, 0x03,
- 0x55, 0x04, 0x0B, 0x13, 0x23, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
- 0x6E, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D, 0x70,
- 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x20,
- 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55, 0x04,
- 0x0B, 0x13, 0x2B, 0x4E, 0x4F, 0x20, 0x4C, 0x49, 0x41, 0x42, 0x49, 0x4C,
- 0x49, 0x54, 0x59, 0x20, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45, 0x44,
- 0x2C, 0x20, 0x28, 0x63, 0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72, 0x69,
- 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x30, 0x1E,
- 0x17, 0x0D, 0x39, 0x37, 0x30, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30,
- 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32,
- 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81, 0x9E, 0x31, 0x1F, 0x30,
- 0x1D, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x16, 0x56, 0x65, 0x72, 0x69,
- 0x53, 0x69, 0x67, 0x6E, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x20, 0x4E,
- 0x65, 0x74, 0x77, 0x6F, 0x72, 0x6B, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03,
- 0x55, 0x04, 0x0B, 0x13, 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67,
- 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x2C, 0x30, 0x2A, 0x06,
- 0x03, 0x55, 0x04, 0x0B, 0x13, 0x23, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69,
- 0x67, 0x6E, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x53, 0x74, 0x61, 0x6D,
- 0x70, 0x69, 0x6E, 0x67, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
- 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x34, 0x30, 0x32, 0x06, 0x03, 0x55,
- 0x04, 0x0B, 0x13, 0x2B, 0x4E, 0x4F, 0x20, 0x4C, 0x49, 0x41, 0x42, 0x49,
- 0x4C, 0x49, 0x54, 0x59, 0x20, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x45,
- 0x44, 0x2C, 0x20, 0x28, 0x63, 0x29, 0x39, 0x37, 0x20, 0x56, 0x65, 0x72,
- 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49, 0x6E, 0x63, 0x2E, 0x30,
- 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89,
- 0x02, 0x81, 0x81, 0x00, 0xD3, 0x2E, 0x20, 0xF0, 0x68, 0x7C, 0x2C, 0x2D,
- 0x2E, 0x81, 0x1C, 0xB1, 0x06, 0xB2, 0xA7, 0x0B, 0xB7, 0x11, 0x0D, 0x57,
- 0xDA, 0x53, 0xD8, 0x75, 0xE3, 0xC9, 0x33, 0x2A, 0xB2, 0xD4, 0xF6, 0x09,
- 0x5B, 0x34, 0xF3, 0xE9, 0x90, 0xFE, 0x09, 0x0C, 0xD0, 0xDB, 0x1B, 0x5A,
- 0xB9, 0xCD, 0xE7, 0xF6, 0x88, 0xB1, 0x9D, 0xC0, 0x87, 0x25, 0xEB, 0x7D,
- 0x58, 0x10, 0x73, 0x6A, 0x78, 0xCB, 0x71, 0x15, 0xFD, 0xC6, 0x58, 0xF6,
- 0x29, 0xAB, 0x58, 0x5E, 0x96, 0x04, 0xFD, 0x2D, 0x62, 0x11, 0x58, 0x81,
- 0x1C, 0xCA, 0x71, 0x94, 0xD5, 0x22, 0x58, 0x2F, 0xD5, 0xCC, 0x14, 0x05,
- 0x84, 0x36, 0xBA, 0x94, 0xAA, 0xB4, 0x4D, 0x4A, 0xE9, 0xEE, 0x3B, 0x22,
- 0xAD, 0x56, 0x99, 0x7E, 0x21, 0x9C, 0x6C, 0x86, 0xC0, 0x4A, 0x47, 0x97,
- 0x6A, 0xB4, 0xA6, 0x36, 0xD5, 0xFC, 0x09, 0x2D, 0xD3, 0xB4, 0x39, 0x9B,
- 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48,
- 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00,
- 0x61, 0x55, 0x0E, 0x3E, 0x7B, 0xC7, 0x92, 0x12, 0x7E, 0x11, 0x10, 0x8E,
- 0x22, 0xCC, 0xD4, 0xB3, 0x13, 0x2B, 0x5B, 0xE8, 0x44, 0xE4, 0x0B, 0x78,
- 0x9E, 0xA4, 0x7E, 0xF3, 0xA7, 0x07, 0x72, 0x1E, 0xE2, 0x59, 0xEF, 0xCC,
- 0x84, 0xE3, 0x89, 0x94, 0x4C, 0xDB, 0x4E, 0x61, 0xEF, 0xB3, 0xA4, 0xFB,
- 0x46, 0x3D, 0x50, 0x34, 0x0B, 0x9F, 0x70, 0x56, 0xF6, 0x8E, 0x2A, 0x7F,
- 0x17, 0xCE, 0xE5, 0x63, 0xBF, 0x79, 0x69, 0x07, 0x73, 0x2E, 0xB0, 0x95,
- 0x28, 0x8A, 0xF5, 0xED, 0xAA, 0xA9, 0xD2, 0x5D, 0xCD, 0x0A, 0xCA, 0x10,
- 0x09, 0x8F, 0xCE, 0xB3, 0xAF, 0x28, 0x96, 0xC4, 0x79, 0x29, 0x84, 0x92,
- 0xDC, 0xFF, 0xBA, 0x67, 0x42, 0x48, 0xA6, 0x90, 0x10, 0xE4, 0xBF, 0x61,
- 0xF8, 0x9C, 0x53, 0xE5, 0x93, 0xD1, 0x73, 0x3F, 0xF8, 0xFD, 0x9D, 0x4F,
- 0x84, 0xAC, 0x55, 0xD1, 0xFD, 0x11, 0x63, 0x63 };
-
- // old verisign code signing certificate (96-99) using MD2
- // still valid because of the timestamps
- static byte[] oldverisign = {
- 0x30, 0x82, 0x02, 0x35, 0x30, 0x82, 0x01, 0x9E, 0x02, 0x05, 0x02, 0xB4,
- 0x00, 0x00, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0F,
- 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6E, 0x74, 0x65, 0x72,
- 0x6E, 0x65, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A,
- 0x13, 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20,
- 0x49, 0x6E, 0x63, 0x2E, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04,
- 0x0B, 0x13, 0x2A, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20,
- 0x43, 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x53,
- 0x6F, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C,
- 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43, 0x41, 0x30, 0x1E, 0x17,
- 0x0D, 0x39, 0x36, 0x30, 0x34, 0x30, 0x39, 0x30, 0x39, 0x33, 0x35, 0x35,
- 0x39, 0x5A, 0x17, 0x0D, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x30, 0x39,
- 0x33, 0x35, 0x35, 0x38, 0x5A, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0F, 0x06,
- 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6E,
- 0x65, 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13,
- 0x0E, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x2C, 0x20, 0x49,
- 0x6E, 0x63, 0x2E, 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0B,
- 0x13, 0x2A, 0x56, 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6E, 0x20, 0x43,
- 0x6F, 0x6D, 0x6D, 0x65, 0x72, 0x63, 0x69, 0x61, 0x6C, 0x20, 0x53, 0x6F,
- 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69,
- 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43, 0x41, 0x30, 0x81, 0x9F, 0x30,
- 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01,
- 0x05, 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81,
- 0x00, 0xC3, 0xD3, 0x69, 0x65, 0x52, 0x01, 0x94, 0x54, 0xAB, 0x28, 0xC6,
- 0x62, 0x18, 0xB3, 0x54, 0x55, 0xC5, 0x44, 0x87, 0x45, 0x4A, 0x3B, 0xC2,
- 0x7E, 0xD8, 0xD3, 0xD7, 0xC8, 0x80, 0x86, 0x8D, 0xD8, 0x0C, 0xF1, 0x16,
- 0x9C, 0xCC, 0x6B, 0xA9, 0x29, 0xB2, 0x8F, 0x76, 0x73, 0x92, 0xC8, 0xC5,
- 0x62, 0xA6, 0x3C, 0xED, 0x1E, 0x05, 0x75, 0xF0, 0x13, 0x00, 0x6C, 0x14,
- 0x4D, 0xD4, 0x98, 0x90, 0x07, 0xBE, 0x69, 0x73, 0x81, 0xB8, 0x62, 0x4E,
- 0x31, 0x1E, 0xD1, 0xFC, 0xC9, 0x0C, 0xEB, 0x7D, 0x90, 0xBF, 0xAE, 0xB4,
- 0x47, 0x51, 0xEC, 0x6F, 0xCE, 0x64, 0x35, 0x02, 0xD6, 0x7D, 0x67, 0x05,
- 0x77, 0xE2, 0x8F, 0xD9, 0x51, 0xD7, 0xFB, 0x97, 0x19, 0xBC, 0x3E, 0xD7,
- 0x77, 0x81, 0xC6, 0x43, 0xDD, 0xF2, 0xDD, 0xDF, 0xCA, 0xA3, 0x83, 0x8B,
- 0xCB, 0x41, 0xC1, 0x3D, 0x22, 0x48, 0x48, 0xA6, 0x19, 0x02, 0x03, 0x01,
- 0x00, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D,
- 0x01, 0x01, 0x02, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0x31, 0xBB, 0x30,
- 0xC5, 0x6F, 0xA7, 0xBE, 0x23, 0x26, 0x6D, 0xA5, 0x99, 0x76, 0x68, 0xC5,
- 0x2A, 0x03, 0x28, 0x4B, 0xF3, 0x89, 0xB0, 0x99, 0x03, 0x32, 0x5B, 0x94,
- 0xA1, 0x7B, 0xC1, 0xC8, 0x19, 0xD7, 0xF4, 0x95, 0x6C, 0xAC, 0x73, 0x24,
- 0x0A, 0xCB, 0x44, 0x05, 0x7D, 0x78, 0xEE, 0xFA, 0xF6, 0xA7, 0x9F, 0x87,
- 0xA4, 0x7F, 0xE8, 0xF3, 0x4B, 0x4F, 0x32, 0x30, 0x30, 0x15, 0x08, 0x17,
- 0x01, 0xB2, 0x80, 0xFC, 0xA1, 0xD9, 0x24, 0x87, 0xA5, 0x00, 0x5F, 0xCD,
- 0xDD, 0x29, 0xC8, 0xA1, 0xA5, 0xCA, 0x58, 0x75, 0x39, 0x60, 0x45, 0x1F,
- 0xDE, 0x8D, 0xD6, 0x57, 0x08, 0xD3, 0xC0, 0x1B, 0x81, 0xC2, 0xD9, 0xE2,
- 0x00, 0x8C, 0xEC, 0x0A, 0x91, 0x02, 0xC6, 0x9D, 0x36, 0x74, 0x9A, 0x83,
- 0x6B, 0xEF, 0x7C, 0x8C, 0xD2, 0xA5, 0x2A, 0x6A, 0xC9, 0x7E, 0xDB, 0xA9,
- 0xBD, 0x2B, 0x22, 0xFF, 0x1C };
-
- static byte[] thawte = {
- 0x30, 0x82, 0x03, 0x13, 0x30, 0x82, 0x02, 0x7C, 0xA0, 0x03, 0x02, 0x01,
- 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86,
- 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x30, 0x81, 0xC4, 0x31, 0x0B,
- 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x5A, 0x41, 0x31,
- 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0C, 0x57, 0x65,
- 0x73, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x43, 0x61, 0x70, 0x65, 0x31, 0x12,
- 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09, 0x43, 0x61, 0x70,
- 0x65, 0x20, 0x54, 0x6F, 0x77, 0x6E, 0x31, 0x1D, 0x30, 0x1B, 0x06, 0x03,
- 0x55, 0x04, 0x0A, 0x13, 0x14, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65, 0x20,
- 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x20, 0x63,
- 0x63, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1F,
- 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F,
- 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x20, 0x44,
- 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x19, 0x30, 0x17, 0x06,
- 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x54, 0x68, 0x61, 0x77, 0x74, 0x65,
- 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43, 0x41, 0x31, 0x26,
- 0x30, 0x24, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09,
- 0x01, 0x16, 0x17, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2D, 0x63, 0x65,
- 0x72, 0x74, 0x73, 0x40, 0x74, 0x68, 0x61, 0x77, 0x74, 0x65, 0x2E, 0x63,
- 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x39, 0x36, 0x30, 0x38, 0x30, 0x31,
- 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, 0x31,
- 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5A, 0x30, 0x81,
- 0xC4, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02,
- 0x5A, 0x41, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13,
- 0x0C, 0x57, 0x65, 0x73, 0x74, 0x65, 0x72, 0x6E, 0x20, 0x43, 0x61, 0x70,
- 0x65, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x09,
- 0x43, 0x61, 0x70, 0x65, 0x20, 0x54, 0x6F, 0x77, 0x6E, 0x31, 0x1D, 0x30,
- 0x1B, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x14, 0x54, 0x68, 0x61, 0x77,
- 0x74, 0x65, 0x20, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E,
- 0x67, 0x20, 0x63, 0x63, 0x31, 0x28, 0x30, 0x26, 0x06, 0x03, 0x55, 0x04,
- 0x0B, 0x13, 0x1F, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61,
- 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
- 0x73, 0x20, 0x44, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x31, 0x19,
- 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x10, 0x54, 0x68, 0x61,
- 0x77, 0x74, 0x65, 0x20, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x43,
- 0x41, 0x31, 0x26, 0x30, 0x24, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x01, 0x16, 0x17, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
- 0x2D, 0x63, 0x65, 0x72, 0x74, 0x73, 0x40, 0x74, 0x68, 0x61, 0x77, 0x74,
- 0x65, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03,
- 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xD3, 0xA4,
- 0x50, 0x6E, 0xC8, 0xFF, 0x56, 0x6B, 0xE6, 0xCF, 0x5D, 0xB6, 0xEA, 0x0C,
- 0x68, 0x75, 0x47, 0xA2, 0xAA, 0xC2, 0xDA, 0x84, 0x25, 0xFC, 0xA8, 0xF4,
- 0x47, 0x51, 0xDA, 0x85, 0xB5, 0x20, 0x74, 0x94, 0x86, 0x1E, 0x0F, 0x75,
- 0xC9, 0xE9, 0x08, 0x61, 0xF5, 0x06, 0x6D, 0x30, 0x6E, 0x15, 0x19, 0x02,
- 0xE9, 0x52, 0xC0, 0x62, 0xDB, 0x4D, 0x99, 0x9E, 0xE2, 0x6A, 0x0C, 0x44,
- 0x38, 0xCD, 0xFE, 0xBE, 0xE3, 0x64, 0x09, 0x70, 0xC5, 0xFE, 0xB1, 0x6B,
- 0x29, 0xB6, 0x2F, 0x49, 0xC8, 0x3B, 0xD4, 0x27, 0x04, 0x25, 0x10, 0x97,
- 0x2F, 0xE7, 0x90, 0x6D, 0xC0, 0x28, 0x42, 0x99, 0xD7, 0x4C, 0x43, 0xDE,
- 0xC3, 0xF5, 0x21, 0x6D, 0x54, 0x9F, 0x5D, 0xC3, 0x58, 0xE1, 0xC0, 0xE4,
- 0xD9, 0x5B, 0xB0, 0xB8, 0xDC, 0xB4, 0x7B, 0xDF, 0x36, 0x3A, 0xC2, 0xB5,
- 0x66, 0x22, 0x12, 0xD6, 0x87, 0x0D, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3,
- 0x13, 0x30, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01,
- 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09,
- 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x04, 0x05, 0x00, 0x03,
- 0x81, 0x81, 0x00, 0x07, 0xFA, 0x4C, 0x69, 0x5C, 0xFB, 0x95, 0xCC, 0x46,
- 0xEE, 0x85, 0x83, 0x4D, 0x21, 0x30, 0x8E, 0xCA, 0xD9, 0xA8, 0x6F, 0x49,
- 0x1A, 0xE6, 0xDA, 0x51, 0xE3, 0x60, 0x70, 0x6C, 0x84, 0x61, 0x11, 0xA1,
- 0x1A, 0xC8, 0x48, 0x3E, 0x59, 0x43, 0x7D, 0x4F, 0x95, 0x3D, 0xA1, 0x8B,
- 0xB7, 0x0B, 0x62, 0x98, 0x7A, 0x75, 0x8A, 0xDD, 0x88, 0x4E, 0x4E, 0x9E,
- 0x40, 0xDB, 0xA8, 0xCC, 0x32, 0x74, 0xB9, 0x6F, 0x0D, 0xC6, 0xE3, 0xB3,
- 0x44, 0x0B, 0xD9, 0x8A, 0x6F, 0x9A, 0x29, 0x9B, 0x99, 0x18, 0x28, 0x3B,
- 0xD1, 0xE3, 0x40, 0x28, 0x9A, 0x5A, 0x3C, 0xD5, 0xB5, 0xE7, 0x20, 0x1B,
- 0x8B, 0xCA, 0xA4, 0xAB, 0x8D, 0xE9, 0x51, 0xD9, 0xE2, 0x4C, 0x2C, 0x59,
- 0xA9, 0xDA, 0xB9, 0xB2, 0x75, 0x1B, 0xF6, 0x42, 0xF2, 0xEF, 0xC7, 0xF2,
- 0x18, 0xF9, 0x89, 0xBC, 0xA3, 0xFF, 0x8A, 0x23, 0x2E, 0x70, 0x47 };
-
- static internal X509CertificateCollection coll;
-
- static TrustAnchors ()
- {
- coll = new X509CertificateCollection ();
- coll.Add (new X509Certificate (msroot));
- coll.Add (new X509Certificate (verisign));
- coll.Add (new X509Certificate (verisign_ts_root));
- coll.Add (new X509Certificate (thawte));
- }
-
- public X509CertificateCollection Anchors {
- get { return coll; }
- }
- }
-}
+++ /dev/null
-//
-// X501Name.cs: X.501 Distinguished Names stuff
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2006 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.Globalization;
-using System.Text;
-
-using Mono.Security;
-using Mono.Security.Cryptography;
-
-namespace Mono.Security.X509 {
-
- // References:
- // 1. Information technology - Open Systems Interconnection - The Directory: Models
- // http://www.itu.int/rec/recommendation.asp?type=items&lang=e&parent=T-REC-X.501-200102-I
- // 2. RFC2253: Lightweight Directory Access Protocol (v3): UTF-8 String Representation of Distinguished Names
- // http://www.ietf.org/rfc/rfc2253.txt
-
- /*
- * Name ::= CHOICE { RDNSequence }
- *
- * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
- *
- * RelativeDistinguishedName ::= SET OF AttributeTypeAndValue
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class X501 {
-
- static byte[] countryName = { 0x55, 0x04, 0x06 };
- static byte[] organizationName = { 0x55, 0x04, 0x0A };
- static byte[] organizationalUnitName = { 0x55, 0x04, 0x0B };
- static byte[] commonName = { 0x55, 0x04, 0x03 };
- static byte[] localityName = { 0x55, 0x04, 0x07 };
- static byte[] stateOrProvinceName = { 0x55, 0x04, 0x08 };
- static byte[] streetAddress = { 0x55, 0x04, 0x09 };
- //static byte[] serialNumber = { 0x55, 0x04, 0x05 };
- static byte[] domainComponent = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19 };
- static byte[] userid = { 0x09, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x01 };
- static byte[] email = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01 };
- static byte[] dnQualifier = { 0x55, 0x04, 0x2E };
- static byte[] title = { 0x55, 0x04, 0x0C };
- static byte[] surname = { 0x55, 0x04, 0x04 };
- static byte[] givenName = { 0x55, 0x04, 0x2A };
- static byte[] initial = { 0x55, 0x04, 0x2B };
-
- private X501 ()
- {
- }
-
- static public string ToString (ASN1 seq)
- {
- StringBuilder sb = new StringBuilder ();
- for (int i = 0; i < seq.Count; i++) {
- ASN1 entry = seq [i];
- AppendEntry (sb, entry, true);
-
- // separator (not on last iteration)
- if (i < seq.Count - 1)
- sb.Append (", ");
- }
- return sb.ToString ();
- }
-
- static public string ToString (ASN1 seq, bool reversed, string separator, bool quotes)
- {
- StringBuilder sb = new StringBuilder ();
-
- if (reversed) {
- for (int i = seq.Count - 1; i >= 0; i--) {
- ASN1 entry = seq [i];
- AppendEntry (sb, entry, quotes);
-
- // separator (not on last iteration)
- if (i > 0)
- sb.Append (separator);
- }
- } else {
- for (int i = 0; i < seq.Count; i++) {
- ASN1 entry = seq [i];
- AppendEntry (sb, entry, quotes);
-
- // separator (not on last iteration)
- if (i < seq.Count - 1)
- sb.Append (separator);
- }
- }
- return sb.ToString ();
- }
-
- static private void AppendEntry (StringBuilder sb, ASN1 entry, bool quotes)
- {
- // multiple entries are valid
- for (int k = 0; k < entry.Count; k++) {
- ASN1 pair = entry [k];
- ASN1 s = pair [1];
- if (s == null)
- continue;
-
- ASN1 poid = pair [0];
- if (poid == null)
- continue;
-
- if (poid.CompareValue (countryName))
- sb.Append ("C=");
- else if (poid.CompareValue (organizationName))
- sb.Append ("O=");
- else if (poid.CompareValue (organizationalUnitName))
- sb.Append ("OU=");
- else if (poid.CompareValue (commonName))
- sb.Append ("CN=");
- else if (poid.CompareValue (localityName))
- sb.Append ("L=");
- else if (poid.CompareValue (stateOrProvinceName))
- sb.Append ("S="); // NOTE: RFC2253 uses ST=
- else if (poid.CompareValue (streetAddress))
- sb.Append ("STREET=");
- else if (poid.CompareValue (domainComponent))
- sb.Append ("DC=");
- else if (poid.CompareValue (userid))
- sb.Append ("UID=");
- else if (poid.CompareValue (email))
- sb.Append ("E="); // NOTE: Not part of RFC2253
- else if (poid.CompareValue (dnQualifier))
- sb.Append ("dnQualifier=");
- else if (poid.CompareValue (title))
- sb.Append ("T=");
- else if (poid.CompareValue (surname))
- sb.Append ("SN=");
- else if (poid.CompareValue (givenName))
- sb.Append ("G=");
- else if (poid.CompareValue (initial))
- sb.Append ("I=");
- else {
- // unknown OID
- sb.Append ("OID."); // NOTE: Not present as RFC2253
- sb.Append (ASN1Convert.ToOid (poid));
- sb.Append ("=");
- }
-
- string sValue = null;
- // 16bits or 8bits string ? TODO not complete (+special chars!)
- if (s.Tag == 0x1E) {
- // BMPSTRING
- StringBuilder sb2 = new StringBuilder ();
- for (int j = 1; j < s.Value.Length; j += 2)
- sb2.Append ((char)s.Value[j]);
- sValue = sb2.ToString ();
- } else {
- if (s.Tag == 0x14)
- sValue = Encoding.UTF7.GetString (s.Value);
- else
- sValue = Encoding.UTF8.GetString (s.Value);
- // in some cases we must quote (") the value
- // Note: this doesn't seems to conform to RFC2253
- char[] specials = { ',', '+', '"', '\\', '<', '>', ';' };
- if (quotes) {
- if ((sValue.IndexOfAny (specials, 0, sValue.Length) > 0) ||
- sValue.StartsWith (" ") || (sValue.EndsWith (" ")))
- sValue = "\"" + sValue + "\"";
- }
- }
-
- sb.Append (sValue);
-
- // separator (not on last iteration)
- if (k < entry.Count - 1)
- sb.Append (", ");
- }
- }
-
- static private X520.AttributeTypeAndValue GetAttributeFromOid (string attributeType)
- {
- string s = attributeType.ToUpper (CultureInfo.InvariantCulture).Trim ();
- switch (s) {
- case "C":
- return new X520.CountryName ();
- case "O":
- return new X520.OrganizationName ();
- case "OU":
- return new X520.OrganizationalUnitName ();
- case "CN":
- return new X520.CommonName ();
- case "L":
- return new X520.LocalityName ();
- case "S": // Microsoft
- case "ST": // RFC2253
- return new X520.StateOrProvinceName ();
- case "E": // NOTE: Not part of RFC2253
- return new X520.EmailAddress ();
- case "DC": // RFC2247
- return new X520.DomainComponent ();
- case "UID": // RFC1274
- return new X520.UserId ();
- case "DNQUALIFIER":
- return new X520.DnQualifier ();
- case "T":
- return new X520.Title ();
- case "SN":
- return new X520.Surname ();
- case "G":
- return new X520.GivenName ();
- case "I":
- return new X520.Initial ();
- default:
- if (s.StartsWith ("OID.")) {
- // MUST support it but it OID may be without it
- return new X520.Oid (s.Substring (4));
- } else {
- if (IsOid (s))
- return new X520.Oid (s);
- else
- return null;
- }
- }
- }
-
- static private bool IsOid (string oid)
- {
- try {
- ASN1 asn = ASN1Convert.FromOid (oid);
- return (asn.Tag == 0x06);
- }
- catch {
- return false;
- }
- }
-
- // no quote processing
- static private X520.AttributeTypeAndValue ReadAttribute (string value, ref int pos)
- {
- while ((value[pos] == ' ') && (pos < value.Length))
- pos++;
-
- // get '=' position in substring
- int equal = value.IndexOf ('=', pos);
- if (equal == -1) {
- string msg = Locale.GetText ("No attribute found.");
- throw new FormatException (msg);
- }
-
- string s = value.Substring (pos, equal - pos);
- X520.AttributeTypeAndValue atv = GetAttributeFromOid (s);
- if (atv == null) {
- string msg = Locale.GetText ("Unknown attribute '{0}'.");
- throw new FormatException (String.Format (msg, s));
- }
- pos = equal + 1; // skip the '='
- return atv;
- }
-
- static private bool IsHex (char c)
- {
- if (Char.IsDigit (c))
- return true;
- char up = Char.ToUpper (c, CultureInfo.InvariantCulture);
- return ((up >= 'A') && (up <= 'F'));
- }
-
- static string ReadHex (string value, ref int pos)
- {
- StringBuilder sb = new StringBuilder ();
- // it is (at least an) 8 bits char
- sb.Append (value[pos++]);
- sb.Append (value[pos]);
- // look ahead for a 16 bits char
- if ((pos < value.Length - 4) && (value[pos+1] == '\\') && IsHex (value[pos+2])) {
- pos += 2; // pass last char and skip \
- sb.Append (value[pos++]);
- sb.Append (value[pos]);
- }
- byte[] data = CryptoConvert.FromHex (sb.ToString ());
- return Encoding.UTF8.GetString (data);
- }
-
- static private int ReadEscaped (StringBuilder sb, string value, int pos)
- {
- switch (value[pos]) {
- case '\\':
- case '"':
- case '=':
- case ';':
- case '<':
- case '>':
- case '+':
- case '#':
- case ',':
- sb.Append (value[pos]);
- return pos;
- default:
- if (pos >= value.Length - 2) {
- string msg = Locale.GetText ("Malformed escaped value '{0}'.");
- throw new FormatException (string.Format (msg, value.Substring (pos)));
- }
- // it's either a 8 bits or 16 bits char
- sb.Append (ReadHex (value, ref pos));
- return pos;
- }
- }
-
- static private int ReadQuoted (StringBuilder sb, string value, int pos)
- {
- int original = pos;
- while (pos <= value.Length) {
- switch (value[pos]) {
- case '"':
- return pos;
- case '\\':
- return ReadEscaped (sb, value, pos);
- default:
- sb.Append (value[pos]);
- pos++;
- break;
- }
- }
- string msg = Locale.GetText ("Malformed quoted value '{0}'.");
- throw new FormatException (string.Format (msg, value.Substring (original)));
- }
-
- static private string ReadValue (string value, ref int pos)
- {
- int original = pos;
- StringBuilder sb = new StringBuilder ();
- while (pos < value.Length) {
- switch (value [pos]) {
- case '\\':
- pos = ReadEscaped (sb, value, ++pos);
- break;
- case '"':
- pos = ReadQuoted (sb, value, ++pos);
- break;
- case '=':
- case ';':
- case '<':
- case '>':
- string msg = Locale.GetText ("Malformed value '{0}' contains '{1}' outside quotes.");
- throw new FormatException (string.Format (msg, value.Substring (original), value[pos]));
- case '+':
- case '#':
- throw new NotImplementedException ();
- case ',':
- pos++;
- return sb.ToString ();
- default:
- sb.Append (value[pos]);
- break;
- }
- pos++;
- }
- return sb.ToString ();
- }
-
- static public ASN1 FromString (string rdn)
- {
- if (rdn == null)
- throw new ArgumentNullException ("rdn");
-
- int pos = 0;
- ASN1 asn1 = new ASN1 (0x30);
- while (pos < rdn.Length) {
- X520.AttributeTypeAndValue atv = ReadAttribute (rdn, ref pos);
- atv.Value = ReadValue (rdn, ref pos);
-
- ASN1 sequence = new ASN1 (0x31);
- sequence.Add (atv.GetASN1 ());
- asn1.Add (sequence);
- }
- return asn1;
- }
- }
-}
+++ /dev/null
-//
-// X509CRL.cs: Handles X.509 certificates revocation lists.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// Copyright (C) 2004,2006 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.Collections;
-using System.Globalization;
-using System.IO;
-using System.Security.Cryptography;
-
-using Mono.Security.X509.Extensions;
-
-namespace Mono.Security.X509 {
- /*
- * CertificateList ::= SEQUENCE {
- * tbsCertList TBSCertList,
- * signatureAlgorithm AlgorithmIdentifier,
- * signature BIT STRING
- * }
- *
- * TBSCertList ::= SEQUENCE {
- * version Version OPTIONAL,
- * -- if present, MUST be v2
- * signature AlgorithmIdentifier,
- * issuer Name,
- * thisUpdate Time,
- * nextUpdate Time OPTIONAL,
- * revokedCertificates SEQUENCE OF SEQUENCE {
- * userCertificate CertificateSerialNumber,
- * revocationDate Time,
- * crlEntryExtensions Extensions OPTIONAL
- * -- if present, MUST be v2
- * } OPTIONAL,
- * crlExtensions [0] Extensions OPTIONAL }
- * -- if present, MUST be v2
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509Crl {
-
- public class X509CrlEntry {
-
- private byte[] sn;
- private DateTime revocationDate;
- private X509ExtensionCollection extensions;
-
- internal X509CrlEntry (byte[] serialNumber, DateTime revocationDate, X509ExtensionCollection extensions)
- {
- sn = serialNumber;
- this.revocationDate = revocationDate;
- if (extensions == null)
- this.extensions = new X509ExtensionCollection ();
- else
- this.extensions = extensions;
- }
-
- internal X509CrlEntry (ASN1 entry)
- {
- sn = entry [0].Value;
- Array.Reverse (sn);
- revocationDate = ASN1Convert.ToDateTime (entry [1]);
- extensions = new X509ExtensionCollection (entry [2]);
- }
-
- public byte[] SerialNumber {
- get { return (byte[]) sn.Clone (); }
- }
-
- public DateTime RevocationDate {
- get { return revocationDate; }
- }
-
- public X509ExtensionCollection Extensions {
- get { return extensions; }
- }
-
- public byte[] GetBytes ()
- {
- ASN1 sequence = new ASN1 (0x30);
- sequence.Add (new ASN1 (0x02, sn));
- sequence.Add (ASN1Convert.FromDateTime (revocationDate));
- if (extensions.Count > 0)
- sequence.Add (new ASN1 (extensions.GetBytes ()));
- return sequence.GetBytes ();
- }
- }
-
- private string issuer;
- private byte version;
- private DateTime thisUpdate;
- private DateTime nextUpdate;
- private ArrayList entries;
- private string signatureOID;
- private byte[] signature;
- private X509ExtensionCollection extensions;
- private byte[] encoded;
- private byte[] hash_value;
-
- public X509Crl (byte[] crl)
- {
- if (crl == null)
- throw new ArgumentNullException ("crl");
- encoded = (byte[]) crl.Clone ();
- Parse (encoded);
- }
-
- private void Parse (byte[] crl)
- {
- string e = "Input data cannot be coded as a valid CRL.";
- try {
- // CertificateList ::= SEQUENCE {
- ASN1 encodedCRL = new ASN1 (encoded);
- if ((encodedCRL.Tag != 0x30) || (encodedCRL.Count != 3))
- throw new CryptographicException (e);
-
- // CertificateList / TBSCertList,
- ASN1 toBeSigned = encodedCRL [0];
- if ((toBeSigned.Tag != 0x30) || (toBeSigned.Count < 3))
- throw new CryptographicException (e);
-
- int n = 0;
- // CertificateList / TBSCertList / Version OPTIONAL, -- if present, MUST be v2
- if (toBeSigned [n].Tag == 0x02) {
- version = (byte) (toBeSigned [n++].Value [0] + 1);
- }
- else
- version = 1; // DEFAULT
- // CertificateList / TBSCertList / AlgorithmIdentifier,
- signatureOID = ASN1Convert.ToOid (toBeSigned [n++][0]);
- // CertificateList / TBSCertList / Name,
- issuer = X501.ToString (toBeSigned [n++]);
- // CertificateList / TBSCertList / Time,
- thisUpdate = ASN1Convert.ToDateTime (toBeSigned [n++]);
- // CertificateList / TBSCertList / Time OPTIONAL,
- ASN1 next = toBeSigned [n++];
- if ((next.Tag == 0x17) || (next.Tag == 0x18)) {
- nextUpdate = ASN1Convert.ToDateTime (next);
- next = toBeSigned [n++];
- }
- // CertificateList / TBSCertList / revokedCertificates SEQUENCE OF SEQUENCE {
- entries = new ArrayList ();
- // this is OPTIONAL so it may not be present if no entries exists
- if ((next != null) && (next.Tag == 0x30)) {
- ASN1 revokedCertificates = next;
- for (int i=0; i < revokedCertificates.Count; i++) {
- entries.Add (new X509CrlEntry (revokedCertificates [i]));
- }
- } else {
- n--;
- }
- // CertificateList / TBSCertList / crlExtensions [0] Extensions OPTIONAL }
- ASN1 extns = toBeSigned [n];
- if ((extns != null) && (extns.Tag == 0xA0) && (extns.Count == 1))
- extensions = new X509ExtensionCollection (extns [0]);
- else
- extensions = new X509ExtensionCollection (null); // result in a read only object
- // CertificateList / AlgorithmIdentifier
- string signatureAlgorithm = ASN1Convert.ToOid (encodedCRL [1][0]);
- if (signatureOID != signatureAlgorithm)
- throw new CryptographicException (e + " [Non-matching signature algorithms in CRL]");
-
- // CertificateList / BIT STRING
- byte[] bitstring = encodedCRL [2].Value;
- // first byte contains unused bits in first byte
- signature = new byte [bitstring.Length - 1];
- Buffer.BlockCopy (bitstring, 1, signature, 0, signature.Length);
- }
- catch {
- throw new CryptographicException (e);
- }
- }
-
- public ArrayList Entries {
- get { return ArrayList.ReadOnly (entries); }
- }
-
- public X509CrlEntry this [int index] {
- get { return (X509CrlEntry) entries [index]; }
- }
-
- public X509CrlEntry this [byte[] serialNumber] {
- get { return GetCrlEntry (serialNumber); }
- }
-
- public X509ExtensionCollection Extensions {
- get { return extensions; }
- }
-
- public byte[] Hash {
- get {
- if (hash_value == null) {
- ASN1 encodedCRL = new ASN1 (encoded);
- byte[] toBeSigned = encodedCRL [0].GetBytes ();
- HashAlgorithm ha = HashAlgorithm.Create (GetHashName ());
- hash_value = ha.ComputeHash (toBeSigned);
- }
- return hash_value;
- }
- }
-
- public string IssuerName {
- get { return issuer; }
- }
-
- public DateTime NextUpdate {
- get { return nextUpdate; }
- }
-
- public DateTime ThisUpdate {
- get { return thisUpdate; }
- }
-
- public string SignatureAlgorithm {
- get { return signatureOID; }
- }
-
- public byte[] Signature {
- get {
- if (signature == null)
- return null;
- return (byte[]) signature.Clone ();
- }
- }
-
- public byte[] RawData {
- get { return (byte[]) encoded.Clone (); }
- }
-
- public byte Version {
- get { return version; }
- }
-
- public bool IsCurrent {
- get { return WasCurrent (DateTime.Now); }
- }
-
- public bool WasCurrent (DateTime instant)
- {
- if (nextUpdate == DateTime.MinValue)
- return (instant >= thisUpdate);
- else
- return ((instant >= thisUpdate) && (instant <= nextUpdate));
- }
-
- public byte[] GetBytes ()
- {
- return (byte[]) encoded.Clone ();
- }
-
- private bool Compare (byte[] array1, byte[] array2)
- {
- if ((array1 == null) && (array2 == null))
- return true;
- if ((array1 == null) || (array2 == null))
- return false;
- if (array1.Length != array2.Length)
- return false;
- for (int i=0; i < array1.Length; i++) {
- if (array1 [i] != array2 [i])
- return false;
- }
- return true;
- }
-
- public X509CrlEntry GetCrlEntry (X509Certificate x509)
- {
- if (x509 == null)
- throw new ArgumentNullException ("x509");
-
- return GetCrlEntry (x509.SerialNumber);
- }
-
- public X509CrlEntry GetCrlEntry (byte[] serialNumber)
- {
- if (serialNumber == null)
- throw new ArgumentNullException ("serialNumber");
-
- for (int i=0; i < entries.Count; i++) {
- X509CrlEntry entry = (X509CrlEntry) entries [i];
- if (Compare (serialNumber, entry.SerialNumber))
- return entry;
- }
- return null;
- }
-
- public bool VerifySignature (X509Certificate x509)
- {
- if (x509 == null)
- throw new ArgumentNullException ("x509");
-
- // 1. x509 certificate must be a CA certificate (unknown for v1 or v2 certs)
- if (x509.Version >= 3) {
- // 1.1. Check for "cRLSign" bit in KeyUsage extension
- X509Extension ext = x509.Extensions ["2.5.29.15"];
- if (ext != null) {
- KeyUsageExtension keyUsage = new KeyUsageExtension (ext);
- if (!keyUsage.Support (KeyUsages.cRLSign))
- return false;
- }
- // 1.2. Check for ca = true in BasicConstraint
- ext = x509.Extensions ["2.5.29.19"];
- if (ext != null) {
- BasicConstraintsExtension basicConstraints = new BasicConstraintsExtension (ext);
- if (!basicConstraints.CertificateAuthority)
- return false;
- }
- }
- // 2. CRL issuer must match CA subject name
- if (issuer != x509.SubjectName)
- return false;
- // 3. Check the CRL signature with the CA certificate public key
- switch (signatureOID) {
- case "1.2.840.10040.4.3":
- return VerifySignature (x509.DSA);
- default:
- return VerifySignature (x509.RSA);
- }
- }
-
- private string GetHashName ()
- {
- switch (signatureOID) {
- // MD2 with RSA encryption
- case "1.2.840.113549.1.1.2":
- // maybe someone installed MD2 ?
- return "MD2";
- // MD5 with RSA encryption
- case "1.2.840.113549.1.1.4":
- return "MD5";
- // SHA-1 with DSA
- case "1.2.840.10040.4.3":
- // SHA-1 with RSA Encryption
- case "1.2.840.113549.1.1.5":
- return "SHA1";
- default:
- throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
- }
- }
-
- internal bool VerifySignature (DSA dsa)
- {
- if (signatureOID != "1.2.840.10040.4.3")
- throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
- DSASignatureDeformatter v = new DSASignatureDeformatter (dsa);
- // only SHA-1 is supported
- v.SetHashAlgorithm ("SHA1");
- ASN1 sign = new ASN1 (signature);
- if ((sign == null) || (sign.Count != 2))
- return false;
- // parts may be less than 20 bytes (i.e. first bytes were 0x00)
- byte[] part1 = sign [0].Value;
- byte[] part2 = sign [1].Value;
- byte[] sig = new byte [40];
- // parts may be less than 20 bytes (i.e. first bytes were 0x00)
- // parts may be more than 20 bytes (i.e. first byte > 0x80, negative)
- int s1 = System.Math.Max (0, part1.Length - 20);
- int e1 = System.Math.Max (0, 20 - part1.Length);
- Buffer.BlockCopy (part1, s1, sig, e1, part1.Length - s1);
- int s2 = System.Math.Max (0, part2.Length - 20);
- int e2 = System.Math.Max (20, 40 - part2.Length);
- Buffer.BlockCopy (part2, s2, sig, e2, part2.Length - s2);
- return v.VerifySignature (Hash, sig);
- }
-
- internal bool VerifySignature (RSA rsa)
- {
- RSAPKCS1SignatureDeformatter v = new RSAPKCS1SignatureDeformatter (rsa);
- v.SetHashAlgorithm (GetHashName ());
- return v.VerifySignature (Hash, signature);
- }
-
- public bool VerifySignature (AsymmetricAlgorithm aa)
- {
- if (aa == null)
- throw new ArgumentNullException ("aa");
-
- // only validate the signature (in case we don't have the CA certificate)
- if (aa is RSA)
- return VerifySignature (aa as RSA);
- else if (aa is DSA)
- return VerifySignature (aa as DSA);
- else
- throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa.ToString ());
- }
-
- static public X509Crl CreateFromFile (string filename)
- {
- byte[] crl = null;
- using (FileStream fs = File.Open (filename, FileMode.Open, FileAccess.Read, FileShare.Read)) {
- crl = new byte [fs.Length];
- fs.Read (crl, 0, crl.Length);
- fs.Close ();
- }
- return new X509Crl (crl);
- }
- }
-}
+++ /dev/null
-//
-// X509Certificates.cs: Handles X.509 certificates.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2006 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.Runtime.Serialization;
-using System.Security.Cryptography;
-using SSCX = System.Security.Cryptography.X509Certificates;
-using System.Security.Permissions;
-using System.Text;
-
-using Mono.Security.Cryptography;
-
-namespace Mono.Security.X509 {
-
- // References:
- // a. Internet X.509 Public Key Infrastructure Certificate and CRL Profile
- // http://www.ietf.org/rfc/rfc3280.txt
- // b. ITU ASN.1 standards (free download)
- // http://www.itu.int/ITU-T/studygroups/com17/languages/
-
-#if INSIDE_CORLIB
- internal class X509Certificate : ISerializable {
-#else
- public class X509Certificate : ISerializable {
-#endif
- const string encoding_error = "Input data cannot be coded as a valid certificate.";
-
- private ASN1 decoder;
-
- private byte[] m_encodedcert;
- private DateTime m_from;
- private DateTime m_until;
- private ASN1 issuer;
- private string m_issuername;
- private string m_keyalgo;
- private byte[] m_keyalgoparams;
- private ASN1 subject;
- private string m_subject;
- private byte[] m_publickey;
- private byte[] signature;
- private string m_signaturealgo;
- private byte[] m_signaturealgoparams;
- private byte[] certhash;
- private RSA _rsa;
- private DSA _dsa;
-
- // from http://www.ietf.org/rfc/rfc2459.txt
- //
- //Certificate ::= SEQUENCE {
- // tbsCertificate TBSCertificate,
- // signatureAlgorithm AlgorithmIdentifier,
- // signature BIT STRING }
- //
- //TBSCertificate ::= SEQUENCE {
- // version [0] Version DEFAULT v1,
- // serialNumber CertificateSerialNumber,
- // signature AlgorithmIdentifier,
- // issuer Name,
- // validity Validity,
- // subject Name,
- // subjectPublicKeyInfo SubjectPublicKeyInfo,
- // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
- // -- If present, version shall be v2 or v3
- // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
- // -- If present, version shall be v2 or v3
- // extensions [3] Extensions OPTIONAL
- // -- If present, version shall be v3 -- }
- private int version;
- private byte[] serialnumber;
-
- private byte[] issuerUniqueID;
- private byte[] subjectUniqueID;
- private X509ExtensionCollection extensions;
-
- // that's were the real job is!
- private void Parse (byte[] data)
- {
- try {
- decoder = new ASN1 (data);
- // Certificate
- if (decoder.Tag != 0x30)
- throw new CryptographicException (encoding_error);
- // Certificate / TBSCertificate
- if (decoder [0].Tag != 0x30)
- throw new CryptographicException (encoding_error);
-
- ASN1 tbsCertificate = decoder [0];
-
- int tbs = 0;
- // Certificate / TBSCertificate / Version
- ASN1 v = decoder [0][tbs];
- version = 1; // DEFAULT v1
- if ((v.Tag == 0xA0) && (v.Count > 0)) {
- // version (optional) is present only in v2+ certs
- version += v [0].Value [0]; // zero based
- tbs++;
- }
-
- // Certificate / TBSCertificate / CertificateSerialNumber
- ASN1 sn = decoder [0][tbs++];
- if (sn.Tag != 0x02)
- throw new CryptographicException (encoding_error);
- serialnumber = sn.Value;
- Array.Reverse (serialnumber, 0, serialnumber.Length);
-
- // Certificate / TBSCertificate / AlgorithmIdentifier
- tbs++;
- // ASN1 signatureAlgo = tbsCertificate.Element (tbs++, 0x30);
-
- issuer = tbsCertificate.Element (tbs++, 0x30);
- m_issuername = X501.ToString (issuer);
-
- ASN1 validity = tbsCertificate.Element (tbs++, 0x30);
- ASN1 notBefore = validity [0];
- m_from = ASN1Convert.ToDateTime (notBefore);
- ASN1 notAfter = validity [1];
- m_until = ASN1Convert.ToDateTime (notAfter);
-
- subject = tbsCertificate.Element (tbs++, 0x30);
- m_subject = X501.ToString (subject);
-
- ASN1 subjectPublicKeyInfo = tbsCertificate.Element (tbs++, 0x30);
-
- ASN1 algorithm = subjectPublicKeyInfo.Element (0, 0x30);
- ASN1 algo = algorithm.Element (0, 0x06);
- m_keyalgo = ASN1Convert.ToOid (algo);
- // parameters ANY DEFINED BY algorithm OPTIONAL
- // so we dont ask for a specific (Element) type and return DER
- ASN1 parameters = algorithm [1];
- m_keyalgoparams = ((algorithm.Count > 1) ? parameters.GetBytes () : null);
-
- ASN1 subjectPublicKey = subjectPublicKeyInfo.Element (1, 0x03);
- // we must drop th first byte (which is the number of unused bits
- // in the BITSTRING)
- int n = subjectPublicKey.Length - 1;
- m_publickey = new byte [n];
- Buffer.BlockCopy (subjectPublicKey.Value, 1, m_publickey, 0, n);
-
- // signature processing
- byte[] bitstring = decoder [2].Value;
- // first byte contains unused bits in first byte
- signature = new byte [bitstring.Length - 1];
- Buffer.BlockCopy (bitstring, 1, signature, 0, signature.Length);
-
- algorithm = decoder [1];
- algo = algorithm.Element (0, 0x06);
- m_signaturealgo = ASN1Convert.ToOid (algo);
- parameters = algorithm [1];
- if (parameters != null)
- m_signaturealgoparams = parameters.GetBytes ();
- else
- m_signaturealgoparams = null;
-
- // Certificate / TBSCertificate / issuerUniqueID
- ASN1 issuerUID = tbsCertificate.Element (tbs, 0x81);
- if (issuerUID != null) {
- tbs++;
- issuerUniqueID = issuerUID.Value;
- }
-
- // Certificate / TBSCertificate / subjectUniqueID
- ASN1 subjectUID = tbsCertificate.Element (tbs, 0x82);
- if (subjectUID != null) {
- tbs++;
- subjectUniqueID = subjectUID.Value;
- }
-
- // Certificate / TBSCertificate / Extensions
- ASN1 extns = tbsCertificate.Element (tbs, 0xA3);
- if ((extns != null) && (extns.Count == 1))
- extensions = new X509ExtensionCollection (extns [0]);
- else
- extensions = new X509ExtensionCollection (null);
-
- // keep a copy of the original data
- m_encodedcert = (byte[]) data.Clone ();
- }
- catch (Exception ex) {
- throw new CryptographicException (encoding_error, ex);
- }
- }
-
- // constructors
-
- public X509Certificate (byte[] data)
- {
- if (data != null) {
- // does it looks like PEM ?
- if ((data.Length > 0) && (data [0] != 0x30)) {
- try {
- data = PEM ("CERTIFICATE", data);
- }
- catch (Exception ex) {
- throw new CryptographicException (encoding_error, ex);
- }
- }
- Parse (data);
- }
- }
-
- private byte[] GetUnsignedBigInteger (byte[] integer)
- {
- if (integer [0] == 0x00) {
- // this first byte is added so we're sure it's an unsigned integer
- // however we can't feed it into RSAParameters or DSAParameters
- int length = integer.Length - 1;
- byte[] uinteger = new byte [length];
- Buffer.BlockCopy (integer, 1, uinteger, 0, length);
- return uinteger;
- }
- else
- return integer;
- }
-
- // public methods
-
- public DSA DSA {
- get {
- if (m_keyalgoparams == null)
- throw new CryptographicException ("Missing key algorithm parameters.");
-
- if (_dsa == null) {
- DSAParameters dsaParams = new DSAParameters ();
- // for DSA m_publickey contains 1 ASN.1 integer - Y
- ASN1 pubkey = new ASN1 (m_publickey);
- if ((pubkey == null) || (pubkey.Tag != 0x02))
- return null;
- dsaParams.Y = GetUnsignedBigInteger (pubkey.Value);
-
- ASN1 param = new ASN1 (m_keyalgoparams);
- if ((param == null) || (param.Tag != 0x30) || (param.Count < 3))
- return null;
- if ((param [0].Tag != 0x02) || (param [1].Tag != 0x02) || (param [2].Tag != 0x02))
- return null;
- dsaParams.P = GetUnsignedBigInteger (param [0].Value);
- dsaParams.Q = GetUnsignedBigInteger (param [1].Value);
- dsaParams.G = GetUnsignedBigInteger (param [2].Value);
-
- // BUG: MS BCL 1.0 can't import a key which
- // isn't the same size as the one present in
- // the container.
- _dsa = (DSA) new DSACryptoServiceProvider (dsaParams.Y.Length << 3);
- _dsa.ImportParameters (dsaParams);
- }
- return _dsa;
- }
-
- set {
- _dsa = value;
- if (value != null)
- _rsa = null;
- }
- }
-
- public X509ExtensionCollection Extensions {
- get { return extensions; }
- }
-
- public byte[] Hash {
- get {
- if (certhash == null) {
- HashAlgorithm hash = null;
- switch (m_signaturealgo) {
- case "1.2.840.113549.1.1.2": // MD2 with RSA encryption
- // maybe someone installed MD2 ?
-#if INSIDE_CORLIB
- hash = HashAlgorithm.Create ("MD2");
-#else
- hash = Mono.Security.Cryptography.MD2.Create ();
-#endif
- break;
- case "1.2.840.113549.1.1.4": // MD5 with RSA encryption
- hash = MD5.Create ();
- break;
- case "1.2.840.113549.1.1.5": // SHA-1 with RSA Encryption
- case "1.3.14.3.2.29": // SHA1 with RSA signature
- case "1.2.840.10040.4.3": // SHA1-1 with DSA
- hash = SHA1.Create ();
- break;
- default:
- return null;
- }
- if ((decoder == null) || (decoder.Count < 1))
- return null;
- byte[] toBeSigned = decoder [0].GetBytes ();
- certhash = hash.ComputeHash (toBeSigned, 0, toBeSigned.Length);
- }
- return (byte[]) certhash.Clone ();
- }
- }
-
- public virtual string IssuerName {
- get { return m_issuername; }
- }
-
- public virtual string KeyAlgorithm {
- get { return m_keyalgo; }
- }
-
- public virtual byte[] KeyAlgorithmParameters {
- get {
- if (m_keyalgoparams == null)
- return null;
- return (byte[]) m_keyalgoparams.Clone ();
- }
- set { m_keyalgoparams = value; }
- }
-
- public virtual byte[] PublicKey {
- get {
- if (m_publickey == null)
- return null;
- return (byte[]) m_publickey.Clone ();
- }
- }
-
- public virtual RSA RSA {
- get {
- if (_rsa == null) {
- RSAParameters rsaParams = new RSAParameters ();
- // for RSA m_publickey contains 2 ASN.1 integers
- // the modulus and the public exponent
- ASN1 pubkey = new ASN1 (m_publickey);
- ASN1 modulus = pubkey [0];
- if ((modulus == null) || (modulus.Tag != 0x02))
- return null;
- ASN1 exponent = pubkey [1];
- if (exponent.Tag != 0x02)
- return null;
-
- rsaParams.Modulus = GetUnsignedBigInteger (modulus.Value);
- rsaParams.Exponent = exponent.Value;
-
- // BUG: MS BCL 1.0 can't import a key which
- // isn't the same size as the one present in
- // the container.
- int keySize = (rsaParams.Modulus.Length << 3);
- _rsa = (RSA) new RSACryptoServiceProvider (keySize);
- _rsa.ImportParameters (rsaParams);
- }
- return _rsa;
- }
-
- set {
- if (value != null)
- _dsa = null;
- _rsa = value;
- }
- }
-
- public virtual byte[] RawData {
- get {
- if (m_encodedcert == null)
- return null;
- return (byte[]) m_encodedcert.Clone ();
- }
- }
-
- public virtual byte[] SerialNumber {
- get {
- if (serialnumber == null)
- return null;
- return (byte[]) serialnumber.Clone ();
- }
- }
-
- public virtual byte[] Signature {
- get {
- if (signature == null)
- return null;
-
- switch (m_signaturealgo) {
- case "1.2.840.113549.1.1.2": // MD2 with RSA encryption
- case "1.2.840.113549.1.1.4": // MD5 with RSA encryption
- case "1.2.840.113549.1.1.5": // SHA-1 with RSA Encryption
- case "1.3.14.3.2.29": // SHA1 with RSA signature
- return (byte[]) signature.Clone ();
-
- case "1.2.840.10040.4.3": // SHA-1 with DSA
- ASN1 sign = new ASN1 (signature);
- if ((sign == null) || (sign.Count != 2))
- return null;
- byte[] part1 = sign [0].Value;
- byte[] part2 = sign [1].Value;
- byte[] sig = new byte [40];
- // parts may be less than 20 bytes (i.e. first bytes were 0x00)
- // parts may be more than 20 bytes (i.e. first byte > 0x80, negative)
- int s1 = System.Math.Max (0, part1.Length - 20);
- int e1 = System.Math.Max (0, 20 - part1.Length);
- Buffer.BlockCopy (part1, s1, sig, e1, part1.Length - s1);
- int s2 = System.Math.Max (0, part2.Length - 20);
- int e2 = System.Math.Max (20, 40 - part2.Length);
- Buffer.BlockCopy (part2, s2, sig, e2, part2.Length - s2);
- return sig;
-
- default:
- throw new CryptographicException ("Unsupported hash algorithm: " + m_signaturealgo);
- }
- }
- }
-
- public virtual string SignatureAlgorithm {
- get { return m_signaturealgo; }
- }
-
- public virtual byte[] SignatureAlgorithmParameters {
- get {
- if (m_signaturealgoparams == null)
- return m_signaturealgoparams;
- return (byte[]) m_signaturealgoparams.Clone ();
- }
- }
-
- public virtual string SubjectName {
- get { return m_subject; }
- }
-
- public virtual DateTime ValidFrom {
- get { return m_from; }
- }
-
- public virtual DateTime ValidUntil {
- get { return m_until; }
- }
-
- public int Version {
- get { return version; }
- }
-
- public bool IsCurrent {
- get { return WasCurrent (DateTime.UtcNow); }
- }
-
- public bool WasCurrent (DateTime instant)
- {
- return ((instant > ValidFrom) && (instant <= ValidUntil));
- }
-
- // uncommon v2 "extension"
- public byte[] IssuerUniqueIdentifier {
- get {
- if (issuerUniqueID == null)
- return null;
- return (byte[]) issuerUniqueID.Clone ();
- }
- }
-
- // uncommon v2 "extension"
- public byte[] SubjectUniqueIdentifier {
- get {
- if (subjectUniqueID == null)
- return null;
- return (byte[]) subjectUniqueID.Clone ();
- }
- }
-
- internal bool VerifySignature (DSA dsa)
- {
- // signatureOID is check by both this.Hash and this.Signature
- DSASignatureDeformatter v = new DSASignatureDeformatter (dsa);
- // only SHA-1 is supported
- v.SetHashAlgorithm ("SHA1");
- return v.VerifySignature (this.Hash, this.Signature);
- }
-
- internal string GetHashNameFromOID (string oid)
- {
- switch (oid) {
- // MD2 with RSA encryption
- case "1.2.840.113549.1.1.2":
- // maybe someone installed MD2 ?
- return "MD2";
- // MD5 with RSA encryption
- case "1.2.840.113549.1.1.4":
- return "MD5";
- // SHA-1 with RSA Encryption
- case "1.2.840.113549.1.1.5":
- case "1.3.14.3.2.29":
- return "SHA1";
- default:
- return null;
- }
- }
-
- internal bool VerifySignature (RSA rsa)
- {
- RSAPKCS1SignatureDeformatter v = new RSAPKCS1SignatureDeformatter (rsa);
- string hashName = GetHashNameFromOID (m_signaturealgo);
- if (hashName == null)
- throw new CryptographicException ("Unsupported hash algorithm: " + m_signaturealgo);
-
- v.SetHashAlgorithm (hashName);
- return v.VerifySignature (this.Hash, this.Signature);
- }
-
- public bool VerifySignature (AsymmetricAlgorithm aa)
- {
- if (aa == null)
- throw new ArgumentNullException ("aa");
-
- if (aa is RSA)
- return VerifySignature (aa as RSA);
- else if (aa is DSA)
- return VerifySignature (aa as DSA);
- else
- throw new NotSupportedException ("Unknown Asymmetric Algorithm " + aa.ToString ());
- }
-
- public bool CheckSignature (byte[] hash, string hashAlgorithm, byte[] signature)
- {
- RSACryptoServiceProvider r = (RSACryptoServiceProvider) RSA;
- return r.VerifyHash (hash, hashAlgorithm, signature);
- }
-
- public bool IsSelfSigned {
- get {
- if (m_issuername == m_subject)
- return VerifySignature (RSA);
- else
- return false;
- }
- }
-
- public ASN1 GetIssuerName ()
- {
- return issuer;
- }
-
- public ASN1 GetSubjectName ()
- {
- return subject;
- }
-
- protected X509Certificate (SerializationInfo info, StreamingContext context)
- {
- Parse ((byte[]) info.GetValue ("raw", typeof (byte[])));
- }
-
- [SecurityPermission (SecurityAction.Demand, SerializationFormatter = true)]
- public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
- {
- info.AddValue ("raw", m_encodedcert);
- // note: we NEVER serialize the private key
- }
-
- static byte[] PEM (string type, byte[] data)
- {
- string pem = Encoding.ASCII.GetString (data);
- string header = String.Format ("-----BEGIN {0}-----", type);
- string footer = String.Format ("-----END {0}-----", type);
- int start = pem.IndexOf (header) + header.Length;
- int end = pem.IndexOf (footer, start);
- string base64 = pem.Substring (start, (end - start));
- return Convert.FromBase64String (base64);
- }
- }
-}
+++ /dev/null
-//
-// Based on System.Security.Cryptography.X509Certificates.X509CertificateCollection
-// in System assembly
-//
-// Authors:
-// Lawrence Pit (loz@cable.a2000.nl)
-// Sebastien Pouliot <sebastien@ximian.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.Collections;
-
-namespace Mono.Security.X509 {
-
- [Serializable]
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509CertificateCollection : CollectionBase, IEnumerable {
-
- public X509CertificateCollection ()
- {
- }
-
- public X509CertificateCollection (X509Certificate [] value)
- {
- AddRange (value);
- }
-
- public X509CertificateCollection (X509CertificateCollection value)
- {
- AddRange (value);
- }
-
- // Properties
-
- public X509Certificate this [int index] {
- get { return (X509Certificate) InnerList [index]; }
- set { InnerList [index] = value; }
- }
-
- // Methods
-
- public int Add (X509Certificate value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- return InnerList.Add (value);
- }
-
- public void AddRange (X509Certificate [] value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- for (int i = 0; i < value.Length; i++)
- InnerList.Add (value [i]);
- }
-
- public void AddRange (X509CertificateCollection value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- for (int i = 0; i < value.InnerList.Count; i++)
- InnerList.Add (value [i]);
- }
-
- public bool Contains (X509Certificate value)
- {
- return (IndexOf (value) != -1);
- }
-
- public void CopyTo (X509Certificate[] array, int index)
- {
- InnerList.CopyTo (array, index);
- }
-
- public new X509CertificateEnumerator GetEnumerator ()
- {
- return new X509CertificateEnumerator (this);
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return InnerList.GetEnumerator ();
- }
-
- public override int GetHashCode ()
- {
- return InnerList.GetHashCode ();
- }
-
- public int IndexOf (X509Certificate value)
- {
- if (value == null)
- throw new ArgumentNullException ("value");
-
- byte[] hash = value.Hash;
- for (int i=0; i < InnerList.Count; i++) {
- X509Certificate x509 = (X509Certificate) InnerList [i];
- if (Compare (x509.Hash, hash))
- return i;
- }
- return -1;
- }
-
- public void Insert (int index, X509Certificate value)
- {
- InnerList.Insert (index, value);
- }
-
- public void Remove (X509Certificate value)
- {
- InnerList.Remove (value);
- }
-
- // private stuff
-
- private bool Compare (byte[] array1, byte[] array2)
- {
- if ((array1 == null) && (array2 == null))
- return true;
- if ((array1 == null) || (array2 == null))
- return false;
- if (array1.Length != array2.Length)
- return false;
- for (int i=0; i < array1.Length; i++) {
- if (array1 [i] != array2 [i])
- return false;
- }
- return true;
- }
-
- // Inner Class
-
- public class X509CertificateEnumerator : IEnumerator {
-
- private IEnumerator enumerator;
-
- // Constructors
-
- public X509CertificateEnumerator (X509CertificateCollection mappings)
- {
- enumerator = ((IEnumerable) mappings).GetEnumerator ();
- }
-
- // Properties
-
- public X509Certificate Current {
- get { return (X509Certificate) enumerator.Current; }
- }
-
- object IEnumerator.Current {
- get { return enumerator.Current; }
- }
-
- // Methods
-
- bool IEnumerator.MoveNext ()
- {
- return enumerator.MoveNext ();
- }
-
- void IEnumerator.Reset ()
- {
- enumerator.Reset ();
- }
-
- public bool MoveNext ()
- {
- return enumerator.MoveNext ();
- }
-
- public void Reset ()
- {
- enumerator.Reset ();
- }
- }
- }
-}
+++ /dev/null
-//
-// X509Chain.cs: X.509 Certificate Path
-// This is a VERY simplified and minimal version
-// used for
-// Authenticode support
-// TLS/SSL support
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 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;
-using System.Security.Permissions;
-
-#if !INSIDE_CORLIB
-using System.Net;
-#endif
-
-using Mono.Security.X509.Extensions;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509Chain {
-
- private X509CertificateCollection roots;
- private X509CertificateCollection certs;
- private X509Certificate _root;
-
- private X509CertificateCollection _chain;
- private X509ChainStatusFlags _status;
-
- // constructors
-
- public X509Chain ()
- {
- certs = new X509CertificateCollection ();
- }
-
- // get a pre-builded chain
- public X509Chain (X509CertificateCollection chain) : this ()
- {
- _chain = new X509CertificateCollection ();
- _chain.AddRange (chain);
- }
-
- // properties
-
- public X509CertificateCollection Chain {
- get { return _chain; }
- }
-
- // the root of the specified certificate (may not be trusted!)
- public X509Certificate Root {
- get { return _root; }
- }
-
- public X509ChainStatusFlags Status {
- get { return _status; }
- }
-
- public X509CertificateCollection TrustAnchors {
- get {
- if (roots == null) {
- roots = new X509CertificateCollection ();
- roots.AddRange (X509StoreManager.TrustedRootCertificates);
- return roots;
- }
- return roots;
- }
- [SecurityPermission (SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPolicy)]
- set { roots = value; }
- }
-
- // methods
-
- public void LoadCertificate (X509Certificate x509)
- {
- certs.Add (x509);
- }
-
- public void LoadCertificates (X509CertificateCollection collection)
- {
- certs.AddRange (collection);
- }
-
- public X509Certificate FindByIssuerName (string issuerName)
- {
- foreach (X509Certificate x in certs) {
- if (x.IssuerName == issuerName)
- return x;
- }
- return null;
- }
-
- public bool Build (X509Certificate leaf)
- {
- _status = X509ChainStatusFlags.NoError;
- if (_chain == null) {
- // chain not supplied - we must build it ourselve
- _chain = new X509CertificateCollection ();
- X509Certificate x = leaf;
- X509Certificate tmp = x;
- while ((x != null) && (!x.IsSelfSigned)) {
- tmp = x; // last valid
- _chain.Add (x);
- x = FindCertificateParent (x);
- }
- // find a trusted root
- _root = FindCertificateRoot (tmp);
- }
- else {
- // chain supplied - still have to check signatures!
- int last = _chain.Count;
- if (last > 0) {
- if (IsParent (leaf, _chain [0])) {
- int i = 1;
- for (; i < last; i++) {
- if (!IsParent (_chain [i-1], _chain [i]))
- break;
- }
- if (i == last)
- _root = FindCertificateRoot (_chain [last - 1]);
- }
- }
- else {
- // is the leaf a root ? (trusted or untrusted)
- _root = FindCertificateRoot (leaf);
- }
- }
-
- // validate the chain
- if ((_chain != null) && (_status == X509ChainStatusFlags.NoError)) {
- foreach (X509Certificate x in _chain) {
- // validate dates for each certificate in the chain
- // note: we DO NOT check for nested date/time
- if (!IsValid (x)) {
- return false;
- }
- }
- // check leaf
- if (!IsValid (leaf)) {
- // switch status code if the failure is expiration
- if (_status == X509ChainStatusFlags.NotTimeNested)
- _status = X509ChainStatusFlags.NotTimeValid;
- return false;
- }
- // check root
- if ((_root != null) && !IsValid (_root)) {
- return false;
- }
- }
- return (_status == X509ChainStatusFlags.NoError);
- }
-
- //
-
- public void Reset ()
- {
- _status = X509ChainStatusFlags.NoError;
- roots = null; // this force a reload
- certs.Clear ();
- if (_chain != null)
- _chain.Clear ();
- }
-
- // private stuff
-
- private bool IsValid (X509Certificate cert)
- {
- if (!cert.IsCurrent) {
- // FIXME: nesting isn't very well implemented
- _status = X509ChainStatusFlags.NotTimeNested;
- return false;
- }
-
- // TODO - we should check for CRITICAL but unknown extensions
- // X509ChainStatusFlags.InvalidExtension
-#if !INSIDE_CORLIB
- if (ServicePointManager.CheckCertificateRevocationList) {
- // TODO - check revocation (CRL, OCSP ...)
- // X509ChainStatusFlags.RevocationStatusUnknown
- // X509ChainStatusFlags.Revoked
- }
-#endif
- return true;
- }
-
- private X509Certificate FindCertificateParent (X509Certificate child)
- {
- foreach (X509Certificate potentialParent in certs) {
- if (IsParent (child, potentialParent))
- return potentialParent;
- }
- return null;
- }
-
- private X509Certificate FindCertificateRoot (X509Certificate potentialRoot)
- {
- if (potentialRoot == null) {
- _status = X509ChainStatusFlags.PartialChain;
- return null;
- }
-
- // if the trusted root is in the chain
- if (IsTrusted (potentialRoot)) {
- return potentialRoot;
- }
-
- // if the root isn't in the chain
- foreach (X509Certificate root in TrustAnchors) {
- if (IsParent (potentialRoot, root)) {
- return root;
- }
- }
-
- // is it a (untrusted) root ?
- if (potentialRoot.IsSelfSigned) {
- _status = X509ChainStatusFlags.UntrustedRoot;
- return potentialRoot;
- }
-
- _status = X509ChainStatusFlags.PartialChain;
- return null;
- }
-
- private bool IsTrusted (X509Certificate potentialTrusted)
- {
- return TrustAnchors.Contains (potentialTrusted);
- }
-
- private bool IsParent (X509Certificate child, X509Certificate parent)
- {
- if (child.IssuerName != parent.SubjectName)
- return false;
-
- // parent MUST have the Basic Constraint CA=true (except for trusted roots)
- // see why at http://www.microsoft.com/technet/security/bulletin/MS02-050.asp
- if ((parent.Version > 2) && (!IsTrusted (parent))) {
- // TODO: we do not support pathLenConstraint
- X509Extension ext = parent.Extensions ["2.5.29.19"];
- if (ext != null) {
- BasicConstraintsExtension bc = new BasicConstraintsExtension (ext);
- if (!bc.CertificateAuthority)
- _status = X509ChainStatusFlags.InvalidBasicConstraints;
- }
- else
- _status = X509ChainStatusFlags.InvalidBasicConstraints;
- }
-
- if (!child.VerifySignature (parent.RSA)) {
- _status = X509ChainStatusFlags.NotSignatureValid;
- return false;
- }
- return true;
- }
- }
-}
+++ /dev/null
-//
-// X509ChainStatusFlags.cs: X.509 Chain Status
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2004 Novell (http://www.novell.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;
-
-namespace Mono.Security.X509 {
-
- // definitions from Fx 1.2
- // commented flags aren't implemented in X509Chain
-
- [Serializable]
- [Flags]
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- enum X509ChainStatusFlags {
-// CtlNotSignatureValid = 262144,
-// CtlNotTimeValid = 131072,
-// CtlNotValidForUsage = 524288,
-// Cyclic = 128,
-// HasExcludedNameConstraint = 32768,
-// HasNotDefinedNameConstraint = 8192,
-// HasNotPermittedNameConstraint = 16384,
-// HasNotSupportedNameConstraint = 4096,
- InvalidBasicConstraints = 1024,
-// InvalidExtension = 256,
-// InvalidNameConstraints = 2048,
-// InvalidPolicyConstraints = 512,
- NoError = 0,
-// NoIssuanceChainPolicy = 33554432,
- NotSignatureValid = 8,
- NotTimeNested = 2,
- NotTimeValid = 1,
-// NotValidForUsage = 16,
-// OfflineRevocation = 16777216,
- PartialChain = 65536,
-// RevocationStatusUnknown = 64,
-// Revoked = 4,
- UntrustedRoot = 32
- }
-}
+++ /dev/null
-//
-// X509Extension.cs: Base class for all X.509 extensions.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 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.Globalization;
-using System.Text;
-
-using Mono.Security;
-
-namespace Mono.Security.X509 {
- /*
- * Extension ::= SEQUENCE {
- * extnID OBJECT IDENTIFIER,
- * critical BOOLEAN DEFAULT FALSE,
- * extnValue OCTET STRING
- * }
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509Extension {
-
- protected string extnOid;
- protected bool extnCritical;
- protected ASN1 extnValue;
-
- protected X509Extension ()
- {
- extnCritical = false;
- }
-
- public X509Extension (ASN1 asn1)
- {
- if ((asn1.Tag != 0x30) || (asn1.Count < 2))
- throw new ArgumentException (Locale.GetText ("Invalid X.509 extension."));
- if (asn1[0].Tag != 0x06)
- throw new ArgumentException (Locale.GetText ("Invalid X.509 extension."));
-
- extnOid = ASN1Convert.ToOid (asn1[0]);
- extnCritical = ((asn1[1].Tag == 0x01) && (asn1[1].Value[0] == 0xFF));
- // last element is an octet string which may need to be decoded
- extnValue = asn1 [asn1.Count - 1];
- if ((extnValue.Tag == 0x04) && (extnValue.Length > 0) && (extnValue.Count == 0)) {
- try {
- ASN1 encapsulated = new ASN1 (extnValue.Value);
- extnValue.Value = null;
- extnValue.Add (encapsulated);
- }
- catch {
- // data isn't ASN.1
- }
- }
- Decode ();
- }
-
- public X509Extension (X509Extension extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
- if ((extension.Value == null) || (extension.Value.Tag != 0x04) || (extension.Value.Count != 1))
- throw new ArgumentException (Locale.GetText ("Invalid X.509 extension."));
-
- extnOid = extension.Oid;
- extnCritical = extension.Critical;
- extnValue = extension.Value;
- Decode ();
- }
-
- // encode the extension *into* an OCTET STRING
- protected virtual void Decode ()
- {
- }
-
- // decode the extension from *inside* an OCTET STRING
- protected virtual void Encode ()
- {
- }
-
- public ASN1 ASN1 {
- get {
- ASN1 extension = new ASN1 (0x30);
- extension.Add (ASN1Convert.FromOid (extnOid));
- if (extnCritical)
- extension.Add (new ASN1 (0x01, new byte [1] { 0xFF }));
- Encode ();
- extension.Add (extnValue);
- return extension;
- }
- }
-
- public string Oid {
- get { return extnOid; }
- }
-
- public bool Critical {
- get { return extnCritical; }
- set { extnCritical = value; }
- }
-
- // this gets overrided with more meaningful names
- public virtual string Name {
- get { return extnOid; }
- }
-
- public ASN1 Value {
- get {
- if (extnValue == null) {
- Encode ();
- }
- return extnValue;
- }
- }
-
- public override bool Equals (object obj)
- {
- if (obj == null)
- return false;
-
- X509Extension ex = (obj as X509Extension);
- if (ex == null)
- return false;
-
- if (extnCritical != ex.extnCritical)
- return false;
- if (extnOid != ex.extnOid)
- return false;
- if (extnValue.Length != ex.extnValue.Length)
- return false;
-
- for (int i=0; i < extnValue.Length; i++) {
- if (extnValue [i] != ex.extnValue [i])
- return false;
- }
- return true;
- }
-
- public byte[] GetBytes ()
- {
- return ASN1.GetBytes ();
- }
-
- public override int GetHashCode ()
- {
- // OID should be unique in a collection of extensions
- return extnOid.GetHashCode ();
- }
-
- private void WriteLine (StringBuilder sb, int n, int pos)
- {
- byte[] value = extnValue.Value;
- int p = pos;
- for (int j=0; j < 8; j++) {
- if (j < n) {
- sb.Append (value [p++].ToString ("X2", CultureInfo.InvariantCulture));
- sb.Append (" ");
- }
- else
- sb.Append (" ");
- }
- sb.Append (" ");
- p = pos;
- for (int j=0; j < n; j++) {
- byte b = value [p++];
- if (b < 0x20)
- sb.Append (".");
- else
- sb.Append (Convert.ToChar (b));
- }
- sb.Append (Environment.NewLine);
- }
-
- public override string ToString ()
- {
- StringBuilder sb = new StringBuilder ();
- int div = (extnValue.Length >> 3);
- int rem = (extnValue.Length - (div << 3));
- int x = 0;
- for (int i=0; i < div; i++) {
- WriteLine (sb, 8, x);
- x += 8;
- }
- WriteLine (sb, rem, x);
- return sb.ToString ();
- }
- }
-}
+++ /dev/null
-//
-// X509Extensions.cs: Handles X.509 extensions.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 Novell (http://www.novell.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.Collections;
-
-using Mono.Security;
-
-namespace Mono.Security.X509 {
- /*
- * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
- *
- * Note: 1..MAX -> There shouldn't be 0 Extensions in the ASN1 structure
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class X509ExtensionCollection : CollectionBase, IEnumerable {
-
- private bool readOnly;
-
- public X509ExtensionCollection () : base ()
- {
- }
-
- public X509ExtensionCollection (ASN1 asn1) : this ()
- {
- readOnly = true;
- if (asn1 == null)
- return;
- if (asn1.Tag != 0x30)
- throw new Exception ("Invalid extensions format");
- for (int i=0; i < asn1.Count; i++) {
- X509Extension extension = new X509Extension (asn1 [i]);
- InnerList.Add (extension);
- }
- }
-
- public int Add (X509Extension extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
- if (readOnly)
- throw new NotSupportedException ("Extensions are read only");
-
- return InnerList.Add (extension);
- }
-
- public void AddRange (X509Extension[] extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
- if (readOnly)
- throw new NotSupportedException ("Extensions are read only");
-
- for (int i = 0; i < extension.Length; i++)
- InnerList.Add (extension [i]);
- }
-
- public void AddRange (X509ExtensionCollection collection)
- {
- if (collection == null)
- throw new ArgumentNullException ("collection");
- if (readOnly)
- throw new NotSupportedException ("Extensions are read only");
-
- for (int i = 0; i < collection.InnerList.Count; i++)
- InnerList.Add (collection [i]);
- }
-
- public bool Contains (X509Extension extension)
- {
- return (IndexOf (extension) != -1);
- }
-
- public bool Contains (string oid)
- {
- return (IndexOf (oid) != -1);
- }
-
- public void CopyTo (X509Extension[] extensions, int index)
- {
- if (extensions == null)
- throw new ArgumentNullException ("extensions");
-
- InnerList.CopyTo (extensions, index);
- }
-
- public int IndexOf (X509Extension extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
-
- for (int i=0; i < InnerList.Count; i++) {
- X509Extension ex = (X509Extension) InnerList [i];
- if (ex.Equals (extension))
- return i;
- }
- return -1;
- }
-
- public int IndexOf (string oid)
- {
- if (oid == null)
- throw new ArgumentNullException ("oid");
-
- for (int i=0; i < InnerList.Count; i++) {
- X509Extension ex = (X509Extension) InnerList [i];
- if (ex.Oid == oid)
- return i;
- }
- return -1;
- }
-
- public void Insert (int index, X509Extension extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
-
- InnerList.Insert (index, extension);
- }
-
- public void Remove (X509Extension extension)
- {
- if (extension == null)
- throw new ArgumentNullException ("extension");
-
- InnerList.Remove (extension);
- }
-
- public void Remove (string oid)
- {
- if (oid == null)
- throw new ArgumentNullException ("oid");
-
- int index = IndexOf (oid);
- if (index != -1)
- InnerList.RemoveAt (index);
- }
-
- IEnumerator IEnumerable.GetEnumerator ()
- {
- return InnerList.GetEnumerator ();
- }
-
- public X509Extension this [int index] {
- get { return (X509Extension) InnerList [index]; }
- }
-
- public X509Extension this [string oid] {
- get {
- int index = IndexOf (oid);
- if (index == -1)
- return null;
- return (X509Extension) InnerList [index];
- }
- }
-
- public byte[] GetBytes ()
- {
- if (InnerList.Count < 1)
- return null;
- ASN1 sequence = new ASN1 (0x30);
- for (int i=0; i < InnerList.Count; i++) {
- X509Extension x = (X509Extension) InnerList [i];
- sequence.Add (x.ASN1);
- }
- return sequence.GetBytes ();
- }
- }
-}
+++ /dev/null
-//
-// X509Store.cs: Handles a X.509 certificates/CRLs store
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Pablo Ruiz <pruiz@netway.org>
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// (C) 2010 Pablo Ruiz.
-//
-// 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.Collections;
-using System.Globalization;
-using System.IO;
-using System.Text;
-using System.Security.Cryptography;
-
-using Mono.Security.Cryptography;
-using Mono.Security.X509.Extensions;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509Store {
-
- private string _storePath;
- private X509CertificateCollection _certificates;
- private ArrayList _crls;
- private bool _crl;
- private string _name;
-
- internal X509Store (string path, bool crl)
- {
- _storePath = path;
- _crl = crl;
- }
-
- // properties
-
- public X509CertificateCollection Certificates {
- get {
- if (_certificates == null) {
- _certificates = BuildCertificatesCollection (_storePath);
- }
- return _certificates;
- }
- }
-
- public ArrayList Crls {
- get {
- // CRL aren't applicable to all stores
- // but returning null is a little rude
- if (!_crl) {
- _crls = new ArrayList ();
- }
- if (_crls == null) {
- _crls = BuildCrlsCollection (_storePath);
- }
- return _crls;
- }
- }
-
- public string Name {
- get {
- if (_name == null) {
- int n = _storePath.LastIndexOf (Path.DirectorySeparatorChar);
- _name = _storePath.Substring (n+1);
- }
- return _name;
- }
- }
-
- // methods
-
- public void Clear ()
- {
- if (_certificates != null)
- _certificates.Clear ();
- _certificates = null;
- if (_crls != null)
- _crls.Clear ();
- _crls = null;
- }
-
- public void Import (X509Certificate certificate)
- {
- CheckStore (_storePath, true);
-
- string filename = Path.Combine (_storePath, GetUniqueName (certificate));
- if (!File.Exists (filename)) {
- using (FileStream fs = File.Create (filename)) {
- byte[] data = certificate.RawData;
- fs.Write (data, 0, data.Length);
- fs.Close ();
- }
- }
-#if !NET_2_1
- // Try to save privateKey if available..
- CspParameters cspParams = new CspParameters ();
- cspParams.KeyContainerName = CryptoConvert.ToHex (certificate.Hash);
-
- // Right now this seems to be the best way to know if we should use LM store.. ;)
- if (_storePath.StartsWith (X509StoreManager.LocalMachinePath))
- cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
-
- ImportPrivateKey (certificate, cspParams);
-#endif
- }
-
- public void Import (X509Crl crl)
- {
- CheckStore (_storePath, true);
-
- string filename = Path.Combine (_storePath, GetUniqueName (crl));
- if (!File.Exists (filename)) {
- using (FileStream fs = File.Create (filename)) {
- byte[] data = crl.RawData;
- fs.Write (data, 0, data.Length);
- }
- }
- }
-
- public void Remove (X509Certificate certificate)
- {
- string filename = Path.Combine (_storePath, GetUniqueName (certificate));
- if (File.Exists (filename)) {
- File.Delete (filename);
- }
- }
-
- public void Remove (X509Crl crl)
- {
- string filename = Path.Combine (_storePath, GetUniqueName (crl));
- if (File.Exists (filename)) {
- File.Delete (filename);
- }
- }
-
- // private stuff
-
- private string GetUniqueName (X509Certificate certificate)
- {
- string method;
- byte[] name = GetUniqueName (certificate.Extensions);
- if (name == null) {
- method = "tbp"; // thumbprint
- name = certificate.Hash;
- } else {
- method = "ski";
- }
- return GetUniqueName (method, name, ".cer");
- }
-
- private string GetUniqueName (X509Crl crl)
- {
- string method;
- byte[] name = GetUniqueName (crl.Extensions);
- if (name == null) {
- method = "tbp"; // thumbprint
- name = crl.Hash;
- } else {
- method = "ski";
- }
- return GetUniqueName (method, name, ".crl");
- }
-
- private byte[] GetUniqueName (X509ExtensionCollection extensions)
- {
- // We prefer Subject Key Identifier as the unique name
- // as it will provide faster lookups
- X509Extension ext = extensions ["2.5.29.14"];
- if (ext == null)
- return null;
-
- SubjectKeyIdentifierExtension ski = new SubjectKeyIdentifierExtension (ext);
- return ski.Identifier;
- }
-
- private string GetUniqueName (string method, byte[] name, string fileExtension)
- {
- StringBuilder sb = new StringBuilder (method);
-
- sb.Append ("-");
- foreach (byte b in name) {
- sb.Append (b.ToString ("X2", CultureInfo.InvariantCulture));
- }
- sb.Append (fileExtension);
-
- return sb.ToString ();
- }
-
- private byte[] Load (string filename)
- {
- byte[] data = null;
- using (FileStream fs = File.OpenRead (filename)) {
- data = new byte [fs.Length];
- fs.Read (data, 0, data.Length);
- fs.Close ();
- }
- return data;
- }
-
- private X509Certificate LoadCertificate (string filename)
- {
- byte[] data = Load (filename);
- X509Certificate cert = new X509Certificate (data);
-#if !NET_2_1
- // If privateKey it's available, load it too..
- CspParameters cspParams = new CspParameters ();
- cspParams.KeyContainerName = CryptoConvert.ToHex (cert.Hash);
- if (_storePath.StartsWith (X509StoreManager.LocalMachinePath))
- cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
- KeyPairPersistence kpp = new KeyPairPersistence (cspParams);
-
- if (!kpp.Load ())
- return cert;
-
- if (cert.RSA != null)
- cert.RSA = new RSACryptoServiceProvider (cspParams);
- else if (cert.DSA != null)
- cert.DSA = new DSACryptoServiceProvider (cspParams);
-#endif
- return cert;
- }
-
- private X509Crl LoadCrl (string filename)
- {
- byte[] data = Load (filename);
- X509Crl crl = new X509Crl (data);
- return crl;
- }
-
- private bool CheckStore (string path, bool throwException)
- {
- try {
- if (Directory.Exists (path))
- return true;
- Directory.CreateDirectory (path);
- return Directory.Exists (path);
- }
- catch {
- if (throwException)
- throw;
- return false;
- }
- }
-
- private X509CertificateCollection BuildCertificatesCollection (string storeName)
- {
- X509CertificateCollection coll = new X509CertificateCollection ();
- string path = Path.Combine (_storePath, storeName);
- if (!CheckStore (path, false))
- return coll; // empty collection
-
- string[] files = Directory.GetFiles (path, "*.cer");
- if ((files != null) && (files.Length > 0)) {
- foreach (string file in files) {
- try {
- X509Certificate cert = LoadCertificate (file);
- coll.Add (cert);
- }
- catch {
- // in case someone is dumb enough
- // (like me) to include a base64
- // encoded certs (or other junk
- // into the store).
- }
- }
- }
- return coll;
- }
-
- private ArrayList BuildCrlsCollection (string storeName)
- {
- ArrayList list = new ArrayList ();
- string path = Path.Combine (_storePath, storeName);
- if (!CheckStore (path, false))
- return list; // empty list
-
- string[] files = Directory.GetFiles (path, "*.crl");
- if ((files != null) && (files.Length > 0)) {
- foreach (string file in files) {
- try {
- X509Crl crl = LoadCrl (file);
- list.Add (crl);
- }
- catch {
- // junk catcher
- }
- }
- }
- return list;
- }
-#if !NET_2_1
- private void ImportPrivateKey (X509Certificate certificate, CspParameters cspParams)
- {
- RSACryptoServiceProvider rsaCsp = certificate.RSA as RSACryptoServiceProvider;
- if (rsaCsp != null) {
- if (rsaCsp.PublicOnly)
- return;
-
- RSACryptoServiceProvider csp = new RSACryptoServiceProvider(cspParams);
- csp.ImportParameters(rsaCsp.ExportParameters(true));
- csp.PersistKeyInCsp = true;
- return;
- }
-
- RSAManaged rsaMng = certificate.RSA as RSAManaged;
- if (rsaMng != null) {
- if (rsaMng.PublicOnly)
- return;
-
- RSACryptoServiceProvider csp = new RSACryptoServiceProvider(cspParams);
- csp.ImportParameters(rsaMng.ExportParameters(true));
- csp.PersistKeyInCsp = true;
- return;
- }
-
- DSACryptoServiceProvider dsaCsp = certificate.DSA as DSACryptoServiceProvider;
- if (dsaCsp != null) {
- if (dsaCsp.PublicOnly)
- return;
-
- DSACryptoServiceProvider csp = new DSACryptoServiceProvider(cspParams);
- csp.ImportParameters(dsaCsp.ExportParameters(true));
- csp.PersistKeyInCsp = true;
- }
- }
-#endif
- }
-}
+++ /dev/null
-//
-// X509StoreManager.cs: X.509 store manager.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2004 Novell (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.Collections;
-using System.IO;
-
-using Mono.Security.X509.Extensions;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class X509StoreManager {
-
- static private string _userPath;
- static private string _localMachinePath;
- static private X509Stores _userStore;
- static private X509Stores _machineStore;
-
- private X509StoreManager ()
- {
- }
-
- internal static string CurrentUserPath {
- get {
- if (_userPath == null) {
- _userPath = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
- ".mono");
- _userPath = Path.Combine(_userPath, "certs");
- }
- return _userPath;
- }
- }
-
- internal static string LocalMachinePath {
- get {
- if (_localMachinePath == null) {
- _localMachinePath = Path.Combine (
- Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData),
- ".mono");
- _localMachinePath = Path.Combine (_localMachinePath, "certs");
- }
- return _localMachinePath;
- }
- }
-
- static public X509Stores CurrentUser {
- get {
- if (_userStore == null)
- _userStore = new X509Stores(CurrentUserPath);
-
- return _userStore;
- }
- }
-
- static public X509Stores LocalMachine {
- get {
- if (_machineStore == null)
- _machineStore = new X509Stores (LocalMachinePath);
-
- return _machineStore;
- }
- }
-
- // Merged stores collections
- // we need to look at both the user and the machine (entreprise)
- // certificates/CRLs when building/validating a chain
-
- static public X509CertificateCollection IntermediateCACertificates {
- get {
- X509CertificateCollection intermediateCerts = new X509CertificateCollection ();
- intermediateCerts.AddRange (CurrentUser.IntermediateCA.Certificates);
- intermediateCerts.AddRange (LocalMachine.IntermediateCA.Certificates);
- return intermediateCerts;
- }
- }
-
- static public ArrayList IntermediateCACrls {
- get {
- ArrayList intermediateCRLs = new ArrayList ();
- intermediateCRLs.AddRange (CurrentUser.IntermediateCA.Crls);
- intermediateCRLs.AddRange (LocalMachine.IntermediateCA.Crls);
- return intermediateCRLs;
- }
- }
-
- static public X509CertificateCollection TrustedRootCertificates {
- get {
- X509CertificateCollection trustedCerts = new X509CertificateCollection ();
- trustedCerts.AddRange (CurrentUser.TrustedRoot.Certificates);
- trustedCerts.AddRange (LocalMachine.TrustedRoot.Certificates);
- return trustedCerts;
- }
- }
-
- static public ArrayList TrustedRootCACrls {
- get {
- ArrayList trustedCRLs = new ArrayList ();
- trustedCRLs.AddRange (CurrentUser.TrustedRoot.Crls);
- trustedCRLs.AddRange (LocalMachine.TrustedRoot.Crls);
- return trustedCRLs;
- }
- }
-
- static public X509CertificateCollection UntrustedCertificates {
- get {
- X509CertificateCollection untrustedCerts = new X509CertificateCollection ();
- untrustedCerts.AddRange (CurrentUser.Untrusted.Certificates);
- untrustedCerts.AddRange (LocalMachine.Untrusted.Certificates);
- return untrustedCerts;
- }
- }
- }
-}
+++ /dev/null
-//
-// X509Stores.cs: Handles X.509 certificates/CRLs stores group.
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2004 Novell (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.Collections;
-using System.IO;
-
-using Mono.Security.X509.Extensions;
-
-namespace Mono.Security.X509 {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X509Stores {
-
- private string _storePath;
- private X509Store _personal;
- private X509Store _other;
- private X509Store _intermediate;
- private X509Store _trusted;
- private X509Store _untrusted;
-
- internal X509Stores (string path)
- {
- _storePath = path;
- }
-
- // properties
-
- public X509Store Personal {
- get {
- if (_personal == null) {
- string path = Path.Combine (_storePath, Names.Personal);
- _personal = new X509Store (path, false);
- }
- return _personal;
- }
- }
-
- public X509Store OtherPeople {
- get {
- if (_other == null) {
- string path = Path.Combine (_storePath, Names.OtherPeople);
- _other = new X509Store (path, false);
- }
- return _other;
- }
- }
-
- public X509Store IntermediateCA {
- get {
- if (_intermediate == null) {
- string path = Path.Combine (_storePath, Names.IntermediateCA);
- _intermediate = new X509Store (path, true);
- }
- return _intermediate;
- }
- }
-
- public X509Store TrustedRoot {
- get {
- if (_trusted == null) {
- string path = Path.Combine (_storePath, Names.TrustedRoot);
- _trusted = new X509Store (path, true);
- }
- return _trusted;
- }
- }
-
- public X509Store Untrusted {
- get {
- if (_untrusted == null) {
- string path = Path.Combine (_storePath, Names.Untrusted);
- _untrusted = new X509Store (path, false);
- }
- return _untrusted;
- }
- }
-
- // methods
-
- public void Clear ()
- {
- // this will force a reload of all stores
- if (_personal != null)
- _personal.Clear ();
- _personal = null;
- if (_other != null)
- _other.Clear ();
- _other = null;
- if (_intermediate != null)
- _intermediate.Clear ();
- _intermediate = null;
- if (_trusted != null)
- _trusted.Clear ();
- _trusted = null;
- if (_untrusted != null)
- _untrusted.Clear ();
- _untrusted = null;
- }
-
- public X509Store Open (string storeName, bool create)
- {
- if (storeName == null)
- throw new ArgumentNullException ("storeName");
-
- string path = Path.Combine (_storePath, storeName);
- if (!create && !Directory.Exists (path))
- return null;
-
- return new X509Store (path, true);
- }
-
- // names
-
- public class Names {
-
- // do not translate
- public const string Personal = "My";
- public const string OtherPeople = "AddressBook";
- public const string IntermediateCA = "CA";
- public const string TrustedRoot = "Trust";
- public const string Untrusted = "Disallowed";
-
- public Names () {}
- }
- }
-}
+++ /dev/null
-//
-// X520.cs: X.520 related stuff (attributes, RDN)
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 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.Globalization;
-using System.Text;
-
-using Mono.Security;
-
-namespace Mono.Security.X509 {
-
- // References:
- // 1. Information technology - Open Systems Interconnection - The Directory: Selected attribute types
- // http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.520
- // 2. Internet X.509 Public Key Infrastructure Certificate and CRL Profile
- // http://www.ietf.org/rfc/rfc3280.txt
- // 3. A Summary of the X.500(96) User Schema for use with LDAPv3
- // http://www.faqs.org/rfcs/rfc2256.html
- // 4. RFC 2247 - Using Domains in LDAP/X.500 Distinguished Names
- // http://www.faqs.org/rfcs/rfc2247.html
-
- /*
- * AttributeTypeAndValue ::= SEQUENCE {
- * type AttributeType,
- * value AttributeValue
- * }
- *
- * AttributeType ::= OBJECT IDENTIFIER
- *
- * AttributeValue ::= ANY DEFINED BY AttributeType
- */
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class X520 {
-
- public abstract class AttributeTypeAndValue {
- private string oid;
- private string attrValue;
- private int upperBound;
- private byte encoding;
-
- protected AttributeTypeAndValue (string oid, int upperBound)
- {
- this.oid = oid;
- this.upperBound = upperBound;
- this.encoding = 0xFF;
- }
-
- protected AttributeTypeAndValue (string oid, int upperBound, byte encoding)
- {
- this.oid = oid;
- this.upperBound = upperBound;
- this.encoding = encoding;
- }
-
- public string Value {
- get { return attrValue; }
- set {
- if ((attrValue != null) && (attrValue.Length > upperBound)) {
- string msg = Locale.GetText ("Value length bigger than upperbound ({0}).");
- throw new FormatException (String.Format (msg, upperBound));
- }
- attrValue = value;
- }
- }
-
- public ASN1 ASN1 {
- get { return GetASN1 (); }
- }
-
- internal ASN1 GetASN1 (byte encoding)
- {
- byte encode = encoding;
- if (encode == 0xFF)
- encode = SelectBestEncoding ();
-
- ASN1 asn1 = new ASN1 (0x30);
- asn1.Add (ASN1Convert.FromOid (oid));
- switch (encode) {
- case 0x13:
- // PRINTABLESTRING
- asn1.Add (new ASN1 (0x13, Encoding.ASCII.GetBytes (attrValue)));
- break;
- case 0x16:
- // IA5STRING
- asn1.Add (new ASN1 (0x16, Encoding.ASCII.GetBytes (attrValue)));
- break;
- case 0x1E:
- // BMPSTRING
- asn1.Add (new ASN1 (0x1E, Encoding.BigEndianUnicode.GetBytes (attrValue)));
- break;
- }
- return asn1;
- }
-
- internal ASN1 GetASN1 ()
- {
- return GetASN1 (encoding);
- }
-
- public byte[] GetBytes (byte encoding)
- {
- return GetASN1 (encoding) .GetBytes ();
- }
-
- public byte[] GetBytes ()
- {
- return GetASN1 () .GetBytes ();
- }
-
- private byte SelectBestEncoding ()
- {
- foreach (char c in attrValue) {
- switch (c) {
- case '@':
- case '_':
- return 0x1E; // BMPSTRING
- default:
- if (c > 127)
- return 0x1E; // BMPSTRING
- break;
- }
- }
- return 0x13; // PRINTABLESTRING
- }
- }
-
- public class Name : AttributeTypeAndValue {
-
- public Name () : base ("2.5.4.41", 32768)
- {
- }
- }
-
- public class CommonName : AttributeTypeAndValue {
-
- public CommonName () : base ("2.5.4.3", 64)
- {
- }
- }
-
- // RFC2256, Section 5.6
- public class SerialNumber : AttributeTypeAndValue {
-
- // max length 64 bytes, Printable String only
- public SerialNumber ()
- : base ("2.5.4.5", 64, 0x13)
- {
- }
- }
-
- public class LocalityName : AttributeTypeAndValue {
-
- public LocalityName () : base ("2.5.4.7", 128)
- {
- }
- }
-
- public class StateOrProvinceName : AttributeTypeAndValue {
-
- public StateOrProvinceName () : base ("2.5.4.8", 128)
- {
- }
- }
-
- public class OrganizationName : AttributeTypeAndValue {
-
- public OrganizationName () : base ("2.5.4.10", 64)
- {
- }
- }
-
- public class OrganizationalUnitName : AttributeTypeAndValue {
-
- public OrganizationalUnitName () : base ("2.5.4.11", 64)
- {
- }
- }
-
- // NOTE: Not part of RFC2253
- public class EmailAddress : AttributeTypeAndValue {
-
- public EmailAddress () : base ("1.2.840.113549.1.9.1", 128, 0x16)
- {
- }
- }
-
- // RFC2247, Section 4
- public class DomainComponent : AttributeTypeAndValue {
-
- // no maximum length defined
- public DomainComponent ()
- : base ("0.9.2342.19200300.100.1.25", Int32.MaxValue, 0x16)
- {
- }
- }
-
- // RFC1274, Section 9.3.1
- public class UserId : AttributeTypeAndValue {
-
- public UserId ()
- : base ("0.9.2342.19200300.100.1.1", 256)
- {
- }
- }
-
- public class Oid : AttributeTypeAndValue {
-
- public Oid (string oid)
- : base (oid, Int32.MaxValue)
- {
- }
- }
-
- /* -- Naming attributes of type X520Title
- * id-at-title AttributeType ::= { id-at 12 }
- *
- * X520Title ::= CHOICE {
- * teletexString TeletexString (SIZE (1..ub-title)),
- * printableString PrintableString (SIZE (1..ub-title)),
- * universalString UniversalString (SIZE (1..ub-title)),
- * utf8String UTF8String (SIZE (1..ub-title)),
- * bmpString BMPString (SIZE (1..ub-title))
- * }
- */
- public class Title : AttributeTypeAndValue {
-
- public Title () : base ("2.5.4.12", 64)
- {
- }
- }
-
- public class CountryName : AttributeTypeAndValue {
-
- // (0x13) PRINTABLESTRING
- public CountryName () : base ("2.5.4.6", 2, 0x13)
- {
- }
- }
-
- public class DnQualifier : AttributeTypeAndValue {
-
- // (0x13) PRINTABLESTRING
- public DnQualifier () : base ("2.5.4.46", 2, 0x13)
- {
- }
- }
-
- public class Surname : AttributeTypeAndValue {
-
- public Surname () : base ("2.5.4.4", 32768)
- {
- }
- }
-
- public class GivenName : AttributeTypeAndValue {
-
- public GivenName () : base ("2.5.4.42", 16)
- {
- }
- }
-
- public class Initial : AttributeTypeAndValue {
-
- public Initial () : base ("2.5.4.43", 5)
- {
- }
- }
-
- }
-
- /* From RFC3280
- * -- specifications of Upper Bounds MUST be regarded as mandatory
- * -- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter
- *
- * -- Upper Bounds
- *
- * ub-name INTEGER ::= 32768
- * ub-common-name INTEGER ::= 64
- * ub-locality-name INTEGER ::= 128
- * ub-state-name INTEGER ::= 128
- * ub-organization-name INTEGER ::= 64
- * ub-organizational-unit-name INTEGER ::= 64
- * ub-title INTEGER ::= 64
- * ub-serial-number INTEGER ::= 64
- * ub-match INTEGER ::= 128
- * ub-emailaddress-length INTEGER ::= 128
- * ub-common-name-length INTEGER ::= 64
- * ub-country-name-alpha-length INTEGER ::= 2
- * ub-country-name-numeric-length INTEGER ::= 3
- * ub-domain-defined-attributes INTEGER ::= 4
- * ub-domain-defined-attribute-type-length INTEGER ::= 8
- * ub-domain-defined-attribute-value-length INTEGER ::= 128
- * ub-domain-name-length INTEGER ::= 16
- * ub-extension-attributes INTEGER ::= 256
- * ub-e163-4-number-length INTEGER ::= 15
- * ub-e163-4-sub-address-length INTEGER ::= 40
- * ub-generation-qualifier-length INTEGER ::= 3
- * ub-given-name-length INTEGER ::= 16
- * ub-initials-length INTEGER ::= 5
- * ub-integer-options INTEGER ::= 256
- * ub-numeric-user-id-length INTEGER ::= 32
- * ub-organization-name-length INTEGER ::= 64
- * ub-organizational-unit-name-length INTEGER ::= 32
- * ub-organizational-units INTEGER ::= 4
- * ub-pds-name-length INTEGER ::= 16
- * ub-pds-parameter-length INTEGER ::= 30
- * ub-pds-physical-address-lines INTEGER ::= 6
- * ub-postal-code-length INTEGER ::= 16
- * ub-pseudonym INTEGER ::= 128
- * ub-surname-length INTEGER ::= 40
- * ub-terminal-id-length INTEGER ::= 24
- * ub-unformatted-address-length INTEGER ::= 180
- * ub-x121-address-length INTEGER ::= 16
- *
- * -- Note - upper bounds on string types, such as TeletexString, are
- * -- measured in characters. Excepting PrintableString or IA5String, a
- * -- significantly greater number of octets will be required to hold
- * -- such a value. As a minimum, 16 octets, or twice the specified
- * -- upper bound, whichever is the larger, should be allowed for
- * -- TeletexString. For UTF8String or UniversalString at least four
- * -- times the upper bound should be allowed.
- */
-}
+++ /dev/null
-//
-// ASN1.cs: Abstract Syntax Notation 1 - micro-parser and generator
-//
-// Authors:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Jesper Pedersen <jep@itplus.dk>
-//
-// (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-// (C) 2004 IT+ A/S (http://www.itplus.dk)
-//
-// 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.Collections;
-using System.IO;
-using System.Text;
-
-namespace Mono.Security {
-
- // References:
- // a. ITU ASN.1 standards (free download)
- // http://www.itu.int/ITU-T/studygroups/com17/languages/
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- class ASN1 {
-
- private byte m_nTag;
- private byte[] m_aValue;
- private ArrayList elist;
-
- public ASN1 () : this (0x00, null) {}
-
- public ASN1 (byte tag) : this (tag, null) {}
-
- public ASN1 (byte tag, byte[] data)
- {
- m_nTag = tag;
- m_aValue = data;
- }
-
- public ASN1 (byte[] data)
- {
- m_nTag = data [0];
-
- int nLenLength = 0;
- int nLength = data [1];
-
- if (nLength > 0x80) {
- // composed length
- nLenLength = nLength - 0x80;
- nLength = 0;
- for (int i = 0; i < nLenLength; i++) {
- nLength *= 256;
- nLength += data [i + 2];
- }
- }
- else if (nLength == 0x80) {
- // undefined length encoding
- throw new NotSupportedException ("Undefined length encoding.");
- }
-
- m_aValue = new byte [nLength];
- Buffer.BlockCopy (data, (2 + nLenLength), m_aValue, 0, nLength);
-
- if ((m_nTag & 0x20) == 0x20) {
- int nStart = (2 + nLenLength);
- Decode (data, ref nStart, data.Length);
- }
- }
-
- public int Count {
- get {
- if (elist == null)
- return 0;
- return elist.Count;
- }
- }
-
- public byte Tag {
- get { return m_nTag; }
- }
-
- public int Length {
- get {
- if (m_aValue != null)
- return m_aValue.Length;
- else
- return 0;
- }
- }
-
- public byte[] Value {
- get {
- if (m_aValue == null)
- GetBytes ();
- return (byte[]) m_aValue.Clone ();
- }
- set {
- if (value != null)
- m_aValue = (byte[]) value.Clone ();
- }
- }
-
- private bool CompareArray (byte[] array1, byte[] array2)
- {
- bool bResult = (array1.Length == array2.Length);
- if (bResult) {
- for (int i = 0; i < array1.Length; i++) {
- if (array1[i] != array2[i])
- return false;
- }
- }
- return bResult;
- }
-
- public bool Equals (byte[] asn1)
- {
- return CompareArray (this.GetBytes (), asn1);
- }
-
- public bool CompareValue (byte[] value)
- {
- return CompareArray (m_aValue, value);
- }
-
- public ASN1 Add (ASN1 asn1)
- {
- if (asn1 != null) {
- if (elist == null)
- elist = new ArrayList ();
- elist.Add (asn1);
- }
- return asn1;
- }
-
- public virtual byte[] GetBytes ()
- {
- byte[] val = null;
-
- if (Count > 0) {
- int esize = 0;
- ArrayList al = new ArrayList ();
- foreach (ASN1 a in elist) {
- byte[] item = a.GetBytes ();
- al.Add (item);
- esize += item.Length;
- }
- val = new byte [esize];
- int pos = 0;
- for (int i=0; i < elist.Count; i++) {
- byte[] item = (byte[]) al[i];
- Buffer.BlockCopy (item, 0, val, pos, item.Length);
- pos += item.Length;
- }
- } else if (m_aValue != null) {
- val = m_aValue;
- }
-
- byte[] der;
- int nLengthLen = 0;
-
- if (val != null) {
- int nLength = val.Length;
- // special for length > 127
- if (nLength > 127) {
- if (nLength <= Byte.MaxValue) {
- der = new byte [3 + nLength];
- Buffer.BlockCopy (val, 0, der, 3, nLength);
- nLengthLen = 0x81;
- der[2] = (byte)(nLength);
- }
- else if (nLength <= UInt16.MaxValue) {
- der = new byte [4 + nLength];
- Buffer.BlockCopy (val, 0, der, 4, nLength);
- nLengthLen = 0x82;
- der[2] = (byte)(nLength >> 8);
- der[3] = (byte)(nLength);
- }
- else if (nLength <= 0xFFFFFF) {
- // 24 bits
- der = new byte [5 + nLength];
- Buffer.BlockCopy (val, 0, der, 5, nLength);
- nLengthLen = 0x83;
- der [2] = (byte)(nLength >> 16);
- der [3] = (byte)(nLength >> 8);
- der [4] = (byte)(nLength);
- }
- else {
- // max (Length is an integer) 32 bits
- der = new byte [6 + nLength];
- Buffer.BlockCopy (val, 0, der, 6, nLength);
- nLengthLen = 0x84;
- der [2] = (byte)(nLength >> 24);
- der [3] = (byte)(nLength >> 16);
- der [4] = (byte)(nLength >> 8);
- der [5] = (byte)(nLength);
- }
- }
- else {
- // basic case (no encoding)
- der = new byte [2 + nLength];
- Buffer.BlockCopy (val, 0, der, 2, nLength);
- nLengthLen = nLength;
- }
- if (m_aValue == null)
- m_aValue = val;
- }
- else
- der = new byte[2];
-
- der[0] = m_nTag;
- der[1] = (byte)nLengthLen;
-
- return der;
- }
-
- // Note: Recursive
- protected void Decode (byte[] asn1, ref int anPos, int anLength)
- {
- byte nTag;
- int nLength;
- byte[] aValue;
-
- // minimum is 2 bytes (tag + length of 0)
- while (anPos < anLength - 1) {
- DecodeTLV (asn1, ref anPos, out nTag, out nLength, out aValue);
- // sometimes we get trailing 0
- if (nTag == 0)
- continue;
-
- ASN1 elm = Add (new ASN1 (nTag, aValue));
-
- if ((nTag & 0x20) == 0x20) {
- int nConstructedPos = anPos;
- elm.Decode (asn1, ref nConstructedPos, nConstructedPos + nLength);
- }
- anPos += nLength; // value length
- }
- }
-
- // TLV : Tag - Length - Value
- protected void DecodeTLV (byte[] asn1, ref int pos, out byte tag, out int length, out byte[] content)
- {
- tag = asn1 [pos++];
- length = asn1 [pos++];
-
- // special case where L contains the Length of the Length + 0x80
- if ((length & 0x80) == 0x80) {
- int nLengthLen = length & 0x7F;
- length = 0;
- for (int i = 0; i < nLengthLen; i++)
- length = length * 256 + asn1 [pos++];
- }
-
- content = new byte [length];
- Buffer.BlockCopy (asn1, pos, content, 0, length);
- }
-
- public ASN1 this [int index] {
- get {
- try {
- if ((elist == null) || (index >= elist.Count))
- return null;
- return (ASN1) elist [index];
- }
- catch (ArgumentOutOfRangeException) {
- return null;
- }
- }
- }
-
- public ASN1 Element (int index, byte anTag)
- {
- try {
- if ((elist == null) || (index >= elist.Count))
- return null;
-
- ASN1 elm = (ASN1) elist [index];
- if (elm.Tag == anTag)
- return elm;
- else
- return null;
- }
- catch (ArgumentOutOfRangeException) {
- return null;
- }
- }
-
- public override string ToString()
- {
- StringBuilder hexLine = new StringBuilder ();
-
- // Add tag
- hexLine.AppendFormat ("Tag: {0} {1}", m_nTag.ToString ("X2"), Environment.NewLine);
-
- // Add length
- hexLine.AppendFormat ("Length: {0} {1}", Value.Length, Environment.NewLine);
-
- // Add value
- hexLine.Append ("Value: ");
- hexLine.Append (Environment.NewLine);
- for (int i = 0; i < Value.Length; i++) {
- hexLine.AppendFormat ("{0} ", Value [i].ToString ("X2"));
- if ((i+1) % 16 == 0)
- hexLine.AppendFormat (Environment.NewLine);
- }
- return hexLine.ToString ();
- }
-
- public void SaveToFile (string filename)
- {
- if (filename == null)
- throw new ArgumentNullException ("filename");
-
- using (FileStream fs = File.Create (filename)) {
- byte[] data = GetBytes ();
- fs.Write (data, 0, data.Length);
- }
- }
- }
-}
+++ /dev/null
-//
-// ASN1Convert.cs: Abstract Syntax Notation 1 convertion routines
-//
-// Authors:
-// Sebastien Pouliot <sebastien@ximian.com>
-// Jesper Pedersen <jep@itplus.dk>
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 IT+ A/S (http://www.itplus.dk)
-// Copyright (C) 2004-2007 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.Collections;
-using System.Globalization;
-using System.Security.Cryptography;
-using System.Text;
-
-namespace Mono.Security {
-
- // References:
- // a. ITU ASN.1 standards (free download)
- // http://www.itu.int/ITU-T/studygroups/com17/languages/
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- static class ASN1Convert {
- // RFC3280, section 4.2.1.5
- // CAs conforming to this profile MUST always encode certificate
- // validity dates through the year 2049 as UTCTime; certificate validity
- // dates in 2050 or later MUST be encoded as GeneralizedTime.
-
- // Under 1.x this API requires a Local datetime to be provided
- // Under 2.0 it will also accept a Utc datetime
- static public ASN1 FromDateTime (DateTime dt)
- {
- if (dt.Year < 2050) {
- // UTCTIME
- return new ASN1 (0x17, Encoding.ASCII.GetBytes (
- dt.ToUniversalTime ().ToString ("yyMMddHHmmss",
- CultureInfo.InvariantCulture) + "Z"));
- }
- else {
- // GENERALIZEDTIME
- return new ASN1 (0x18, Encoding.ASCII.GetBytes (
- dt.ToUniversalTime ().ToString ("yyyyMMddHHmmss",
- CultureInfo.InvariantCulture) + "Z"));
- }
- }
-
- static public ASN1 FromInt32 (Int32 value)
- {
- byte[] integer = BitConverterLE.GetBytes (value);
- Array.Reverse (integer);
- int x = 0;
- while ((x < integer.Length) && (integer [x] == 0x00))
- x++;
- ASN1 asn1 = new ASN1 (0x02);
- switch (x) {
- case 0:
- asn1.Value = integer;
- break;
- case 4:
- asn1.Value = new byte [1];
- break;
- default:
- byte[] smallerInt = new byte [4 - x];
- Buffer.BlockCopy (integer, x, smallerInt, 0, smallerInt.Length);
- asn1.Value = smallerInt;
- break;
- }
- return asn1;
- }
-
- static public ASN1 FromOid (string oid)
- {
- if (oid == null)
- throw new ArgumentNullException ("oid");
-
- return new ASN1 (CryptoConfig.EncodeOID (oid));
- }
-
- static public ASN1 FromUnsignedBigInteger (byte[] big)
- {
- if (big == null)
- throw new ArgumentNullException ("big");
-
- // check for numbers that could be interpreted as negative (first bit)
- if (big [0] >= 0x80) {
- // in thie cas we add a new, empty, byte (position 0) so we're
- // sure this will always be interpreted an unsigned integer.
- // However we can't feed it into RSAParameters or DSAParameters
- int length = big.Length + 1;
- byte[] uinteger = new byte [length];
- Buffer.BlockCopy (big, 0, uinteger, 1, length - 1);
- big = uinteger;
- }
- return new ASN1 (0x02, big);
- }
-
- static public int ToInt32 (ASN1 asn1)
- {
- if (asn1 == null)
- throw new ArgumentNullException ("asn1");
- if (asn1.Tag != 0x02)
- throw new FormatException ("Only integer can be converted");
-
- int x = 0;
- for (int i=0; i < asn1.Value.Length; i++)
- x = (x << 8) + asn1.Value [i];
- return x;
- }
-
- // Convert a binary encoded OID to human readable string representation of
- // an OID (IETF style). Based on DUMPASN1.C from Peter Gutmann.
- static public string ToOid (ASN1 asn1)
- {
- if (asn1 == null)
- throw new ArgumentNullException ("asn1");
-
- byte[] aOID = asn1.Value;
- StringBuilder sb = new StringBuilder ();
- // Pick apart the OID
- byte x = (byte) (aOID[0] / 40);
- byte y = (byte) (aOID[0] % 40);
- if (x > 2) {
- // Handle special case for large y if x = 2
- y += (byte) ((x - 2) * 40);
- x = 2;
- }
- sb.Append (x.ToString (CultureInfo.InvariantCulture));
- sb.Append (".");
- sb.Append (y.ToString (CultureInfo.InvariantCulture));
- ulong val = 0;
- for (x = 1; x < aOID.Length; x++) {
- val = ((val << 7) | ((byte) (aOID [x] & 0x7F)));
- if ( !((aOID [x] & 0x80) == 0x80)) {
- sb.Append (".");
- sb.Append (val.ToString (CultureInfo.InvariantCulture));
- val = 0;
- }
- }
- return sb.ToString ();
- }
-
- static public DateTime ToDateTime (ASN1 time)
- {
- if (time == null)
- throw new ArgumentNullException ("time");
-
- string t = Encoding.ASCII.GetString (time.Value);
- // to support both UTCTime and GeneralizedTime (and not so common format)
- string mask = null;
- int year;
- switch (t.Length) {
- case 11:
- // illegal format, still it's supported for compatibility
- mask = "yyMMddHHmmZ";
- break;
- case 13:
- // RFC3280: 4.1.2.5.1 UTCTime
- year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);
- // Where YY is greater than or equal to 50, the
- // year SHALL be interpreted as 19YY; and
- // Where YY is less than 50, the year SHALL be
- // interpreted as 20YY.
- if (year >= 50)
- t = "19" + t;
- else
- t = "20" + t;
- mask = "yyyyMMddHHmmssZ";
- break;
- case 15:
- mask = "yyyyMMddHHmmssZ"; // GeneralizedTime
- break;
- case 17:
- // another illegal format (990630000000+1000), again supported for compatibility
- year = Convert.ToInt16 (t.Substring (0, 2), CultureInfo.InvariantCulture);
- string century = (year >= 50) ? "19" : "20";
- // ASN.1 (see ITU X.680 section 43.3) deals with offset differently than .NET
- char sign = (t[12] == '+') ? '-' : '+';
- t = String.Format ("{0}{1}{2}{3}{4}:{5}{6}", century, t.Substring (0, 12), sign,
- t[13], t[14], t[15], t[16]);
- mask = "yyyyMMddHHmmsszzz";
- break;
- }
- return DateTime.ParseExact (t, mask, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal);
- }
- }
-}
+++ /dev/null
-//
-// Mono.Security.BitConverterLE.cs
-// Like System.BitConverter but always little endian
-//
-// Author:
-// Bernie Solomon
-//
-
-//
-// 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;
-
-namespace Mono.Security
-{
- internal sealed class BitConverterLE
- {
- private BitConverterLE ()
- {
- }
-
- unsafe private static byte[] GetUShortBytes (byte *bytes)
- {
- if (BitConverter.IsLittleEndian)
- return new byte [] { bytes [0], bytes [1] };
- else
- return new byte [] { bytes [1], bytes [0] };
- }
-
- unsafe private static byte[] GetUIntBytes (byte *bytes)
- {
- if (BitConverter.IsLittleEndian)
- return new byte [] { bytes [0], bytes [1], bytes [2], bytes [3] };
- else
- return new byte [] { bytes [3], bytes [2], bytes [1], bytes [0] };
- }
-
- unsafe private static byte[] GetULongBytes (byte *bytes)
- {
- if (BitConverter.IsLittleEndian)
- return new byte [] { bytes [0], bytes [1], bytes [2], bytes [3],
- bytes [4], bytes [5], bytes [6], bytes [7] };
- else
- return new byte [] { bytes [7], bytes [6], bytes [5], bytes [4],
- bytes [3], bytes [2], bytes [1], bytes [0] };
- }
-
- unsafe internal static byte[] GetBytes (bool value)
- {
- return new byte [] { value ? (byte)1 : (byte)0 };
- }
-
- unsafe internal static byte[] GetBytes (char value)
- {
- return GetUShortBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (short value)
- {
- return GetUShortBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (int value)
- {
- return GetUIntBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (long value)
- {
- return GetULongBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (ushort value)
- {
- return GetUShortBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (uint value)
- {
- return GetUIntBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (ulong value)
- {
- return GetULongBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (float value)
- {
- return GetUIntBytes ((byte *) &value);
- }
-
- unsafe internal static byte[] GetBytes (double value)
- {
- return GetULongBytes ((byte *) &value);
- }
-
- unsafe private static void UShortFromBytes (byte *dst, byte[] src, int startIndex)
- {
- if (BitConverter.IsLittleEndian) {
- dst [0] = src [startIndex];
- dst [1] = src [startIndex + 1];
- } else {
- dst [0] = src [startIndex + 1];
- dst [1] = src [startIndex];
- }
- }
-
- unsafe private static void UIntFromBytes (byte *dst, byte[] src, int startIndex)
- {
- if (BitConverter.IsLittleEndian) {
- dst [0] = src [startIndex];
- dst [1] = src [startIndex + 1];
- dst [2] = src [startIndex + 2];
- dst [3] = src [startIndex + 3];
- } else {
- dst [0] = src [startIndex + 3];
- dst [1] = src [startIndex + 2];
- dst [2] = src [startIndex + 1];
- dst [3] = src [startIndex];
- }
- }
-
- unsafe private static void ULongFromBytes (byte *dst, byte[] src, int startIndex)
- {
- if (BitConverter.IsLittleEndian) {
- for (int i = 0; i < 8; ++i)
- dst [i] = src [startIndex + i];
- } else {
- for (int i = 0; i < 8; ++i)
- dst [i] = src [startIndex + (7 - i)];
- }
- }
-
- unsafe internal static bool ToBoolean (byte[] value, int startIndex)
- {
- return value [startIndex] != 0;
- }
-
- unsafe internal static char ToChar (byte[] value, int startIndex)
- {
- char ret;
-
- UShortFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static short ToInt16 (byte[] value, int startIndex)
- {
- short ret;
-
- UShortFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static int ToInt32 (byte[] value, int startIndex)
- {
- int ret;
-
- UIntFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static long ToInt64 (byte[] value, int startIndex)
- {
- long ret;
-
- ULongFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static ushort ToUInt16 (byte[] value, int startIndex)
- {
- ushort ret;
-
- UShortFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static uint ToUInt32 (byte[] value, int startIndex)
- {
- uint ret;
-
- UIntFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static ulong ToUInt64 (byte[] value, int startIndex)
- {
- ulong ret;
-
- ULongFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static float ToSingle (byte[] value, int startIndex)
- {
- float ret;
-
- UIntFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
-
- unsafe internal static double ToDouble (byte[] value, int startIndex)
- {
- double ret;
-
- ULongFromBytes ((byte *) &ret, value, startIndex);
-
- return ret;
- }
- }
-}
+++ /dev/null
-2010-05-10 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Keep it public for Moonlight. Other types in other
- assemblies needs it and the linker will eventually internalize
- everything.
-
-2010-03-24 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: Specify CultureInfo.InvariantCulture (instead of
- null) to avoid crash on Windows. Patch by Yoni Shalom.
-
-2010-03-16 Jb Evain <jbevain@novell.com>
-
- * StrongName.cs: use MOONLIGHT symbol to disambiguate
- MonoTouch and Moonlight code.
-
-2009-09-22 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Moonlight NET_2_1 cannot depend on machine.config
- * StrongNameManager_2_1.cs: Minimal version for NET_2_1
-
-2009-04-30 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Adapt to work with only RSAManaged when built
- for NET_2_1, i.e. remove use of RSACryptoServiceProvider
-
-2008-09-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Use File.Create instead of OpenWrite to make sure nothing
- else if left at the end of the file.
-
-2008-04-25 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: New test cases to verify signatures from streams.
- Patch from Dave Hillier <daveh@lindenlab.com>
-
-2008-03-10 Stephane Delcroix <sdelcroix@novell.com>
-
- * Uri.cs: port the changes I did in System.Uri in r97844.
-
-2007-03-11 Zoltan Varga <vargaz@gmail.com>
-
- * ASN1Convert.cs: Fix a warning.
-
-2007-02-12 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: Add support for decoding ASN.1 dates with an UTC
- offset (e.g. 990630000000+1000) as some certificates use this format.
-
-2007-01-05 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: Added comment to FromDateTime to specify that, under
- 1.x, the DateTime must be a local (not UTC) date time. Fixed ToDateTime
- to return a DateTimeKind.Utc DateTime under 2.0.
-
-2006-08-17 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Fix the (very unlikely) case where an MD5 public key
- token is requested (part of the spec, never seen in the wild).
-
-2006-06-14 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Switch condition not to use the cached data if there is a
- collection being used. Skip extra 0 at the end of the byte[] buffer.
-
-2006-01-04 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: Fix convertion of integer 0 to ASN.1.
-
-2005-11-07 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Synch with Mono.Security.dll to get support for
- strongname keypairs different from 1024 bits.
-
-2005-10-06 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: Better handle big integer than cannot be interpreted
- as a negative number (don't extend). Fix bug #75778.
-
-2004-12-15 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Fixed warning for unused variable.
-
-2004-10-29 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Throw an NotSupportedException when "undefined length
- encoding" is used (#68903 but it's not a fix ;-). Fixed GetBytes to
- encode structures bigger than 64k (fix #68907). Simplified ToString
- and added Length to help debugging.
- * PKCS7.cs: Added a flag to avoid resigning a structure (which was
- duplicating some attributes).
-
-2004-09-16 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Fixed warning (l4) for unused variable.
- * PKCS7.cs: Fixed warning (l4) for unused variable.
- * Uri.cs: Fixed warning (l4) for unused variables. Remove sealed from
- class to reduce number of warnings.
-
-2004-08-30 Sebastien Pouliot <sebastien@ximian.com>
-
- * Uri.cs: Copied from System.dll assembly and started adaptation for
- it's reuse inside the security classes (CAS).
-
-2004-06-08 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Added corlib specific code to load configuration
- from machine.config to allow public key token remapping to work
- with (for example) gacutil.
- * StrongNameManager.cs: Now load configuration from machine.config.
-
-2004-05-19 Sebastien Pouliot <sebastien@ximian.com>
-
- * PKCS7.cs: In sync with Mono.Security.dll version.
-
-2004-05-18 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1Convert.cs: In sync with Mono.Security.dll version.
- * StrongName.cs: In sync with Mono.Security.dll version.
-
-2004-05-03 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Fixed NullReferenceException in xmldsig standalone tests.
-
-2004-04-28 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: In sync with Mono.Security.dll version.
- * ASN1Convert.cs: In sync with Mono.Security.dll version.
- * PKCS7.cs: In sync with Mono.Security.dll version.
- * StrongName.cs: In sync with Mono.Security.dll version.
-
-2004-04-20 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Added SaveToFile for easier debugging. Patch from
- Jesper Pedersen.
- * StrongName.cs: Removed compilation warning (unused variable).
-
-2004-04-08 Bernie Solomon <bernard@ugsolutions.com>
-
- * BitConverterLE.cs: added which always does
- little endian conversion
- * StrongName.cs: Use BitConverterLE
- * ASN1Convert.cs: Use BitConverterLE
-
-2004-04-06 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Added support for ECMA "key" to StringName(byte[])
- constructor.
-
-2004-03-31 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Update to include new static method that can be
- called from the runtime to validate strongname signatures.
- Refactored the existing class to reduce code duplication.
- * StrongNameManager.cs: New. This class keeps the configuration
- required to map a public key token to an alternative public key
- (e.g. ECMA public key token -> Mono public key) and to skip
- strongname validation for specific assemblies/token/users.
-
-2004-03-24 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Added CanSign property for AssemblyBuilder. Current
- Fx design requires an exception to know if the private key is present
- in an RSA instance. In some case (inside corlib) we can do without...
-
-2004-03-23 Sebastien Pouliot <sebastien@ximian.com>
-
- * StrongName.cs: Added exceptions for null or invalid keys.
-
-2004-03-17 Sebastien Pouliot <sebastien@ximian.com>
-
- * ASN1.cs: Class synched with Mono.Security.
- * ASN1Convert.cs: Class synched with Mono.Security.
-
-2003-10-18 Sebastien Pouliot <spouliot@videotron.ca>
-
- * StrongName.cs: Added from Mono.Security assembly for StrongName
- support in AssemblyBuilder.
-
-2003-10-12 Sebastien Pouliot <spouliot@videotron.ca>
-
- * PKCS7.cs: Added from Mono.Security assembly for Authenticode
- support in X509Certificate.CreateFromSignedFile
-
-2003-03-15 Sebastien Pouliot <spouliot@videotron.ca>
-
- * ASN1.cs: Improved version.
- * ASN1Convert.cs: New. Helper class to convert between .NET
- types and ASN.1 structures.
-
-2003-02-08 Sebastien Pouliot <spouliot@videotron.ca>
-
- * ASN1.cs: Renamed namespace to match new location.
-
+++ /dev/null
-//
-// PKCS7.cs: PKCS #7 - Cryptographic Message Syntax Standard
-// http://www.rsasecurity.com/rsalabs/pkcs/pkcs-7/index.html
-//
-// Author:
-// Sebastien Pouliot <sebastien@ximian.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.Collections;
-using System.Security.Cryptography;
-
-using Mono.Security.X509;
-
-namespace Mono.Security {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class PKCS7 {
-
- public class Oid {
- // pkcs 1
- public const string rsaEncryption = "1.2.840.113549.1.1.1";
- // pkcs 7
- public const string data = "1.2.840.113549.1.7.1";
- public const string signedData = "1.2.840.113549.1.7.2";
- public const string envelopedData = "1.2.840.113549.1.7.3";
- public const string signedAndEnvelopedData = "1.2.840.113549.1.7.4";
- public const string digestedData = "1.2.840.113549.1.7.5";
- public const string encryptedData = "1.2.840.113549.1.7.6";
- // pkcs 9
- public const string contentType = "1.2.840.113549.1.9.3";
- public const string messageDigest = "1.2.840.113549.1.9.4";
- public const string signingTime = "1.2.840.113549.1.9.5";
- public const string countersignature = "1.2.840.113549.1.9.6";
-
- public Oid ()
- {
- }
- }
-
- private PKCS7 ()
- {
- }
-
- static public ASN1 Attribute (string oid, ASN1 value)
- {
- ASN1 attr = new ASN1 (0x30);
- attr.Add (ASN1Convert.FromOid (oid));
- ASN1 aset = attr.Add (new ASN1 (0x31));
- aset.Add (value);
- return attr;
- }
-
- static public ASN1 AlgorithmIdentifier (string oid)
- {
- ASN1 ai = new ASN1 (0x30);
- ai.Add (ASN1Convert.FromOid (oid));
- ai.Add (new ASN1 (0x05)); // NULL
- return ai;
- }
-
- static public ASN1 AlgorithmIdentifier (string oid, ASN1 parameters)
- {
- ASN1 ai = new ASN1 (0x30);
- ai.Add (ASN1Convert.FromOid (oid));
- ai.Add (parameters);
- return ai;
- }
-
- /*
- * IssuerAndSerialNumber ::= SEQUENCE {
- * issuer Name,
- * serialNumber CertificateSerialNumber
- * }
- */
- static public ASN1 IssuerAndSerialNumber (X509Certificate x509)
- {
- ASN1 issuer = null;
- ASN1 serial = null;
- ASN1 cert = new ASN1 (x509.RawData);
- int tbs = 0;
- bool flag = false;
- while (tbs < cert[0].Count) {
- ASN1 e = cert[0][tbs++];
- if (e.Tag == 0x02)
- serial = e;
- else if (e.Tag == 0x30) {
- if (flag) {
- issuer = e;
- break;
- }
- flag = true;
- }
- }
- ASN1 iasn = new ASN1 (0x30);
- iasn.Add (issuer);
- iasn.Add (serial);
- return iasn;
- }
-
- /*
- * ContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
- * }
- * ContentType ::= OBJECT IDENTIFIER
- */
- public class ContentInfo {
-
- private string contentType;
- private ASN1 content;
-
- public ContentInfo ()
- {
- content = new ASN1 (0xA0);
- }
-
- public ContentInfo (string oid) : this ()
- {
- contentType = oid;
- }
-
- public ContentInfo (byte[] data)
- : this (new ASN1 (data)) {}
-
- public ContentInfo (ASN1 asn1)
- {
- // SEQUENCE with 1 or 2 elements
- if ((asn1.Tag != 0x30) || ((asn1.Count < 1) && (asn1.Count > 2)))
- throw new ArgumentException ("Invalid ASN1");
- if (asn1[0].Tag != 0x06)
- throw new ArgumentException ("Invalid contentType");
- contentType = ASN1Convert.ToOid (asn1[0]);
- if (asn1.Count > 1) {
- if (asn1[1].Tag != 0xA0)
- throw new ArgumentException ("Invalid content");
- content = asn1[1];
- }
- }
-
- public ASN1 ASN1 {
- get { return GetASN1(); }
- }
-
- public ASN1 Content {
- get { return content; }
- set { content = value; }
- }
-
- public string ContentType {
- get { return contentType; }
- set { contentType = value; }
- }
-
- internal ASN1 GetASN1 ()
- {
- // ContentInfo ::= SEQUENCE {
- ASN1 contentInfo = new ASN1 (0x30);
- // contentType ContentType, -> ContentType ::= OBJECT IDENTIFIER
- contentInfo.Add (ASN1Convert.FromOid (contentType));
- // content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL
- if ((content != null) && (content.Count > 0))
- contentInfo.Add (content);
- return contentInfo;
- }
-
- public byte[] GetBytes ()
- {
- return GetASN1 ().GetBytes ();
- }
- }
-
- /*
- * EncryptedData ::= SEQUENCE {
- * version INTEGER {edVer0(0)} (edVer0),
- * encryptedContentInfo EncryptedContentInfo
- * }
- */
- public class EncryptedData {
- private byte _version;
- private ContentInfo _content;
- private ContentInfo _encryptionAlgorithm;
- private byte[] _encrypted;
-
- public EncryptedData ()
- {
- _version = 0;
- }
-
- public EncryptedData (byte[] data)
- : this (new ASN1 (data))
- {
- }
-
- public EncryptedData (ASN1 asn1) : this ()
- {
- if ((asn1.Tag != 0x30) || (asn1.Count < 2))
- throw new ArgumentException ("Invalid EncryptedData");
-
- if (asn1 [0].Tag != 0x02)
- throw new ArgumentException ("Invalid version");
- _version = asn1 [0].Value [0];
-
- ASN1 encryptedContentInfo = asn1 [1];
- if (encryptedContentInfo.Tag != 0x30)
- throw new ArgumentException ("missing EncryptedContentInfo");
-
- ASN1 contentType = encryptedContentInfo [0];
- if (contentType.Tag != 0x06)
- throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
- _content = new ContentInfo (ASN1Convert.ToOid (contentType));
-
- ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
- if (contentEncryptionAlgorithm.Tag != 0x30)
- throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
- _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
- _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
-
- ASN1 encryptedContent = encryptedContentInfo [2];
- if (encryptedContent.Tag != 0x80)
- throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
- _encrypted = encryptedContent.Value;
- }
-
- public ASN1 ASN1 {
- get { return GetASN1(); }
- }
-
- public ContentInfo ContentInfo {
- get { return _content; }
- }
-
- public ContentInfo EncryptionAlgorithm {
- get { return _encryptionAlgorithm; }
- }
-
- public byte[] EncryptedContent {
- get {
- if (_encrypted == null)
- return null;
- return (byte[]) _encrypted.Clone ();
- }
- }
-
- public byte Version {
- get { return _version; }
- set { _version = value; }
- }
-
- // methods
-
- internal ASN1 GetASN1 ()
- {
- return null;
- }
-
- public byte[] GetBytes ()
- {
- return GetASN1 ().GetBytes ();
- }
- }
-
- /*
- * EnvelopedData ::= SEQUENCE {
- * version Version,
- * recipientInfos RecipientInfos,
- * encryptedContentInfo EncryptedContentInfo
- * }
- *
- * RecipientInfos ::= SET OF RecipientInfo
- *
- * EncryptedContentInfo ::= SEQUENCE {
- * contentType ContentType,
- * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
- * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL
- * }
- *
- * EncryptedContent ::= OCTET STRING
- *
- */
- public class EnvelopedData {
- private byte _version;
- private ContentInfo _content;
- private ContentInfo _encryptionAlgorithm;
- private ArrayList _recipientInfos;
- private byte[] _encrypted;
-
- public EnvelopedData ()
- {
- _version = 0;
- _content = new ContentInfo ();
- _encryptionAlgorithm = new ContentInfo ();
- _recipientInfos = new ArrayList ();
- }
-
- public EnvelopedData (byte[] data)
- : this (new ASN1 (data))
- {
- }
-
- public EnvelopedData (ASN1 asn1) : this ()
- {
- if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 3))
- throw new ArgumentException ("Invalid EnvelopedData");
-
- if (asn1[0][0].Tag != 0x02)
- throw new ArgumentException ("Invalid version");
- _version = asn1[0][0].Value[0];
-
- // recipientInfos
-
- ASN1 recipientInfos = asn1 [0][1];
- if (recipientInfos.Tag != 0x31)
- throw new ArgumentException ("missing RecipientInfos");
- for (int i=0; i < recipientInfos.Count; i++) {
- ASN1 recipientInfo = recipientInfos [i];
- _recipientInfos.Add (new RecipientInfo (recipientInfo));
- }
-
- ASN1 encryptedContentInfo = asn1[0][2];
- if (encryptedContentInfo.Tag != 0x30)
- throw new ArgumentException ("missing EncryptedContentInfo");
-
- ASN1 contentType = encryptedContentInfo [0];
- if (contentType.Tag != 0x06)
- throw new ArgumentException ("missing EncryptedContentInfo.ContentType");
- _content = new ContentInfo (ASN1Convert.ToOid (contentType));
-
- ASN1 contentEncryptionAlgorithm = encryptedContentInfo [1];
- if (contentEncryptionAlgorithm.Tag != 0x30)
- throw new ArgumentException ("missing EncryptedContentInfo.ContentEncryptionAlgorithmIdentifier");
- _encryptionAlgorithm = new ContentInfo (ASN1Convert.ToOid (contentEncryptionAlgorithm [0]));
- _encryptionAlgorithm.Content = contentEncryptionAlgorithm [1];
-
- ASN1 encryptedContent = encryptedContentInfo [2];
- if (encryptedContent.Tag != 0x80)
- throw new ArgumentException ("missing EncryptedContentInfo.EncryptedContent");
- _encrypted = encryptedContent.Value;
- }
-
- public ArrayList RecipientInfos {
- get { return _recipientInfos; }
- }
-
- public ASN1 ASN1 {
- get { return GetASN1(); }
- }
-
- public ContentInfo ContentInfo {
- get { return _content; }
- }
-
- public ContentInfo EncryptionAlgorithm {
- get { return _encryptionAlgorithm; }
- }
-
- public byte[] EncryptedContent {
- get {
- if (_encrypted == null)
- return null;
- return (byte[]) _encrypted.Clone ();
- }
- }
-
- public byte Version {
- get { return _version; }
- set { _version = value; }
- }
-
- internal ASN1 GetASN1 ()
- {
- // SignedData ::= SEQUENCE {
- ASN1 signedData = new ASN1 (0x30);
- // version Version -> Version ::= INTEGER
-/* byte[] ver = { _version };
- signedData.Add (new ASN1 (0x02, ver));
- // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
- ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
- if (hashAlgorithm != null) {
- string hashOid = CryptoConfig.MapNameToOid (hashAlgorithm);
- digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
- }
-
- // contentInfo ContentInfo,
- ASN1 ci = contentInfo.ASN1;
- signedData.Add (ci);
- if ((mda == null) && (hashAlgorithm != null)) {
- // automatically add the messageDigest authenticated attribute
- HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
- byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
- ASN1 md = new ASN1 (0x30);
- mda = Attribute (messageDigest, md.Add (new ASN1 (0x04, idcHash)));
- signerInfo.AuthenticatedAttributes.Add (mda);
- }
-
- // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
- if (certs.Count > 0) {
- ASN1 a0 = signedData.Add (new ASN1 (0xA0));
- foreach (X509Certificate x in certs)
- a0.Add (new ASN1 (x.RawData));
- }
- // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- if (crls.Count > 0) {
- ASN1 a1 = signedData.Add (new ASN1 (0xA1));
- foreach (byte[] crl in crls)
- a1.Add (new ASN1 (crl));
- }
- // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
- ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
- if (signerInfo.Key != null)
- signerInfos.Add (signerInfo.ASN1);*/
- return signedData;
- }
-
- public byte[] GetBytes () {
- return GetASN1 ().GetBytes ();
- }
- }
-
- /* RecipientInfo ::= SEQUENCE {
- * version Version,
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
- * encryptedKey EncryptedKey
- * }
- *
- * KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
- *
- * EncryptedKey ::= OCTET STRING
- */
- public class RecipientInfo {
-
- private int _version;
- private string _oid;
- private byte[] _key;
- private byte[] _ski;
- private string _issuer;
- private byte[] _serial;
-
- public RecipientInfo () {}
-
- public RecipientInfo (ASN1 data)
- {
- if (data.Tag != 0x30)
- throw new ArgumentException ("Invalid RecipientInfo");
-
- ASN1 version = data [0];
- if (version.Tag != 0x02)
- throw new ArgumentException ("missing Version");
- _version = version.Value [0];
-
- // issuerAndSerialNumber IssuerAndSerialNumber
- ASN1 subjectIdentifierType = data [1];
- if ((subjectIdentifierType.Tag == 0x80) && (_version == 3)) {
- _ski = subjectIdentifierType.Value;
- }
- else {
- _issuer = X501.ToString (subjectIdentifierType [0]);
- _serial = subjectIdentifierType [1].Value;
- }
-
- ASN1 keyEncryptionAlgorithm = data [2];
- _oid = ASN1Convert.ToOid (keyEncryptionAlgorithm [0]);
-
- ASN1 encryptedKey = data [3];
- _key = encryptedKey.Value;
- }
-
- public string Oid {
- get { return _oid; }
- }
-
- public byte[] Key {
- get {
- if (_key == null)
- return null;
- return (byte[]) _key.Clone ();
- }
- }
-
- public byte[] SubjectKeyIdentifier {
- get {
- if (_ski == null)
- return null;
- return (byte[]) _ski.Clone ();
- }
- }
-
- public string Issuer {
- get { return _issuer; }
- }
-
- public byte[] Serial {
- get {
- if (_serial == null)
- return null;
- return (byte[]) _serial.Clone ();
- }
- }
-
- public int Version {
- get { return _version; }
- }
- }
-
- /*
- * SignedData ::= SEQUENCE {
- * version Version,
- * digestAlgorithms DigestAlgorithmIdentifiers,
- * contentInfo ContentInfo,
- * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
- * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- * signerInfos SignerInfos
- * }
- */
- public class SignedData {
- private byte version;
- private string hashAlgorithm;
- private ContentInfo contentInfo;
- private X509CertificateCollection certs;
- private ArrayList crls;
- private SignerInfo signerInfo;
- private bool mda;
- private bool signed;
-
- public SignedData ()
- {
- version = 1;
- contentInfo = new ContentInfo ();
- certs = new X509CertificateCollection ();
- crls = new ArrayList ();
- signerInfo = new SignerInfo ();
- mda = true;
- signed = false;
- }
-
- public SignedData (byte[] data)
- : this (new ASN1 (data))
- {
- }
-
- public SignedData (ASN1 asn1)
- {
- if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 4))
- throw new ArgumentException ("Invalid SignedData");
-
- if (asn1[0][0].Tag != 0x02)
- throw new ArgumentException ("Invalid version");
- version = asn1[0][0].Value[0];
-
- contentInfo = new ContentInfo (asn1[0][2]);
-
- int n = 3;
- certs = new X509CertificateCollection ();
- if (asn1[0][n].Tag == 0xA0) {
- for (int i=0; i < asn1[0][n].Count; i++)
- certs.Add (new X509Certificate (asn1[0][n][i].GetBytes ()));
- n++;
- }
-
- crls = new ArrayList ();
- if (asn1[0][n].Tag == 0xA1) {
- for (int i=0; i < asn1[0][n].Count; i++)
- crls.Add (asn1[0][n][i].GetBytes ());
- n++;
- }
-
- if (asn1[0][n].Count > 0)
- signerInfo = new SignerInfo (asn1[0][n]);
- else
- signerInfo = new SignerInfo ();
-
- // Exchange hash algorithm Oid from SignerInfo
- if (signerInfo.HashName != null) {
- HashName = OidToName(signerInfo.HashName);
- }
-
- // Check if SignerInfo has authenticated attributes
- mda = (signerInfo.AuthenticatedAttributes.Count > 0);
- }
-
- public ASN1 ASN1 {
- get { return GetASN1(); }
- }
-
- public X509CertificateCollection Certificates {
- get { return certs; }
- }
-
- public ContentInfo ContentInfo {
- get { return contentInfo; }
- }
-
- public ArrayList Crls {
- get { return crls; }
- }
-
- public string HashName {
- get { return hashAlgorithm; }
- // todo add validation
- set {
- hashAlgorithm = value;
- signerInfo.HashName = value;
- }
- }
-
- public SignerInfo SignerInfo {
- get { return signerInfo; }
- }
-
- public byte Version {
- get { return version; }
- set { version = value; }
- }
-
- public bool UseAuthenticatedAttributes {
- get { return mda; }
- set { mda = value; }
- }
-
- public bool VerifySignature (AsymmetricAlgorithm aa)
- {
- if (aa == null) {
- return false;
- }
-
- RSAPKCS1SignatureDeformatter r = new RSAPKCS1SignatureDeformatter (aa);
- r.SetHashAlgorithm (hashAlgorithm);
- HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
-
- byte[] signature = signerInfo.Signature;
- byte[] hash = null;
-
- if (mda) {
- ASN1 asn = new ASN1 (0x31);
- foreach (ASN1 attr in signerInfo.AuthenticatedAttributes)
- asn.Add (attr);
-
- hash = ha.ComputeHash (asn.GetBytes ());
- } else {
- hash = ha.ComputeHash (contentInfo.Content[0].Value);
- }
-
- if (hash != null && signature != null) {
- return r.VerifySignature (hash, signature);
- }
- return false;
- }
-
- internal string OidToName (string oid)
- {
- switch (oid) {
- case "1.3.14.3.2.26" :
- return "SHA1";
- case "1.2.840.113549.2.2" :
- return "MD2";
- case "1.2.840.113549.2.5" :
- return "MD5";
- case "2.16.840.1.101.3.4.1" :
- return "SHA256";
- case "2.16.840.1.101.3.4.2" :
- return "SHA384";
- case "2.16.840.1.101.3.4.3" :
- return "SHA512";
- default :
- break;
- }
- // Unknown Oid
- return oid;
- }
-
- internal ASN1 GetASN1 ()
- {
- // SignedData ::= SEQUENCE {
- ASN1 signedData = new ASN1 (0x30);
- // version Version -> Version ::= INTEGER
- byte[] ver = { version };
- signedData.Add (new ASN1 (0x02, ver));
- // digestAlgorithms DigestAlgorithmIdentifiers -> DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
- ASN1 digestAlgorithms = signedData.Add (new ASN1 (0x31));
- if (hashAlgorithm != null) {
- string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
- digestAlgorithms.Add (AlgorithmIdentifier (hashOid));
- }
-
- // contentInfo ContentInfo,
- ASN1 ci = contentInfo.ASN1;
- signedData.Add (ci);
- if (!signed && (hashAlgorithm != null)) {
- if (mda) {
- // Use authenticated attributes for signature
-
- // Automatically add the contentType authenticated attribute
- ASN1 ctattr = Attribute (Oid.contentType, ci[0]);
- signerInfo.AuthenticatedAttributes.Add (ctattr);
-
- // Automatically add the messageDigest authenticated attribute
- HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
- byte[] idcHash = ha.ComputeHash (ci[1][0].Value);
- ASN1 md = new ASN1 (0x30);
- ASN1 mdattr = Attribute (Oid.messageDigest, md.Add (new ASN1 (0x04, idcHash)));
- signerInfo.AuthenticatedAttributes.Add (mdattr);
- } else {
- // Don't use authenticated attributes for signature -- signature is content
- RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (signerInfo.Key);
- r.SetHashAlgorithm (hashAlgorithm);
- HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
- byte[] sig = ha.ComputeHash (ci[1][0].Value);
- signerInfo.Signature = r.CreateSignature (sig);
- }
- signed = true;
- }
-
- // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
- if (certs.Count > 0) {
- ASN1 a0 = signedData.Add (new ASN1 (0xA0));
- foreach (X509Certificate x in certs)
- a0.Add (new ASN1 (x.RawData));
- }
- // crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
- if (crls.Count > 0) {
- ASN1 a1 = signedData.Add (new ASN1 (0xA1));
- foreach (byte[] crl in crls)
- a1.Add (new ASN1 (crl));
- }
- // signerInfos SignerInfos -> SignerInfos ::= SET OF SignerInfo
- ASN1 signerInfos = signedData.Add (new ASN1 (0x31));
- if (signerInfo.Key != null)
- signerInfos.Add (signerInfo.ASN1);
- return signedData;
- }
-
- public byte[] GetBytes ()
- {
- return GetASN1 ().GetBytes ();
- }
- }
-
- /*
- * SignerInfo ::= SEQUENCE {
- * version Version,
- * issuerAndSerialNumber IssuerAndSerialNumber,
- * digestAlgorithm DigestAlgorithmIdentifier,
- * authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
- * digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- * encryptedDigest EncryptedDigest,
- * unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
- * }
- *
- * For version == 3 issuerAndSerialNumber may be replaced by ...
- */
- public class SignerInfo {
-
- private byte version;
- private X509Certificate x509;
- private string hashAlgorithm;
- private AsymmetricAlgorithm key;
- private ArrayList authenticatedAttributes;
- private ArrayList unauthenticatedAttributes;
- private byte[] signature;
- private string issuer;
- private byte[] serial;
- private byte[] ski;
-
- public SignerInfo ()
- {
- version = 1;
- authenticatedAttributes = new ArrayList ();
- unauthenticatedAttributes = new ArrayList ();
- }
-
- public SignerInfo (byte[] data)
- : this (new ASN1 (data)) {}
-
- // TODO: INCOMPLETE
- public SignerInfo (ASN1 asn1) : this ()
- {
- if ((asn1[0].Tag != 0x30) || (asn1[0].Count < 5))
- throw new ArgumentException ("Invalid SignedData");
-
- // version Version
- if (asn1[0][0].Tag != 0x02)
- throw new ArgumentException ("Invalid version");
- version = asn1[0][0].Value[0];
-
- // issuerAndSerialNumber IssuerAndSerialNumber
- ASN1 subjectIdentifierType = asn1 [0][1];
- if ((subjectIdentifierType.Tag == 0x80) && (version == 3)) {
- ski = subjectIdentifierType.Value;
- }
- else {
- issuer = X501.ToString (subjectIdentifierType [0]);
- serial = subjectIdentifierType [1].Value;
- }
-
- // digestAlgorithm DigestAlgorithmIdentifier
- ASN1 digestAlgorithm = asn1 [0][2];
- hashAlgorithm = ASN1Convert.ToOid (digestAlgorithm [0]);
-
- // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL
- int n = 3;
- ASN1 authAttributes = asn1 [0][n];
- if (authAttributes.Tag == 0xA0) {
- n++;
- for (int i=0; i < authAttributes.Count; i++)
- authenticatedAttributes.Add (authAttributes [i]);
- }
-
- // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier
- n++;
- // ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
- // string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
-
- // encryptedDigest EncryptedDigest
- ASN1 encryptedDigest = asn1 [0][n++];
- if (encryptedDigest.Tag == 0x04)
- signature = encryptedDigest.Value;
-
- // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
- ASN1 unauthAttributes = asn1 [0][n];
- if ((unauthAttributes != null) && (unauthAttributes.Tag == 0xA1)) {
- for (int i=0; i < unauthAttributes.Count; i++)
- unauthenticatedAttributes.Add (unauthAttributes [i]);
- }
- }
-
- public string IssuerName {
- get { return issuer; }
- }
-
- public byte[] SerialNumber {
- get {
- if (serial == null)
- return null;
- return (byte[]) serial.Clone ();
- }
- }
-
- public byte[] SubjectKeyIdentifier {
- get {
- if (ski == null)
- return null;
- return (byte[]) ski.Clone ();
- }
- }
-
- public ASN1 ASN1 {
- get { return GetASN1(); }
- }
-
- public ArrayList AuthenticatedAttributes {
- get { return authenticatedAttributes; }
- }
-
- public X509Certificate Certificate {
- get { return x509; }
- set { x509 = value; }
- }
-
- public string HashName {
- get { return hashAlgorithm; }
- set { hashAlgorithm = value; }
- }
-
- public AsymmetricAlgorithm Key {
- get { return key; }
- set { key = value; }
- }
-
- public byte[] Signature {
- get {
- if (signature == null)
- return null;
- return (byte[]) signature.Clone ();
- }
-
- set {
- if (value != null) {
- signature = (byte[]) value.Clone ();
- }
- }
- }
-
- public ArrayList UnauthenticatedAttributes {
- get { return unauthenticatedAttributes; }
- }
-
- public byte Version {
- get { return version; }
- set { version = value; }
- }
-
- internal ASN1 GetASN1 ()
- {
- if ((key == null) || (hashAlgorithm == null))
- return null;
- byte[] ver = { version };
- ASN1 signerInfo = new ASN1 (0x30);
- // version Version -> Version ::= INTEGER
- signerInfo.Add (new ASN1 (0x02, ver));
- // issuerAndSerialNumber IssuerAndSerialNumber,
- signerInfo.Add (PKCS7.IssuerAndSerialNumber (x509));
- // digestAlgorithm DigestAlgorithmIdentifier,
- string hashOid = CryptoConfig.MapNameToOID (hashAlgorithm);
- signerInfo.Add (AlgorithmIdentifier (hashOid));
- // authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
- ASN1 aa = null;
- if (authenticatedAttributes.Count > 0) {
- aa = signerInfo.Add (new ASN1 (0xA0));
- foreach (ASN1 attr in authenticatedAttributes)
- aa.Add (attr);
- }
- // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
- if (key is RSA) {
- signerInfo.Add (AlgorithmIdentifier (PKCS7.Oid.rsaEncryption));
-
- if (aa != null) {
- // Calculate the signature here; otherwise it must be set from SignedData
- RSAPKCS1SignatureFormatter r = new RSAPKCS1SignatureFormatter (key);
- r.SetHashAlgorithm (hashAlgorithm);
- byte[] tbs = aa.GetBytes ();
- tbs [0] = 0x31; // not 0xA0 for signature
- HashAlgorithm ha = HashAlgorithm.Create (hashAlgorithm);
- byte[] tbsHash = ha.ComputeHash (tbs);
- signature = r.CreateSignature (tbsHash);
- }
- }
- else if (key is DSA) {
- throw new NotImplementedException ("not yet");
- }
- else
- throw new CryptographicException ("Unknown assymetric algorithm");
- // encryptedDigest EncryptedDigest,
- signerInfo.Add (new ASN1 (0x04, signature));
- // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
- if (unauthenticatedAttributes.Count > 0) {
- ASN1 ua = signerInfo.Add (new ASN1 (0xA1));
- foreach (ASN1 attr in unauthenticatedAttributes)
- ua.Add (attr);
- }
- return signerInfo;
- }
-
- public byte[] GetBytes ()
- {
- return GetASN1 ().GetBytes ();
- }
- }
- }
-}
+++ /dev/null
-//
-// StrongName.cs - Strong Name Implementation
-//
-// Author:
-// Sebastien Pouliot (sebastien@ximian.com)
-//
-// (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 Novell (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.Configuration.Assemblies;
-using System.Globalization;
-using System.IO;
-using System.Reflection;
-using System.Security.Cryptography;
-
-using Mono.Security.Cryptography;
-
-namespace Mono.Security {
-
-#if INSIDE_CORLIB
- internal
-#else
- public
-#endif
- sealed class StrongName {
-
- internal class StrongNameSignature {
- private byte[] hash;
- private byte[] signature;
- private UInt32 signaturePosition;
- private UInt32 signatureLength;
- private UInt32 metadataPosition;
- private UInt32 metadataLength;
- private byte cliFlag;
- private UInt32 cliFlagPosition;
-
- public byte[] Hash {
- get { return hash; }
- set { hash = value; }
- }
-
- public byte[] Signature {
- get { return signature; }
- set { signature = value; }
- }
-
- public UInt32 MetadataPosition {
- get { return metadataPosition; }
- set { metadataPosition = value; }
- }
-
- public UInt32 MetadataLength {
- get { return metadataLength; }
- set { metadataLength = value; }
- }
-
- public UInt32 SignaturePosition {
- get { return signaturePosition; }
- set { signaturePosition = value; }
- }
-
- public UInt32 SignatureLength {
- get { return signatureLength; }
- set { signatureLength = value; }
- }
-
- // delay signed -> flag = 0x01
- // strongsigned -> flag = 0x09
- public byte CliFlag {
- get { return cliFlag; }
- set { cliFlag = value; }
- }
-
- public UInt32 CliFlagPosition {
- get { return cliFlagPosition; }
- set { cliFlagPosition = value; }
- }
- }
-
- internal enum StrongNameOptions {
- Metadata,
- Signature
- }
-
- private RSA rsa;
- private byte[] publicKey;
- private byte[] keyToken;
- private string tokenAlgorithm;
-
- public StrongName ()
- {
- }
-
- public StrongName (int keySize)
- {
- rsa = new RSAManaged (keySize);
- }
-
- public StrongName (byte[] data)
- {
- if (data == null)
- throw new ArgumentNullException ("data");
-
- // check for ECMA key
- if (data.Length == 16) {
- int i = 0;
- int sum = 0;
- while (i < data.Length)
- sum += data [i++];
- if (sum == 4) {
- // it is the ECMA key
- publicKey = (byte[]) data.Clone ();
- }
- }
- else {
- RSA = CryptoConvert.FromCapiKeyBlob (data);
- if (rsa == null)
- throw new ArgumentException ("data isn't a correctly encoded RSA public key");
- }
- }
-
- public StrongName (RSA rsa)
- {
- if (rsa == null)
- throw new ArgumentNullException ("rsa");
-
- RSA = rsa;
- }
-
- private void InvalidateCache ()
- {
- publicKey = null;
- keyToken = null;
- }
-
- public bool CanSign {
- get {
- if (rsa == null)
- return false;
-#if INSIDE_CORLIB
- // the easy way
- if (RSA is RSACryptoServiceProvider) {
- // available as internal for corlib
- return !(rsa as RSACryptoServiceProvider).PublicOnly;
- }
- else
-#endif
- if (RSA is RSAManaged) {
- return !(rsa as RSAManaged).PublicOnly;
- }
- else {
- // the hard way
- try {
- RSAParameters p = rsa.ExportParameters (true);
- return ((p.D != null) && (p.P != null) && (p.Q != null));
- }
- catch (CryptographicException) {
- return false;
- }
- }
- }
- }
-
- public RSA RSA {
- get {
- // if none then we create a new keypair
- if (rsa == null)
- rsa = (RSA) RSA.Create ();
- return rsa;
- }
- set {
- rsa = value;
- InvalidateCache ();
- }
- }
-
- public byte[] PublicKey {
- get {
- if (publicKey == null) {
- byte[] keyPair = CryptoConvert.ToCapiKeyBlob (rsa, false);
- // since 2.0 public keys can vary from 384 to 16384 bits
- publicKey = new byte [32 + (rsa.KeySize >> 3)];
-
- // The first 12 bytes are documented at:
- // http://msdn.microsoft.com/library/en-us/cprefadd/html/grfungethashfromfile.asp
- // ALG_ID - Signature
- publicKey [0] = keyPair [4];
- publicKey [1] = keyPair [5];
- publicKey [2] = keyPair [6];
- publicKey [3] = keyPair [7];
- // ALG_ID - Hash (SHA1 == 0x8004)
- publicKey [4] = 0x04;
- publicKey [5] = 0x80;
- publicKey [6] = 0x00;
- publicKey [7] = 0x00;
- // Length of Public Key (in bytes)
- byte[] lastPart = BitConverterLE.GetBytes (publicKey.Length - 12);
- publicKey [8] = lastPart [0];
- publicKey [9] = lastPart [1];
- publicKey [10] = lastPart [2];
- publicKey [11] = lastPart [3];
- // Ok from here - Same structure as keypair - expect for public key
- publicKey [12] = 0x06; // PUBLICKEYBLOB
- // we can copy this part
- Buffer.BlockCopy (keyPair, 1, publicKey, 13, publicKey.Length - 13);
- // and make a small adjustment
- publicKey [23] = 0x31; // (RSA1 not RSA2)
- }
- return (byte[]) publicKey.Clone ();
- }
- }
-
- public byte[] PublicKeyToken {
- get {
- if (keyToken == null) {
- byte[] publicKey = PublicKey;
- if (publicKey == null)
- return null;
- HashAlgorithm ha = HashAlgorithm.Create (TokenAlgorithm);
- byte[] hash = ha.ComputeHash (publicKey);
- // we need the last 8 bytes in reverse order
- keyToken = new byte [8];
- Buffer.BlockCopy (hash, (hash.Length - 8), keyToken, 0, 8);
- Array.Reverse (keyToken, 0, 8);
- }
- return (byte[]) keyToken.Clone ();
- }
- }
-
- public string TokenAlgorithm {
- get {
- if (tokenAlgorithm == null)
- tokenAlgorithm = "SHA1";
- return tokenAlgorithm;
- }
- set {
- string algo = value.ToUpper (CultureInfo.InvariantCulture);
- if ((algo == "SHA1") || (algo == "MD5")) {
- tokenAlgorithm = value;
- InvalidateCache ();
- }
- else
- throw new ArgumentException ("Unsupported hash algorithm for token");
- }
- }
-
- public byte[] GetBytes ()
- {
- return CryptoConvert.ToCapiPrivateKeyBlob (RSA);
- }
-
- private UInt32 RVAtoPosition (UInt32 r, int sections, byte[] headers)
- {
- for (int i=0; i < sections; i++) {
- UInt32 p = BitConverterLE.ToUInt32 (headers, i * 40 + 20);
- UInt32 s = BitConverterLE.ToUInt32 (headers, i * 40 + 12);
- int l = (int) BitConverterLE.ToUInt32 (headers, i * 40 + 8);
- if ((s <= r) && (r < s + l)) {
- return p + r - s;
- }
- }
- return 0;
- }
-
- internal StrongNameSignature StrongHash (Stream stream, StrongNameOptions options)
- {
- StrongNameSignature info = new StrongNameSignature ();
-
- HashAlgorithm hash = HashAlgorithm.Create (TokenAlgorithm);
- CryptoStream cs = new CryptoStream (Stream.Null, hash, CryptoStreamMode.Write);
-
- // MS-DOS Header - always 128 bytes
- // ref: Section 24.2.1, Partition II Metadata
- byte[] mz = new byte [128];
- stream.Read (mz, 0, 128);
- if (BitConverterLE.ToUInt16 (mz, 0) != 0x5a4d)
- return null;
- UInt32 peHeader = BitConverterLE.ToUInt32 (mz, 60);
- cs.Write (mz, 0, 128);
- if (peHeader != 128) {
- byte[] mzextra = new byte [peHeader - 128];
- stream.Read (mzextra, 0, mzextra.Length);
- cs.Write (mzextra, 0, mzextra.Length);
- }
-
- // PE File Header - always 248 bytes
- // ref: Section 24.2.2, Partition II Metadata
- byte[] pe = new byte [248];
- stream.Read (pe, 0, 248);
- if (BitConverterLE.ToUInt32 (pe, 0) != 0x4550)
- return null;
- if (BitConverterLE.ToUInt16 (pe, 4) != 0x14c)
- return null;
- // MUST zeroize both CheckSum and Security Directory
- byte[] v = new byte [8];
- Buffer.BlockCopy (v, 0, pe, 88, 4);
- Buffer.BlockCopy (v, 0, pe, 152, 8);
- cs.Write (pe, 0, 248);
-
- UInt16 numSection = BitConverterLE.ToUInt16 (pe, 6);
- int sectionLength = (numSection * 40);
- byte[] sectionHeaders = new byte [sectionLength];
- stream.Read (sectionHeaders, 0, sectionLength);
- cs.Write (sectionHeaders, 0, sectionLength);
-
- UInt32 cliHeaderRVA = BitConverterLE.ToUInt32 (pe, 232);
- UInt32 cliHeaderPos = RVAtoPosition (cliHeaderRVA, numSection, sectionHeaders);
- int cliHeaderSiz = (int) BitConverterLE.ToUInt32 (pe, 236);
-
- // CLI Header
- // ref: Section 24.3.3, Partition II Metadata
- byte[] cli = new byte [cliHeaderSiz];
- stream.Position = cliHeaderPos;
- stream.Read (cli, 0, cliHeaderSiz);
-
- UInt32 strongNameSignatureRVA = BitConverterLE.ToUInt32 (cli, 32);
- info.SignaturePosition = RVAtoPosition (strongNameSignatureRVA, numSection, sectionHeaders);
- info.SignatureLength = BitConverterLE.ToUInt32 (cli, 36);
-
- UInt32 metadataRVA = BitConverterLE.ToUInt32 (cli, 8);
- info.MetadataPosition = RVAtoPosition (metadataRVA, numSection, sectionHeaders);
- info.MetadataLength = BitConverterLE.ToUInt32 (cli, 12);
-
- if (options == StrongNameOptions.Metadata) {
- cs.Close ();
- hash.Initialize ();
- byte[] metadata = new byte [info.MetadataLength];
- stream.Position = info.MetadataPosition;
- stream.Read (metadata, 0, metadata.Length);
- info.Hash = hash.ComputeHash (metadata);
- return info;
- }
-
- // now we hash every section EXCEPT the signature block
- for (int i=0; i < numSection; i++) {
- UInt32 start = BitConverterLE.ToUInt32 (sectionHeaders, i * 40 + 20);
- int length = (int) BitConverterLE.ToUInt32 (sectionHeaders, i * 40 + 16);
- byte[] section = new byte [length];
- stream.Position = start;
- stream.Read (section, 0, length);
- if ((start <= info.SignaturePosition) && (info.SignaturePosition < start + length)) {
- // hash before the signature
- int before = (int)(info.SignaturePosition - start);
- if (before > 0) {
- cs.Write (section, 0, before);
- }
- // copy signature
- info.Signature = new byte [info.SignatureLength];
- Buffer.BlockCopy (section, before, info.Signature, 0, (int)info.SignatureLength);
- Array.Reverse (info.Signature);
- // hash after the signature
- int s = (int)(before + info.SignatureLength);
- int after = (int)(length - s);
- if (after > 0) {
- cs.Write (section, s, after);
- }
- }
- else
- cs.Write (section, 0, length);
- }
-
- cs.Close ();
- info.Hash = hash.Hash;
- return info;
- }
-
- // return the same result as the undocumented and unmanaged GetHashFromAssemblyFile
- public byte[] Hash (string fileName)
- {
- FileStream fs = File.OpenRead (fileName);
- StrongNameSignature sn = StrongHash (fs, StrongNameOptions.Metadata);
- fs.Close ();
-
- return sn.Hash;
- }
-
- public bool Sign (string fileName)
- {
- bool result = false;
- StrongNameSignature sn;
- using (FileStream fs = File.OpenRead (fileName)) {
- sn = StrongHash (fs, StrongNameOptions.Signature);
- fs.Close ();
- }
- if (sn.Hash == null)
- return false;
-
- byte[] signature = null;
- try {
- RSAPKCS1SignatureFormatter sign = new RSAPKCS1SignatureFormatter (rsa);
- sign.SetHashAlgorithm (TokenAlgorithm);
- signature = sign.CreateSignature (sn.Hash);
- Array.Reverse (signature);
- }
- catch (CryptographicException) {
- return false;
- }
-
- using (FileStream fs = File.OpenWrite (fileName)) {
- fs.Position = sn.SignaturePosition;
- fs.Write (signature, 0, signature.Length);
- fs.Close ();
- result = true;
- }
- return result;
- }
-
- public bool Verify (string fileName)
- {
- bool result = false;
- using (FileStream fs = File.OpenRead (fileName)) {
- result = Verify (fs);
- fs.Close ();
- }
- return result;
- }
-
- public bool Verify (Stream stream)
- {
- StrongNameSignature sn = StrongHash (stream, StrongNameOptions.Signature);
- if (sn.Hash == null) {
- return false;
- }
-
- try {
- AssemblyHashAlgorithm algorithm = AssemblyHashAlgorithm.SHA1;
- if (tokenAlgorithm == "MD5")
- algorithm = AssemblyHashAlgorithm.MD5;
- return Verify (rsa, algorithm, sn.Hash, sn.Signature);
- }
- catch (CryptographicException) {
- // no exception allowed
- return false;
- }
- }
-
-#if INSIDE_CORLIB
- static object lockObject = new object ();
- static bool initialized;
-
- // We don't want a dependency on StrongNameManager in Mono.Security.dll
- static public bool IsAssemblyStrongnamed (string assemblyName)
- {
- if (!initialized) {
- lock (lockObject) {
- if (!initialized) {
-#if NET_2_1
- // Moonlight cannot depend on machine.config
-#else
- string config = Environment.GetMachineConfigPath ();
- StrongNameManager.LoadConfig (config);
-#endif
- initialized = true;
- }
- }
- }
-
- try {
- // this doesn't load the assembly (well it unloads it ;)
- // http://weblogs.asp.net/nunitaddin/posts/9991.aspx
- AssemblyName an = AssemblyName.GetAssemblyName (assemblyName);
- if (an == null)
- return false;
-
- byte[] publicKey = StrongNameManager.GetMappedPublicKey (an.GetPublicKeyToken ());
- if ((publicKey == null) || (publicKey.Length < 12)) {
- // no mapping
- publicKey = an.GetPublicKey ();
- if ((publicKey == null) || (publicKey.Length < 12))
- return false;
- }
-
- // Note: MustVerify is based on the original token (by design). Public key
- // remapping won't affect if the assembly is verified or not.
- if (!StrongNameManager.MustVerify (an)) {
- return true;
- }
-
- RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (publicKey, 12);
- StrongName sn = new StrongName (rsa);
- bool result = sn.Verify (assemblyName);
- return result;
- }
- catch {
- // no exception allowed
- return false;
- }
- }
-
- // TODO
- // we would get better performance if the runtime hashed the
- // assembly - as we wouldn't have to load it from disk a
- // second time. The runtime already have implementations of
- // SHA1 (and even MD5 if required someday).
- static public bool VerifySignature (byte[] publicKey, int algorithm, byte[] hash, byte[] signature)
- {
- try {
- RSA rsa = CryptoConvert.FromCapiPublicKeyBlob (publicKey);
- return Verify (rsa, (AssemblyHashAlgorithm) algorithm, hash, signature);
- }
- catch {
- // no exception allowed
- return false;
- }
- }
-#endif
- static private bool Verify (RSA rsa, AssemblyHashAlgorithm algorithm, byte[] hash, byte[] signature)
- {
- RSAPKCS1SignatureDeformatter vrfy = new RSAPKCS1SignatureDeformatter (rsa);
- switch (algorithm) {
- case AssemblyHashAlgorithm.MD5:
- vrfy.SetHashAlgorithm ("MD5");
- break;
- case AssemblyHashAlgorithm.SHA1:
- case AssemblyHashAlgorithm.None:
- default:
- vrfy.SetHashAlgorithm ("SHA1");
- break;
- }
- return vrfy.VerifySignature (hash, signature);
- }
- }
-}