Статус: Сотрудник
Группы: Участники
Зарегистрирован: 26.07.2011(UTC) Сообщений: 13,340 Сказал «Спасибо»: 550 раз Поблагодарили: 2212 раз в 1727 постах
|
Вот что получилось для получения DecryptPara: GetCertToDecrypt(string EncryptedFile, out SafeCSPHandle hProv, out Win32.CRYPT_KEY_PROV_INFO KeyProvInfo, out Win32.CMSG_CTRL_DECRYPT_PARA DecryptPara)
Код:
public unsafe static bool GetCertToDecrypt(string EncryptedFile, out SafeCSPHandle hProv, out Win32.CRYPT_KEY_PROV_INFO KeyProvInfo, out Win32.CMSG_CTRL_DECRYPT_PARA DecryptPara)
{
/*SafeCSPHandle */hProv = SafeCSPHandle.Null;
DecryptPara = new Win32.CMSG_CTRL_DECRYPT_PARA();
DecryptPara.cbSize = 0;
/*Win32.CRYPT_KEY_PROV_INFO*/ KeyProvInfo = new Win32.CRYPT_KEY_PROV_INFO();
SafeNTHeapHandle pCertInfo = SafeNTHeapHandle.Null;
SafeStoreHandle hStore = SafeStoreHandle.Null;
SafeCertContextHandle pCertContext = SafeCertContextHandle.Null;
SafeNTHeapHandle pKeyProvInfo = SafeNTHeapHandle.Null;
// Variables
FileStream encodedFile = null;
EnvelopedLargeCMS cms = null;
X509Certificate2Collection recipients = null;
encodedFile = File.Open(EncryptedFile, FileMode.Open,FileAccess.Read, FileShare.Read);
cms = new EnvelopedLargeCMS();
Win32.CMSG_STREAM_INFO StreamInfo = new Win32.CMSG_STREAM_INFO();
// Check parameters
if (encodedFile == null)
{
throw new Exception("DecodeAndDecrypt error: Missing encoded file stream");
}
StreamInfo = Win32.CreateStreamInfo((int)encodedFile.Length, new Win32.StreamOutputCallbackDelegate(cms.StreamOutputCallback));
// Open message to encode
SafeMsgHandle hMsg = Win32.OpenMessageToDecode(StreamInfo);
try
{
// Variables
int BufSize = 1024 * 1024;
BinaryReader stream = null;
byte[] pbData = null;
long dwRemaining = 0;
bool bFinal = false;
bool bResult = false;
// Process message
dwRemaining = encodedFile.Length;
stream = new BinaryReader(encodedFile);
do
{
// Read one chunk of data
pbData = stream.ReadBytes(BufSize);
if (pbData.Length == 0)
{
break;
}
bFinal = (dwRemaining <= BufSize);
fixed (byte* pAux = &pbData[0])
{
bResult = Win32.CryptMsgUpdate(
hMsg.DangerousGetHandle(),
new IntPtr(pAux),
pbData.Length,
bFinal
);
if (!bResult)
{
throw new Exception("CryptMsgUpdate error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
else
{
Win32.CRYPT_ALGORITHM_IDENTIFIER AlgId = new Win32.CRYPT_ALGORITHM_IDENTIFIER();
SafeNTHeapHandle pEnvelopeAlg = SafeNTHeapHandle.Null;
try
{
// Get envelope encryption algorithm
Win32.GetMessageParam(hMsg, Win32.CMSG_ENVELOPE_ALGORITHM_PARAM, out pEnvelopeAlg);
AlgId = (Win32.CRYPT_ALGORITHM_IDENTIFIER)Marshal.PtrToStructure(pEnvelopeAlg.DangerousGetHandle(), typeof(Win32.CRYPT_ALGORITHM_IDENTIFIER));
if (AlgId.Parameters.cbData > 0)
{
try
{
// Get recipient cert
Win32.GetMessageParam(hMsg, Win32.CMSG_RECIPIENT_INFO_PARAM, out pCertInfo);
// Open personal cert store
hStore = Win32.CertOpenSystemStore(
IntPtr.Zero,
"MY"
);
if ((hStore == null) || (hStore.IsInvalid))
{
throw new Exception("CertOpenStore error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
// Find recipient cert in store
pCertContext = Win32.CertGetSubjectCertificateFromStore(
hStore,
Win32.X509_ASN_ENCODING | Win32.PKCS_7_ASN_ENCODING,
pCertInfo
);
if ((pCertContext == null) || (pCertContext.IsInvalid))
{
throw new Exception("CertGetSubjectCertificateFromStore error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
// Get key info for that cert
Win32.GetCertContextProperty(pCertContext, Win32.CERT_KEY_PROV_INFO_PROP_ID, out pKeyProvInfo);
KeyProvInfo = (Win32.CRYPT_KEY_PROV_INFO)Marshal.PtrToStructure(pKeyProvInfo.DangerousGetHandle(), typeof(Win32.CRYPT_KEY_PROV_INFO));
// Get CSP for that key
bResult = Win32.CryptAcquireContext(
out hProv,
KeyProvInfo.pwszContainerName,
KeyProvInfo.pwszProvName,
KeyProvInfo.dwProvType,
0
);
if (!bResult)
{
throw new Exception("CryptAcquireContext error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
// Prepare decryption
DecryptPara.cbSize = Marshal.SizeOf(DecryptPara);
DecryptPara.hCryptProvOrNCryptKey = hProv.DangerousGetHandle();
DecryptPara.dwKeySpec = KeyProvInfo.dwKeySpec;
DecryptPara.dwRecipientIndex = 0; // баг - нужно выставить правильный индекс
// MessageBox.Show(KeyProvInfo.pwszContainerName);
}
finally
{
// Clean up
pCertContext.Dispose();
hStore.Dispose();
pCertInfo.Dispose();
//hProv.Dispose(); // This is not needed. We get an AV when disposing the message handle if we do this now.
pKeyProvInfo.Dispose();
}
break;
}
}
finally
{
// Clean up
pEnvelopeAlg.Dispose();
}
}
}
dwRemaining = dwRemaining - pbData.Length;
} while (!bFinal);
}
finally
{
// Clean up
if (encodedFile != null) { encodedFile.Close(); }
if (cms != null) { cms.Dispose(); }
}
return DecryptPara.cbSize > 0;
}
GetCertToDecrypt - вызвать внутри, получить\показать информацию (в логе - какой CSP\Контейнер..) и вместо вызова Win32.Decrypt(hMsg) (в исходном коде largecms):
Код:
fixed (byte* pAux = &pbData[0])
{
bResult = CryptMsgUpdate(
hMsg.DangerousGetHandle(),
new IntPtr(pAux),
pbData.Length,
bFinal
);
if (!bResult)
{
throw new Exception("CryptMsgUpdate error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
else
{
CRYPT_ALGORITHM_IDENTIFIER AlgId = new CRYPT_ALGORITHM_IDENTIFIER();
SafeNTHeapHandle pEnvelopeAlg = SafeNTHeapHandle.Null;
try
{
GetMessageParam(hMsg, CMSG_ENVELOPE_ALGORITHM_PARAM, out pEnvelopeAlg);
AlgId = (CRYPT_ALGORITHM_IDENTIFIER)Marshal.PtrToStructure(pEnvelopeAlg.DangerousGetHandle(), typeof(CRYPT_ALGORITHM_IDENTIFIER));
if (AlgId.Parameters.cbData > 0)
{
bResult = CryptMsgControl(hMsg,0, CMSG_CTRL_DECRYPT, ref DecryptPara);
if (!bResult)
{
// throw new Exception("CryptMsgControl error #" + Marshal.GetLastWin32Error().ToString(), new Win32Exception(Marshal.GetLastWin32Error()));
}
// Win32.Decrypt(hMsg);
}
}
finally
{
// Clean up
pEnvelopeAlg.Dispose();
}
}
}
|
|