66 lines
2.1 KiB
C#
66 lines
2.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using ECDsaTest.SafeHandles;
|
|
|
|
internal static partial class Interop
|
|
{
|
|
internal static partial class Crypto
|
|
{
|
|
|
|
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumDestroy")]
|
|
internal static extern void BigNumDestroy(IntPtr a);
|
|
|
|
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumToBinary")]
|
|
private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte* to);
|
|
|
|
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetBigNumBytes")]
|
|
private static extern int GetBigNumBytes(SafeBignumHandle a);
|
|
|
|
|
|
internal static byte[] ExtractBignum(IntPtr bignum, int targetSize)
|
|
{
|
|
// Given that the only reference held to bignum is an IntPtr, create an unowned SafeHandle
|
|
// to ensure that we don't destroy the key after extraction.
|
|
using (SafeBignumHandle handle = new SafeBignumHandle(bignum, ownsHandle: false))
|
|
{
|
|
return ExtractBignum(handle, targetSize);
|
|
}
|
|
}
|
|
|
|
private static unsafe byte[] ExtractBignum(SafeBignumHandle bignum, int targetSize)
|
|
{
|
|
if (bignum == null || bignum.IsInvalid)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
int compactSize = GetBigNumBytes(bignum);
|
|
|
|
if (targetSize < compactSize)
|
|
{
|
|
targetSize = compactSize;
|
|
}
|
|
|
|
// OpenSSL BIGNUM values do not record leading zeroes.
|
|
// Windows Crypt32 does.
|
|
//
|
|
// Since RSACryptoServiceProvider already checks that RSAParameters.DP.Length is
|
|
// exactly half of RSAParameters.Modulus.Length, we need to left-pad (big-endian)
|
|
// the array with zeroes.
|
|
int offset = targetSize - compactSize;
|
|
|
|
byte[] buf = new byte[targetSize];
|
|
|
|
fixed (byte* to = buf)
|
|
{
|
|
byte* start = to + offset;
|
|
BigNumToBinary(bignum, start);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
}
|
|
}
|