mirror of
https://github.com/raphaeIl/Novaria.git
synced 2025-12-13 15:04:36 +01:00
fix dh (by plagiarism), refactor pcapparser
This commit is contained in:
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Mono.Math;
|
||||||
|
using Mono.Security.Cryptography;
|
||||||
using NSec.Cryptography;
|
using NSec.Cryptography;
|
||||||
using Org.BouncyCastle.Crypto.Engines;
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
using Org.BouncyCastle.Crypto.Modes;
|
using Org.BouncyCastle.Crypto.Modes;
|
||||||
@@ -24,7 +26,7 @@ namespace Novaria.Common.Crypto
|
|||||||
public static readonly int IVSize = 16;
|
public static readonly int IVSize = 16;
|
||||||
|
|
||||||
public static byte[] PS_REQUEST_NONCE = new byte[12]; // hardcoded nonce, probably makes it easier for server idk? could also just randomly generate but me lazy
|
public static byte[] PS_REQUEST_NONCE = new byte[12]; // hardcoded nonce, probably makes it easier for server idk? could also just randomly generate but me lazy
|
||||||
public static byte[] PS_PUBLIC_KEY { get => DiffieHellman.Instance.ServerPublicKey.ToByteArray(); }
|
//public static byte[] PS_PUBLIC_KEY { get => DiffieHellman.Instance.ServerPublicKey.GetBytes(); }
|
||||||
public static string TOKEN = "seggs"; // hardcoded for now
|
public static string TOKEN = "seggs"; // hardcoded for now
|
||||||
|
|
||||||
public static readonly byte[] DEFAULT_SERVERLIST_KEY = new byte[] { 74, 72, 42, 67, 80, 51, 50, 57, 89, 120, 111, 103, 81, 74, 69, 120 };
|
public static readonly byte[] DEFAULT_SERVERLIST_KEY = new byte[] { 74, 72, 42, 67, 80, 51, 50, 57, 89, 120, 111, 103, 81, 74, 69, 120 };
|
||||||
@@ -34,8 +36,9 @@ namespace Novaria.Common.Crypto
|
|||||||
|
|
||||||
public static readonly byte[] IKE_KEY = Encoding.ASCII.GetBytes("3LS9&oYdsp^5wi8&ZxC#c7MZg73hbEDw");
|
public static readonly byte[] IKE_KEY = Encoding.ASCII.GetBytes("3LS9&oYdsp^5wi8&ZxC#c7MZg73hbEDw");
|
||||||
|
|
||||||
|
private static DiffieHellmanManaged SendKey;
|
||||||
|
private static BigInteger p = BigInteger.Parse("1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919");
|
||||||
private static GcmBlockCipher cipher;
|
private static GcmBlockCipher cipher;
|
||||||
|
|
||||||
private static AesEngine engine;
|
private static AesEngine engine;
|
||||||
|
|
||||||
public delegate void AeadEncryptHandler(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, bool needAssociatedData);
|
public delegate void AeadEncryptHandler(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, bool needAssociatedData);
|
||||||
@@ -57,6 +60,25 @@ namespace Novaria.Common.Crypto
|
|||||||
PS_REQUEST_NONCE[11] = 42;
|
PS_REQUEST_NONCE[11] = 42;
|
||||||
|
|
||||||
InitAeadTool();
|
InitAeadTool();
|
||||||
|
InitDH();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int InitDH()
|
||||||
|
{
|
||||||
|
int nRandom = 1;
|
||||||
|
byte[] bytes = BitConverter.GetBytes(2);
|
||||||
|
if (BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
Array.Reverse<byte>(bytes);
|
||||||
|
}
|
||||||
|
byte[] bytes2 = BitConverter.GetBytes(nRandom);
|
||||||
|
if (BitConverter.IsLittleEndian)
|
||||||
|
{
|
||||||
|
Array.Reverse<byte>(bytes2);
|
||||||
|
}
|
||||||
|
|
||||||
|
SendKey = new DiffieHellmanManaged(p.GetBytes(), bytes, bytes2);
|
||||||
|
return nRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void InitAeadTool()
|
public static void InitAeadTool()
|
||||||
@@ -84,6 +106,24 @@ namespace Novaria.Common.Crypto
|
|||||||
AeadTool.cipher = new GcmBlockCipher(AeadTool.engine);
|
AeadTool.cipher = new GcmBlockCipher(AeadTool.engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SetAeadKey(byte[] pubKey)
|
||||||
|
{
|
||||||
|
byte[] array = SendKey.DecryptKeyExchange(pubKey);
|
||||||
|
|
||||||
|
int num = array.Length;
|
||||||
|
if (num > 32)
|
||||||
|
{
|
||||||
|
num = 32;
|
||||||
|
}
|
||||||
|
key3 = new byte[32];
|
||||||
|
Buffer.BlockCopy(array, 0, key3, 0, num);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] GetPubKey()
|
||||||
|
{
|
||||||
|
return new BigInteger(SendKey.CreateKeyExchange()).GetBytes();
|
||||||
|
}
|
||||||
|
|
||||||
private static void Encrypt_AESGCM_BouncyCastle(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, bool needAssociatedData)
|
private static void Encrypt_AESGCM_BouncyCastle(Span<byte> result, ReadOnlySpan<byte> key, ReadOnlySpan<byte> nonce, ReadOnlySpan<byte> data, bool needAssociatedData)
|
||||||
{
|
{
|
||||||
if (!needAssociatedData)
|
if (!needAssociatedData)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
using Novaria.Common.Util;
|
using Mono.Math;
|
||||||
using System.Numerics;
|
using Novaria.Common.Util;
|
||||||
|
|
||||||
namespace Novaria.Common.Crypto
|
namespace Novaria.Common.Crypto
|
||||||
{
|
{
|
||||||
public class DiffieHellman : Singleton<DiffieHellman>
|
public class DiffieHellman : Singleton<DiffieHellman>
|
||||||
{
|
{
|
||||||
private BigInteger p = BigInteger.Parse("1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919");
|
private System.Numerics.BigInteger old_p = System.Numerics.BigInteger.Parse("1552518092300708935130918131258481755631334049434514313202351194902966239949102107258669453876591642442910007680288864229150803718918046342632727613031282983744380820890196288509170691316593175367469551763119843371637221007210577919");
|
||||||
|
|
||||||
private BigInteger g = 2;
|
private BigInteger g = 2;
|
||||||
|
|
||||||
@@ -15,37 +15,49 @@ namespace Novaria.Common.Crypto
|
|||||||
|
|
||||||
public DiffieHellman()
|
public DiffieHellman()
|
||||||
{
|
{
|
||||||
Console.WriteLine(spriv);
|
//Console.WriteLine(spriv);
|
||||||
//g** Spriv mod p
|
//g** Spriv mod p
|
||||||
ServerPublicKey = BigInteger.ModPow(g, spriv, p);
|
//ServerPublicKey = this.g.ModPow(spriv, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] CalculateKey(byte[] clientPubKey) // server calculates key like this
|
public byte[] CalculateKey(byte[] clientPubKey) // server calculates key like this
|
||||||
{
|
{
|
||||||
BigInteger clientPubKeyInt = new BigInteger(clientPubKey.Reverse().ToArray());
|
// old stuff
|
||||||
|
//System.Numerics.BigInteger clientPubKeyInt = new System.Numerics.BigInteger(clientPubKey.Reverse().ToArray());
|
||||||
//Cpub**Spriv mod p
|
//var result = System.Numerics.BigInteger.ModPow(clientPubKeyInt, new System.Numerics.BigInteger(new byte[] { 1, 2, 3, 4 }), old_p);
|
||||||
Console.WriteLine(clientPubKeyInt.ToString());
|
|
||||||
|
|
||||||
var result = BigInteger.ModPow(clientPubKeyInt, spriv, p);
|
|
||||||
|
|
||||||
|
//Console.WriteLine(result);
|
||||||
//if (result < 0)
|
//if (result < 0)
|
||||||
//{
|
//{
|
||||||
// return result.ToByteArray(false, true)[..32];
|
// Console.WriteLine("THIS SHOULD CRASH");
|
||||||
//}
|
//}
|
||||||
|
|
||||||
return result.ToByteArray(true, true)[..32];
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is for manual pcap parsing use only, officalServerPubKey is in the first IKE response, client priv will be in frida
|
//BigInteger bigInteger = new BigInteger(clientPubKey.Reverse().ToArray()).ModPow(this.spriv, this.p);
|
||||||
public byte[] CalculateKey(byte[] officalServerPubKey, byte[] officialClientPriv)
|
|
||||||
{
|
|
||||||
BigInteger officalServerPubKeyInt = new BigInteger(officalServerPubKey.Reverse().ToArray());
|
|
||||||
BigInteger officialClientPrivInt = new BigInteger(officialClientPriv.Reverse().ToArray());
|
|
||||||
|
|
||||||
BigInteger result = BigInteger.ModPow(officalServerPubKeyInt, officialClientPrivInt, p);
|
//return bigInteger.GetBytes()[..32];
|
||||||
|
return null;
|
||||||
|
//BigInteger clientPubKeyInt = new BigInteger(clientPubKey.Reverse().ToArray());
|
||||||
|
|
||||||
return result.ToByteArray(true, true)[..32];
|
////Cpub**Spriv mod p
|
||||||
|
//Console.WriteLine(clientPubKeyInt.ToString());
|
||||||
|
|
||||||
|
//var result = BigInteger.ModPow(clientPubKeyInt, spriv, p);
|
||||||
|
|
||||||
|
//Console.WriteLine("------------test-------------------");
|
||||||
|
|
||||||
|
////Utils.PrintByteArray(BigInteger.Abs());
|
||||||
|
////if (result < 0)
|
||||||
|
////{
|
||||||
|
//// return result.ToByteArray(false, true)[..32];
|
||||||
|
////}
|
||||||
|
|
||||||
|
//Utils.PrintByteArray(result.ToByteArray(true, true));
|
||||||
|
|
||||||
|
//Console.WriteLine("----------------------------------");
|
||||||
|
|
||||||
|
//return result.GetBytes()[..32];
|
||||||
|
//return result.ToByteArray(true, true)[..32];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
//
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
68
Novaria.Common/Mono/Mono.Math.Prime/ConfidenceFactor.cs
Normal file
68
Novaria.Common/Mono/Mono.Math.Prime/ConfidenceFactor.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
218
Novaria.Common/Mono/Mono.Math.Prime/PrimalityTests.cs
Normal file
218
Novaria.Common/Mono/Mono.Math.Prime/PrimalityTests.cs
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
}
|
||||||
2372
Novaria.Common/Mono/Mono.Math/BigInteger.cs
Normal file
2372
Novaria.Common/Mono/Mono.Math/BigInteger.cs
Normal file
File diff suppressed because it is too large
Load Diff
805
Novaria.Common/Mono/Mono.Security.Cryptography/CryptoConvert.cs
Normal file
805
Novaria.Common/Mono/Mono.Security.Cryptography/CryptoConvert.cs
Normal file
@@ -0,0 +1,805 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INSIDE_CORLIB
|
||||||
|
static internal bool TryImportCapiPrivateKeyBlob (byte[] blob, int offset)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
var rsap = GetParametersFromCapiPrivateKeyBlob (blob, offset);
|
||||||
|
// Since we are only checking whether this throws an exception and
|
||||||
|
// not actually returning the `RSA` object, we can use `RSAManaged`
|
||||||
|
// here because that's what the `RSACryptoServiceProvider` implementation
|
||||||
|
// does internally.
|
||||||
|
var rsa = new RSAManaged ();
|
||||||
|
rsa.ImportParameters (rsap);
|
||||||
|
return true;
|
||||||
|
} catch (CryptographicException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
RSAParameters rsap = GetParametersFromCapiPrivateKeyBlob (blob, offset);
|
||||||
|
|
||||||
|
#if INSIDE_CORLIB && MOBILE
|
||||||
|
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 RSAParameters GetParametersFromCapiPrivateKeyBlob (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);
|
||||||
|
}
|
||||||
|
return rsap;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CryptographicException ("Invalid blob.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 INSIDE_CORLIB && MOBILE
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if INSIDE_CORLIB
|
||||||
|
static internal bool TryImportCapiPublicKeyBlob (byte[] blob, int offset)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
var rsap = GetParametersFromCapiPublicKeyBlob (blob, offset);
|
||||||
|
// Since we are only checking whether this throws an exception and
|
||||||
|
// not actually returning the `RSA` object, we can use `RSAManaged`
|
||||||
|
// here because that's what the `RSACryptoServiceProvider` implementation
|
||||||
|
// does internally.
|
||||||
|
var rsa = new RSAManaged ();
|
||||||
|
rsa.ImportParameters (rsap);
|
||||||
|
return true;
|
||||||
|
} catch (CryptographicException) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static public RSA FromCapiPublicKeyBlob (byte[] blob)
|
||||||
|
{
|
||||||
|
return FromCapiPublicKeyBlob (blob, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public RSA FromCapiPublicKeyBlob (byte[] blob, int offset)
|
||||||
|
{
|
||||||
|
var rsap = GetParametersFromCapiPublicKeyBlob (blob, offset);
|
||||||
|
|
||||||
|
try {
|
||||||
|
#if INSIDE_CORLIB && MOBILE
|
||||||
|
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 RSAParameters GetParametersFromCapiPublicKeyBlob (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);
|
||||||
|
return rsap;
|
||||||
|
} 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
147
Novaria.Common/Mono/Mono.Security.Cryptography/CryptoTools.cs
Normal file
147
Novaria.Common/Mono/Mono.Security.Cryptography/CryptoTools.cs
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
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
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (transform == null)
|
||||||
|
throw new ArgumentNullException ("transform");
|
||||||
|
if (blockSize <= 0)
|
||||||
|
throw new ArgumentOutOfRangeException ("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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
//
|
||||||
|
// DHKeyGeneration.cs: Defines the different key generation methods.
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Pieter Philippaerts (Pieter@mentalis.org)
|
||||||
|
//
|
||||||
|
// (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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.Cryptography {
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the different Diffie-Hellman key generation methods.
|
||||||
|
/// </summary>
|
||||||
|
public enum DHKeyGeneration {
|
||||||
|
/// <summary>
|
||||||
|
/// [TODO] you first randomly select a prime Q of size 160 bits, then choose P randomly among numbers like
|
||||||
|
/// Q*R+1 with R random. Then you go along with finding a generator G which has order exactly Q. The private
|
||||||
|
/// key X is then a number modulo Q.
|
||||||
|
/// [FIPS 186-2-Change1 -- http://csrc.nist.gov/publications/fips/]
|
||||||
|
/// </summary>
|
||||||
|
// see RFC2631 [http://www.faqs.org/rfcs/rfc2631.html]
|
||||||
|
//DSA,
|
||||||
|
/// <summary>
|
||||||
|
/// Returns dynamically generated values for P and G. Unlike the Sophie Germain or DSA key generation methods,
|
||||||
|
/// this method does not ensure that the selected prime offers an adequate security level.
|
||||||
|
/// </summary>
|
||||||
|
Random,
|
||||||
|
/// <summary>
|
||||||
|
/// Returns dynamically generated values for P and G. P is a Sophie Germain prime, which has some interesting
|
||||||
|
/// security features when used with Diffie Hellman.
|
||||||
|
/// </summary>
|
||||||
|
//SophieGermain,
|
||||||
|
/// <summary>
|
||||||
|
/// Returns values for P and G that are hard coded in this library. Contrary to what your intuition may tell you,
|
||||||
|
/// using these hard coded values is perfectly safe.
|
||||||
|
/// The values of the P and G parameters are taken from 'The OAKLEY Key Determination Protocol' [RFC2412].
|
||||||
|
/// This is the prefered key generation method, because it is very fast and very safe.
|
||||||
|
/// Because this method uses fixed values for the P and G parameters, not all bit sizes are supported.
|
||||||
|
/// The current implementation supports bit sizes of 768, 1024 and 1536.
|
||||||
|
/// </summary>
|
||||||
|
Static
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// DHParameters.cs: Defines a structure that holds the parameters of the Diffie-Hellman algorithm
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Pieter Philippaerts (Pieter@mentalis.org)
|
||||||
|
//
|
||||||
|
// (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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.Cryptography {
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the parameters of the Diffie-Hellman algorithm.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public struct DHParameters {
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the public <b>P</b> parameter of the Diffie-Hellman algorithm.
|
||||||
|
/// </summary>
|
||||||
|
public byte[] P;
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the public <b>G</b> parameter of the Diffie-Hellman algorithm.
|
||||||
|
/// </summary>
|
||||||
|
public byte[] G;
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the private <b>X</b> parameter of the Diffie-Hellman algorithm.
|
||||||
|
/// </summary>
|
||||||
|
[NonSerialized]
|
||||||
|
public byte[] X;
|
||||||
|
}
|
||||||
|
}
|
||||||
124
Novaria.Common/Mono/Mono.Security.Cryptography/DiffieHellman.cs
Normal file
124
Novaria.Common/Mono/Mono.Security.Cryptography/DiffieHellman.cs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
//
|
||||||
|
// DiffieHellman.cs: Defines a base class from which all Diffie-Hellman implementations inherit
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Pieter Philippaerts (Pieter@mentalis.org)
|
||||||
|
//
|
||||||
|
// (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// 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.Text;
|
||||||
|
using System.Security;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using Mono.Math;
|
||||||
|
|
||||||
|
namespace Mono.Security.Cryptography {
|
||||||
|
/// <summary>
|
||||||
|
/// Defines a base class from which all Diffie-Hellman implementations inherit.
|
||||||
|
/// </summary>
|
||||||
|
public abstract class DiffieHellman : AsymmetricAlgorithm {
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the default implementation of the <see cref="DiffieHellman"/> algorithm.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A new instance of the default implementation of DiffieHellman.</returns>
|
||||||
|
public static new DiffieHellman Create () {
|
||||||
|
return Create ("Mono.Security.Cryptography.DiffieHellman");
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the specified implementation of <see cref="DiffieHellman"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="algName">The name of the implementation of DiffieHellman to use.</param>
|
||||||
|
/// <returns>A new instance of the specified implementation of DiffieHellman.</returns>
|
||||||
|
public static new DiffieHellman Create (string algName) {
|
||||||
|
return (DiffieHellman) CryptoConfig.CreateFromName (algName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, creates the key exchange data.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The key exchange data to be sent to the intended recipient.</returns>
|
||||||
|
public abstract byte[] CreateKeyExchange();
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, extracts secret information from the key exchange data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keyex">The key exchange data within which the secret information is hidden.</param>
|
||||||
|
/// <returns>The secret information derived from the key exchange data.</returns>
|
||||||
|
public abstract byte[] DecryptKeyExchange (byte[] keyex);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, exports the <see cref="DHParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="includePrivate"><b>true</b> to include private parameters; otherwise, <b>false</b>.</param>
|
||||||
|
/// <returns>The parameters for Diffie-Hellman.</returns>
|
||||||
|
public abstract DHParameters ExportParameters (bool includePrivate);
|
||||||
|
/// <summary>
|
||||||
|
/// When overridden in a derived class, imports the specified <see cref="DHParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parameters">The parameters for Diffie-Hellman.</param>
|
||||||
|
public abstract void ImportParameters (DHParameters parameters);
|
||||||
|
|
||||||
|
private byte[] GetNamedParam(SecurityElement se, string param) {
|
||||||
|
SecurityElement sep = se.SearchForChildByTag(param);
|
||||||
|
if (sep == null)
|
||||||
|
return null;
|
||||||
|
return Convert.FromBase64String(sep.Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates and returns an XML string representation of the current <see cref="DiffieHellman"/> object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="includePrivateParameters"><b>true</b> to include private parameters; otherwise, <b>false</b>.</param>
|
||||||
|
/// <returns>An XML string encoding of the current DiffieHellman object.</returns>
|
||||||
|
public override string ToXmlString (bool includePrivateParameters) {
|
||||||
|
StringBuilder sb = new StringBuilder ();
|
||||||
|
DHParameters dhParams = ExportParameters(includePrivateParameters);
|
||||||
|
try {
|
||||||
|
sb.Append ("<DHKeyValue>");
|
||||||
|
|
||||||
|
sb.Append ("<P>");
|
||||||
|
sb.Append (Convert.ToBase64String (dhParams.P));
|
||||||
|
sb.Append ("</P>");
|
||||||
|
|
||||||
|
sb.Append ("<G>");
|
||||||
|
sb.Append (Convert.ToBase64String (dhParams.G));
|
||||||
|
sb.Append ("</G>");
|
||||||
|
|
||||||
|
if (includePrivateParameters) {
|
||||||
|
sb.Append ("<X>");
|
||||||
|
sb.Append (Convert.ToBase64String (dhParams.X));
|
||||||
|
sb.Append ("</X>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append ("</DHKeyValue>");
|
||||||
|
} finally {
|
||||||
|
Array.Clear(dhParams.P, 0, dhParams.P.Length);
|
||||||
|
Array.Clear(dhParams.G, 0, dhParams.G.Length);
|
||||||
|
if (dhParams.X != null)
|
||||||
|
Array.Clear(dhParams.X, 0, dhParams.X.Length);
|
||||||
|
}
|
||||||
|
return sb.ToString ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,273 @@
|
|||||||
|
//
|
||||||
|
// DiffieHellmanManaged.cs: Implements the Diffie-Hellman key agreement algorithm
|
||||||
|
//
|
||||||
|
// Author:
|
||||||
|
// Pieter Philippaerts (Pieter@mentalis.org)
|
||||||
|
//
|
||||||
|
// (C) 2003 The Mentalis.org Team (http://www.mentalis.org/)
|
||||||
|
//
|
||||||
|
// References:
|
||||||
|
// - PKCS#3 [http://www.rsasecurity.com/rsalabs/pkcs/pkcs-3/]
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
// a copy of this software and associated documentation files (the
|
||||||
|
// "Software"), to deal in the Software without restriction, including
|
||||||
|
// without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
// permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
// the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be
|
||||||
|
// included in all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
//
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using Mono.Math;
|
||||||
|
|
||||||
|
namespace Mono.Security.Cryptography {
|
||||||
|
/// <summary>
|
||||||
|
/// Implements the Diffie-Hellman algorithm.
|
||||||
|
/// </summary>
|
||||||
|
public sealed class DiffieHellmanManaged : DiffieHellman {
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The default length of the shared secret is 1024 bits.</remarks>
|
||||||
|
public DiffieHellmanManaged() : this(1024, 160, DHKeyGeneration.Static) {}
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bitLength">The length, in bits, of the public P parameter.</param>
|
||||||
|
/// <param name="l">The length, in bits, of the secret value X. This parameter can be set to 0 to use the default size.</param>
|
||||||
|
/// <param name="method">One of the <see cref="DHKeyGeneration"/> values.</param>
|
||||||
|
/// <remarks>The larger the bit length, the more secure the algorithm is. The default is 1024 bits. The minimum bit length is 128 bits.<br/>The size of the private value will be one fourth of the bit length specified.</remarks>
|
||||||
|
/// <exception cref="ArgumentException">The specified bit length is invalid.</exception>
|
||||||
|
public DiffieHellmanManaged(int bitLength, int l, DHKeyGeneration method) {
|
||||||
|
if (bitLength < 256 || l < 0)
|
||||||
|
throw new ArgumentException();
|
||||||
|
BigInteger p, g;
|
||||||
|
GenerateKey (bitLength, method, out p, out g);
|
||||||
|
Initialize(p, g, null, l, false);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">The P parameter of the Diffie-Hellman algorithm. This is a public parameter.</param>
|
||||||
|
/// <param name="g">The G parameter of the Diffie-Hellman algorithm. This is a public parameter.</param>
|
||||||
|
/// <param name="x">The X parameter of the Diffie-Hellman algorithm. This is a private parameter. If this parameters is a null reference (<b>Nothing</b> in Visual Basic), a secret value of the default size will be generated.</param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="p"/> or <paramref name="g"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
|
||||||
|
/// <exception cref="CryptographicException"><paramref name="p"/> or <paramref name="g"/> is invalid.</exception>
|
||||||
|
public DiffieHellmanManaged(byte[] p, byte[] g, byte[] x) {
|
||||||
|
if (p == null || g == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
if (x == null)
|
||||||
|
Initialize(new BigInteger(p), new BigInteger(g), null, 0, true);
|
||||||
|
else
|
||||||
|
Initialize(new BigInteger(p), new BigInteger(g), new BigInteger(x), 0, true);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new <see cref="DiffieHellmanManaged"/> instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="p">The P parameter of the Diffie-Hellman algorithm.</param>
|
||||||
|
/// <param name="g">The G parameter of the Diffie-Hellman algorithm.</param>
|
||||||
|
/// <param name="l">The length, in bits, of the private value. If 0 is specified, the default value will be used.</param>
|
||||||
|
/// <exception cref="ArgumentNullException"><paramref name="p"/> or <paramref name="g"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
|
||||||
|
/// <exception cref="ArgumentException"><paramref name="l"/> is invalid.</exception>
|
||||||
|
/// <exception cref="CryptographicException"><paramref name="p"/> or <paramref name="g"/> is invalid.</exception>
|
||||||
|
public DiffieHellmanManaged(byte[] p, byte[] g, int l) {
|
||||||
|
if (p == null || g == null)
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
if (l < 0)
|
||||||
|
throw new ArgumentException();
|
||||||
|
Initialize(new BigInteger(p), new BigInteger(g), null, l, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// initializes the private variables (throws CryptographicException)
|
||||||
|
private void Initialize(BigInteger p, BigInteger g, BigInteger x, int secretLen, bool checkInput) {
|
||||||
|
if (checkInput) {
|
||||||
|
if (!p.IsProbablePrime() || g <= 0 || g >= p || (x != null && (x <= 0 || x > p - 2)))
|
||||||
|
throw new CryptographicException();
|
||||||
|
}
|
||||||
|
// default is to generate a number as large as the prime this
|
||||||
|
// is usually overkill, but it's the most secure thing we can
|
||||||
|
// do if the user doesn't specify a desired secret length ...
|
||||||
|
if (secretLen == 0)
|
||||||
|
secretLen = p.BitCount();
|
||||||
|
m_P = p;
|
||||||
|
m_G = g;
|
||||||
|
if (x == null) {
|
||||||
|
BigInteger pm1 = m_P - 1;
|
||||||
|
for(m_X = BigInteger.GenerateRandom(secretLen); m_X >= pm1 || m_X == 0; m_X = BigInteger.GenerateRandom(secretLen)) {}
|
||||||
|
} else {
|
||||||
|
m_X = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Creates the key exchange data.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The key exchange data to be sent to the intended recipient.</returns>
|
||||||
|
public override byte[] CreateKeyExchange() {
|
||||||
|
BigInteger y = m_G.ModPow(m_X, m_P);
|
||||||
|
byte[] ret = y.GetBytes();
|
||||||
|
y.Clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Extracts secret information from the key exchange data.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="keyEx">The key exchange data within which the shared key is hidden.</param>
|
||||||
|
/// <returns>The shared key derived from the key exchange data.</returns>
|
||||||
|
public override byte[] DecryptKeyExchange(byte[] keyEx) {
|
||||||
|
BigInteger pvr = new BigInteger(keyEx);
|
||||||
|
BigInteger z = pvr.ModPow(m_X, m_P);
|
||||||
|
byte[] ret = z.GetBytes();
|
||||||
|
z.Clear();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the key exchange algorithm.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the key exchange algorithm.</value>
|
||||||
|
public override string KeyExchangeAlgorithm {
|
||||||
|
get {
|
||||||
|
return "1.2.840.113549.1.3"; // PKCS#3 OID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the signature algorithm.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>The name of the signature algorithm.</value>
|
||||||
|
public override string SignatureAlgorithm {
|
||||||
|
get {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// clear keys
|
||||||
|
protected override void Dispose(bool disposing) {
|
||||||
|
if (!m_Disposed) {
|
||||||
|
if (m_P != null) m_P.Clear();
|
||||||
|
if (m_G != null) m_G.Clear();
|
||||||
|
if (m_X != null) m_X.Clear();
|
||||||
|
}
|
||||||
|
m_Disposed = true;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Exports the <see cref="DHParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="includePrivateParameters"><b>true</b> to include private parameters; otherwise, <b>false</b>.</param>
|
||||||
|
/// <returns>The parameters for <see cref="DiffieHellman"/>.</returns>
|
||||||
|
public override DHParameters ExportParameters(bool includePrivateParameters) {
|
||||||
|
DHParameters ret = new DHParameters();
|
||||||
|
ret.P = m_P.GetBytes();
|
||||||
|
ret.G = m_G.GetBytes();
|
||||||
|
if (includePrivateParameters) {
|
||||||
|
ret.X = m_X.GetBytes();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Imports the specified <see cref="DHParameters"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="parameters">The parameters for <see cref="DiffieHellman"/>.</param>
|
||||||
|
/// <exception cref="CryptographicException"><paramref name="P"/> or <paramref name="G"/> is a null reference (<b>Nothing</b> in Visual Basic) -or- <paramref name="P"/> is not a prime number.</exception>
|
||||||
|
public override void ImportParameters(DHParameters parameters) {
|
||||||
|
if (parameters.P == null)
|
||||||
|
throw new CryptographicException("Missing P value.");
|
||||||
|
if (parameters.G == null)
|
||||||
|
throw new CryptographicException("Missing G value.");
|
||||||
|
|
||||||
|
BigInteger p = new BigInteger(parameters.P), g = new BigInteger(parameters.G), x = null;
|
||||||
|
if (parameters.X != null) {
|
||||||
|
x = new BigInteger(parameters.X);
|
||||||
|
}
|
||||||
|
Initialize(p, g, x, 0, true);
|
||||||
|
}
|
||||||
|
~DiffieHellmanManaged() {
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: implement DH key generation methods
|
||||||
|
private void GenerateKey(int bitlen, DHKeyGeneration keygen, out BigInteger p, out BigInteger g) {
|
||||||
|
if (keygen == DHKeyGeneration.Static) {
|
||||||
|
if (bitlen == 768)
|
||||||
|
p = new BigInteger(m_OAKLEY768);
|
||||||
|
else if (bitlen == 1024)
|
||||||
|
p = new BigInteger(m_OAKLEY1024);
|
||||||
|
else if (bitlen == 1536)
|
||||||
|
p = new BigInteger(m_OAKLEY1536);
|
||||||
|
else
|
||||||
|
throw new ArgumentException("Invalid bit size.");
|
||||||
|
g = new BigInteger(22); // all OAKLEY keys use 22 as generator
|
||||||
|
//} else if (keygen == DHKeyGeneration.SophieGermain) {
|
||||||
|
// throw new NotSupportedException(); //TODO
|
||||||
|
//} else if (keygen == DHKeyGeneration.DSA) {
|
||||||
|
// 1. Let j = (p - 1)/q.
|
||||||
|
// 2. Set h = any integer, where 1 < h < p - 1
|
||||||
|
// 3. Set g = h^j mod p
|
||||||
|
// 4. If g = 1 go to step 2
|
||||||
|
// BigInteger j = (p - 1) / q;
|
||||||
|
} else { // random
|
||||||
|
p = BigInteger.GeneratePseudoPrime(bitlen);
|
||||||
|
g = new BigInteger(3); // always use 3 as a generator
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BigInteger m_P;
|
||||||
|
private BigInteger m_G;
|
||||||
|
private BigInteger m_X;
|
||||||
|
private bool m_Disposed;
|
||||||
|
|
||||||
|
private static byte[] m_OAKLEY768 = new byte[] {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||||
|
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||||
|
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||||
|
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||||
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||||
|
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||||
|
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||||
|
0xA6, 0x3A, 0x36, 0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
private static byte[] m_OAKLEY1024 = new byte[] {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||||
|
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||||
|
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||||
|
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||||
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||||
|
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||||
|
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||||
|
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||||
|
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||||
|
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
private static byte[] m_OAKLEY1536 = new byte[] {
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x0F, 0xDA, 0xA2,
|
||||||
|
0x21, 0x68, 0xC2, 0x34, 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||||
|
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74, 0x02, 0x0B, 0xBE, 0xA6,
|
||||||
|
0x3B, 0x13, 0x9B, 0x22, 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||||
|
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B, 0x30, 0x2B, 0x0A, 0x6D,
|
||||||
|
0xF2, 0x5F, 0x14, 0x37, 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||||
|
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6, 0xF4, 0x4C, 0x42, 0xE9,
|
||||||
|
0xA6, 0x37, 0xED, 0x6B, 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||||
|
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5, 0xAE, 0x9F, 0x24, 0x11,
|
||||||
|
0x7C, 0x4B, 0x1F, 0xE6, 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||||
|
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05, 0x98, 0xDA, 0x48, 0x36,
|
||||||
|
0x1C, 0x55, 0xD3, 0x9A, 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||||
|
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96, 0x1C, 0x62, 0xF3, 0x56,
|
||||||
|
0x20, 0x85, 0x52, 0xBB, 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||||
|
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04, 0xF1, 0x74, 0x6C, 0x08,
|
||||||
|
0xCA, 0x23, 0x73, 0x27, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<AllowUnsafeBlocks>False</AllowUnsafeBlocks>
|
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -15,5 +15,9 @@
|
|||||||
<PackageReference Include="Serilog" Version="3.1.1" />
|
<PackageReference Include="Serilog" Version="3.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Mono\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
75
Novaria.Common/Util/BigIntegerExtensions.cs
Normal file
75
Novaria.Common/Util/BigIntegerExtensions.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Novaria.Common.Util
|
||||||
|
{
|
||||||
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
|
public static class BigIntegerExtensions
|
||||||
|
{
|
||||||
|
public static byte[] GetBytes(this BigInteger value)
|
||||||
|
{
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return new byte[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
int bitCount = value.GetBitCount();
|
||||||
|
int byteCount = bitCount >> 3;
|
||||||
|
if ((bitCount & 7) != 0)
|
||||||
|
{
|
||||||
|
byteCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] result = new byte[byteCount];
|
||||||
|
int remainingBytes = byteCount & 3;
|
||||||
|
if (remainingBytes == 0)
|
||||||
|
{
|
||||||
|
remainingBytes = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteIndex = 0;
|
||||||
|
|
||||||
|
// Convert BigInteger to unsigned equivalent (to match the behavior of the original code)
|
||||||
|
BigInteger unsignedValue = BigInteger.Abs(value);
|
||||||
|
|
||||||
|
// Iterate through each 32-bit chunk of the BigInteger
|
||||||
|
while (unsignedValue != 0)
|
||||||
|
{
|
||||||
|
uint currentWord = (uint)(unsignedValue & 0xFFFFFFFF);
|
||||||
|
unsignedValue >>= 32;
|
||||||
|
|
||||||
|
for (int i = remainingBytes - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
result[byteIndex + i] = (byte)(currentWord & 0xFF);
|
||||||
|
currentWord >>= 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
byteIndex += remainingBytes;
|
||||||
|
remainingBytes = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to calculate the number of significant bits in a BigInteger
|
||||||
|
private static int GetBitCount(this BigInteger value)
|
||||||
|
{
|
||||||
|
BigInteger unsignedValue = BigInteger.Abs(value);
|
||||||
|
int bits = 0;
|
||||||
|
|
||||||
|
while (unsignedValue != 0)
|
||||||
|
{
|
||||||
|
unsignedValue >>= 1;
|
||||||
|
bits++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -113,18 +113,28 @@ namespace Novaria.GameServer.Controllers.Api
|
|||||||
Log.Information("RECEIVED client public key: ");
|
Log.Information("RECEIVED client public key: ");
|
||||||
Utils.PrintByteArray(clientPublicKey);
|
Utils.PrintByteArray(clientPublicKey);
|
||||||
|
|
||||||
AeadTool.key3 = DiffieHellman.Instance.CalculateKey(clientPublicKey);
|
Console.WriteLine("OLD::");
|
||||||
|
|
||||||
|
Console.WriteLine(new System.Numerics.BigInteger(clientPublicKey.Reverse().ToArray()));
|
||||||
|
|
||||||
|
Console.WriteLine("OLD::");
|
||||||
|
|
||||||
|
//AeadTool.key3 = DiffieHellman.Instance.CalculateKey(clientPublicKey);
|
||||||
|
AeadTool.SetAeadKey(clientPublicKey);
|
||||||
Log.Information("KEY3 (chacha20 key) calculated: ");
|
Log.Information("KEY3 (chacha20 key) calculated: ");
|
||||||
Utils.PrintByteArray(AeadTool.key3);
|
Utils.PrintByteArray(AeadTool.key3);
|
||||||
|
|
||||||
|
byte[] pubKey = AeadTool.GetPubKey();
|
||||||
|
|
||||||
IKEResp ikeResponse = new IKEResp()
|
IKEResp ikeResponse = new IKEResp()
|
||||||
{
|
{
|
||||||
PubKey = ByteString.CopyFrom(AeadTool.PS_PUBLIC_KEY.Reverse().ToArray()),
|
//PubKey = ByteString.CopyFrom(AeadTool.PS_PUBLIC_KEY.Reverse().ToArray()),
|
||||||
|
PubKey = ByteString.CopyFrom(pubKey),
|
||||||
Token = AeadTool.TOKEN
|
Token = AeadTool.TOKEN
|
||||||
};
|
};
|
||||||
|
|
||||||
Log.Information("Sending ps server public key: ");
|
Log.Information("Sending ps server public key: ");
|
||||||
Utils.PrintByteArray(AeadTool.PS_PUBLIC_KEY);
|
Utils.PrintByteArray(pubKey);
|
||||||
|
|
||||||
Packet ikePacket = new Packet()
|
Packet ikePacket = new Packet()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -52,20 +52,6 @@ namespace Novaria.GameServer.Controllers.Api.ProtocolHandlers
|
|||||||
accountInfo.Newbies.Add(new NewbieInfo() { GroupId = 101, StepId = -1 });
|
accountInfo.Newbies.Add(new NewbieInfo() { GroupId = 101, StepId = -1 });
|
||||||
accountInfo.Newbies.Add(new NewbieInfo() { GroupId = 102, StepId = -1 });
|
accountInfo.Newbies.Add(new NewbieInfo() { GroupId = 102, StepId = -1 });
|
||||||
|
|
||||||
|
|
||||||
byte[] real_key = AeadTool.key3;
|
|
||||||
ClientType real_client_type = AeadTool.clientType;
|
|
||||||
|
|
||||||
// load from pcap
|
|
||||||
AeadTool.clientType = ClientType.Mobile; // my pcap were from mobile so gotta switch it over
|
|
||||||
AeadTool.InitAeadTool();
|
|
||||||
|
|
||||||
PcapParser.PcapParser.Instance.Parse("all_mainmenu_packets.json");
|
|
||||||
|
|
||||||
// after pcap parse switch it back, this should rlly be done inside PcapParser.Parse()
|
|
||||||
AeadTool.clientType = real_client_type;
|
|
||||||
AeadTool.InitAeadTool();
|
|
||||||
|
|
||||||
PlayerInfo pcapPlayerInfo = (PlayerInfo)PcapParser.PcapParser.Instance.GetPcapPacket(NetMsgId.player_data_succeed_ack);
|
PlayerInfo pcapPlayerInfo = (PlayerInfo)PcapParser.PcapParser.Instance.GetPcapPacket(NetMsgId.player_data_succeed_ack);
|
||||||
|
|
||||||
PlayerInfo playerInfoResponse = new PlayerInfo()
|
PlayerInfo playerInfoResponse = new PlayerInfo()
|
||||||
@@ -73,7 +59,6 @@ namespace Novaria.GameServer.Controllers.Api.ProtocolHandlers
|
|||||||
Acc = pcapPlayerInfo.Acc
|
Acc = pcapPlayerInfo.Acc
|
||||||
};
|
};
|
||||||
|
|
||||||
AeadTool.key3 = real_key;
|
|
||||||
Log.Information("Sending player_new_notify packet: " + JsonSerializer.Serialize(pcapPlayerInfo));
|
Log.Information("Sending player_new_notify packet: " + JsonSerializer.Serialize(pcapPlayerInfo));
|
||||||
return Packet.Create(NetMsgId.player_data_succeed_ack, pcapPlayerInfo);
|
return Packet.Create(NetMsgId.player_data_succeed_ack, pcapPlayerInfo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ namespace Novaria.GameServer
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
|
PcapParser.PcapParser.Instance.LoadAllPackets(); // turn this off after real handlers are finished
|
||||||
|
|
||||||
Log.Information("Starting SDK Server...");
|
Log.Information("Starting SDK Server...");
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,6 +19,29 @@ namespace Novaria.PcapParser
|
|||||||
public int totalPacketsCount = 0;
|
public int totalPacketsCount = 0;
|
||||||
public List<NovaPacket> packets = new List<NovaPacket>();
|
public List<NovaPacket> packets = new List<NovaPacket>();
|
||||||
|
|
||||||
|
public void LoadAllPackets()
|
||||||
|
{
|
||||||
|
byte[] real_key = AeadTool.key3;
|
||||||
|
ClientType real_client_type = AeadTool.clientType;
|
||||||
|
|
||||||
|
// load from pcap
|
||||||
|
AeadTool.clientType = ClientType.Mobile; // my pcap were from mobile so gotta switch it over
|
||||||
|
AeadTool.InitAeadTool();
|
||||||
|
|
||||||
|
// these are all the packets i have, should've done more but ran out of time :/
|
||||||
|
PcapParser.Instance.Parse("all_mainmenu_packets.json");
|
||||||
|
PcapParser.Instance.Parse("accidently_too_many.json");
|
||||||
|
PcapParser.Instance.Parse("create_acc_packets.json");
|
||||||
|
PcapParser.Instance.Parse("first_instant_join.json");
|
||||||
|
PcapParser.Instance.Parse("full_everything.json");
|
||||||
|
PcapParser.Instance.Parse("lvl30_tutorials.json");
|
||||||
|
|
||||||
|
// after pcap parse switch it back
|
||||||
|
AeadTool.clientType = real_client_type;
|
||||||
|
AeadTool.InitAeadTool();
|
||||||
|
AeadTool.key3 = real_key;
|
||||||
|
}
|
||||||
|
|
||||||
public void Parse(string pcapFileName, bool auto_key = true)
|
public void Parse(string pcapFileName, bool auto_key = true)
|
||||||
{
|
{
|
||||||
string pcapJsonFile = File.ReadAllText($"../../../../Novaria.PcapParser/{pcapFileName}"); // disgusting pathing, but "not hardcoded" now ig
|
string pcapJsonFile = File.ReadAllText($"../../../../Novaria.PcapParser/{pcapFileName}"); // disgusting pathing, but "not hardcoded" now ig
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
{
|
{
|
||||||
public static void Main(string[] args)
|
public static void Main(string[] args)
|
||||||
{
|
{
|
||||||
PcapParser.Instance.Parse("all_mainmenu_packets.json");
|
PcapParser.Instance.LoadAllPackets();
|
||||||
|
|
||||||
PcapParser.Instance.SavePackets("parsed_packets.json");
|
PcapParser.Instance.SavePackets("all_parsed_packets.json");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
87884
Novaria.PcapParser/all_parsed_packets.json
Normal file
87884
Novaria.PcapParser/all_parsed_packets.json
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user