- Remove From My Forums
-
Question
-
User411292362 posted
Dear Experts
Thanx for reply.I gor idea from that links.One more doubt when i decrypt the ecncrypt string using auto generate key its showing error as
System.Security.Cryptography.CryptographicException: Bad Data.I give the my function
private
void DecryptFunctionINGData(){
try
{
string strEncrypt =
«9FEDAB741C3B085859D22FB1DDE46F32»;
// Encrypt stringTripleDESCryptoServiceProvider tdes =
new TripleDESCryptoServiceProvider();tdes.Key = Encoding.UTF8.GetBytes(«NlQr7tt/AJE/i/mVmI6TRg==»);
// AutoGenerate Key
tdes.Mode = CipherMode.ECB;
tdes.Padding = PaddingMode.PKCS7;
ICryptoTransform crypt = tdes.CreateDecryptor();
byte[] cipher = FromHex(strEncrypt);
byte[] plain = crypt.TransformFinalBlock(cipher, 0, cipher.Length);
// Here Error showing
Response.Write(«Decryped string : « + System.Text.Encoding.UTF8.GetString(plain) +
«<br/>»);}
catch (Exception ex)
{
Response.Write(ex.Message);
}
}
I would appreciate some help
Thanx & Regards
Mani
Answers
-
User717210030 posted
Hi,thanigaimaniveena
Do you know how the data encrypted by java: code and the name of Cryptography Arithmetic ?
Both c# and java implement the same arithmetic, but with some kind of difference in using of parameter.
Here is a example, data encrypt by c# and encrypted by java:
Data encrypted by c#
public static string Encrypt(string message, string key)
{
DES des = new DESCryptoServiceProvider();
des.Key = Encoding.UTF8.GetBytes(key);
des.IV = Encoding.UTF8.GetBytes(key);byte[] bytes = Encoding.UTF8.GetBytes(message);
byte[] resultBytes = des.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length);return Convert.ToBase64String(resultBytes);
}
Data encrupted by Java:
public static byte[] desEncrypt(String message, String key) throws Exception {
Cipher cipher = Cipher.getInstance(«DES/CBC/PKCS5Padding«);DESKeySpec desKeySpec
= new DESKeySpec(key.getBytes(«UTF-8«));
SecretKeyFactory keyFactory
= SecretKeyFactory.getInstance(«DES«);
SecretKey secretKey = keyFactory.generateSecret(desKeySpec);
IvParameterSpec iv = new IvParameterSpec(key.getBytes(«UTF-8»));
cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);return cipher.doFinal(message.getBytes(«UTF-8«));
}
Check this difference between the different ways;
Regards
-
Marked as answer by
Thursday, October 7, 2021 12:00 AM
-
Marked as answer by
yamaoto |
|
Статус: Новичок Группы: Участники
|
При попытке получения доступа к секретному ключу происходит ошибка: А именно в том случае если код запущен в сервисе WCF внутри ASP.NET сайта. Тот же код запущенный от имени пользователя с консоли работает прекрасно Пробовал получить доступ как из хранилища сертификатов стандартными как средствами Код:
так и через Gost3410CryptoServiceProvider Код:
Сертификаты установлены в хранилище компьютера (проверял кучу раз) в ветке реестра нет чего-либо Код:
а в ветке Код:
есть разделы KeyDevices и Random Параметры системы:
|
|
|
Андрей Писарев |
|
Статус: Сотрудник Группы: Участники Сказал «Спасибо»: 451 раз |
Криптопровайдер от ОАО «Информационные Технологии и Коммуникационные Системы» — обязателен? |
Техническую поддержку оказываем тут |
|
|
WWW |
yamaoto |
|
Статус: Новичок Группы: Участники
|
Автор: Андрей * Криптопровайдер от ОАО «Информационные Технологии и Коммуникационные Системы» — обязателен? Да, обязателен. Проблемы могут быть из-за его несовместимости с КриптоПро? |
|
|
yamaoto |
|
Статус: Новичок Группы: Участники
|
Попробовали запустить на новой машине MS WS2008R2 Standard x64 en без VipNet’a SecretNet Код:
ключ находится в реестре компьютера, сертификат тоже установлен в «личное» компьютера скриншот сертификатов: проверка сертификата: Код:
|
|
|
Максим Коллегин |
|
Статус: Сотрудник Группы: Администраторы Сказал «Спасибо»: 21 раз |
Дайте учетке IIS полный доступ к контейнеру ключей. Обсуждалось неоднократно. |
Знания в базе знаний, поддержка в техподдержке |
|
|
WWW |
Максим Коллегин |
|
Статус: Сотрудник Группы: Администраторы Сказал «Спасибо»: 21 раз |
Написал статью в FAQ |
Знания в базе знаний, поддержка в техподдержке |
|
|
WWW |
STP |
|
Статус: Новичок Группы: Участники
|
Коллеги, у меня аналогичная проблема ПО: Замечания: Какие могут быть мыли как это исправить? |
|
|
Максим Коллегин |
|
Статус: Сотрудник Группы: Администраторы Сказал «Спасибо»: 21 раз |
Автор: STP Поигравшись выяснил, что есть баг в КП CSP 3.6 КС2 при назначении прав на закрытые ключи. Какие могут быть мыли как это исправить? Какая версия CSP 3.6? В 3.9 пробовали? |
Знания в базе знаний, поддержка в техподдержке |
|
|
WWW |
STP |
|
Статус: Новичок Группы: Участники
|
Версия КП CSP 3.6.6497 КС2 (СКЗИ 3.6.5359), данная версия нам задана в рамках большего проекта по внедрению уц. |
|
|
alexvg75 |
|
Статус: Новичок Группы: Участники
|
Доброго дня! |
|
|
Пользователи, просматривающие эту тему |
Guest |
Быстрый переход
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.
Raymond
articleArticles 549
imageDiagrams 49
codeCode 3
chat_bubble_outlineThreads 8
commentComments 265
loyaltyKontext Points 6055
account_circle Profile
visibility 4,447
event 2021-08-24
access_time 2 years ago
language English
more_vert
When it comes to protect data, one direct way is to encrypt it by adopting certain cryptographic algorithm. In .NET, there are many encryption or decryption algorithms available to use. Like storing secrets in a container with a key, you don’t want to expose that key to anyone else if you want to keep the secrets. In .NET Core or f.NET 5/6, data protection system provides quite a few approaches to secure the private key.
Different ways to secure the keys
On Azure, we can store the keys in Azure Key Vault; in other applications, we can persist the key to a disk that cannot be accessed by others. You can also upload the keys to a database via EntityFramework via DbContext so that only users who have access to the database can access the private key and use it to encrypt or decrypt messages.
The following is one example:
services.AddDataProtection() .PersistKeysToDbContext<ApplicationDbContext>() .SetDefaultKeyLifetime(TimeSpan.FromDays(180));
The payload was invalid error
Exceptions can be thrown out using the above code snippet:
System.Security.Cryptography.CryptographicException: The payload was invalid. at Microsoft.AspNetCore.DataProtection.Cng.CbcAuthenticatedEncryptor.DecryptImpl(Byte* pbCiphertext, UInt32 cbCiphertext, Byte* pbAdditionalAuthenticatedData, UInt32 cbAdditionalAuthenticatedData) at Microsoft.AspNetCore.DataProtection.Cng.Internal.CngAuthenticatedEncryptorBase.Decrypt(ArraySegment`1 ciphertext, ArraySegment`1 additionalAuthenticatedData) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.UnprotectCore(Byte[] protectedData, Boolean allowOperationsOnRevokedKeys, UnprotectStatus& status) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.DangerousUnprotect(Byte[] protectedData, Boolean ignoreRevocationErrors, Boolean& requiresMigration, Boolean& wasRevoked) at Microsoft.AspNetCore.DataProtection.KeyManagement.KeyRingBasedDataProtector.Unprotect(Byte[] protectedData)
Root causes
There are usually two typical causes for the above exception:
- Private key is not persisted thus if the value was encrypted with a key from one instance, it cannot be decrypted using the current key.
- Application name is not set.
Since we are persisting the keys to a database, the latter is the root cause.
Fix the problem
To fix the problem, we just need to call SetApplicationName function to ensure the application name is not consistent among different runs. If it is not specified, a random application name will be used and even if the key is the same the payload cannot be decrypted.
services.AddDataProtection() .PersistKeysToDbContext<ApplicationDbContext>() .SetApplicationName("YourAppName") .SetDefaultKeyLifetime(TimeSpan.FromDays(180));
References
Configure ASP.NET Core Data Protection | Microsoft Docs
I am getting error when the system tries to decrypt the data.
Below is the code I am using to encrypt and decrypt the data. Is there any issue with the code ?
Can anyone help me out in this issue ?
Any help will be appreciated
Stack Trace:
<?xml version=»1.0″ encoding=»utf-16″?>
<error host=»localhost» type=»System.Security.Cryptography.CryptographicException»
message=»Bad Data. »
source=»mscorlib»
detail=»System.Web.HttpUnhandledException: Exception of type ‘System.Web.HttpUnhandledException’ was thrown.
System.Exception: Bad Data.
System.Security.Cryptography.CryptographicException: Bad Data.
at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
at System.Security.Cryptography.Utils._DecryptData(SafeKeyHandle hKey, Byte[] data, Int32 ib, Int32 cb, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode PaddingMode, Boolean fDone)
at System.Security.Cryptography.CryptoAPITransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
CODE:
public static string Decrypt(string stringToDecrypt, string sEncryptionKey)
{
byte[] IV = { 10, 20, 30, 40, 50, 60, 70, 80 };
//Private IV() As Byte = {&H12, &H34, &H56, &H78, &H90, &HAB, &HCD, &HEF}
byte[] inputByteArray;
try
{
byte[] key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
inputByteArray = Convert.FromBase64String(stringToDecrypt);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(key, IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
Encoding encoding = Encoding.UTF8;
return encoding.GetString(ms.ToArray());
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public static string Encrypt(string stringToEncrypt, string sEncryptionKey)
{
byte[] IV = { 1, 2, 3, 4, 5, 6, 7, 8 };
byte[] inputByteArray; //Convert.ToByte(stringToEncrypt.Length)
try
{
byte[] key = Encoding.UTF8.GetBytes(sEncryptionKey.Substring(0, 8));
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
inputByteArray = Encoding.UTF8.GetBytes(stringToEncrypt);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(key, IV), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
return Convert.ToBase64String(ms.ToArray());
}
catch (Exception ex)
{
throw new Exception(ex.Message, ex);
}
}
public static string encryptString(string strToEncrypt)
{
UTF8Encoding ue = new UTF8Encoding();
byte[] bytes = ue.GetBytes(strToEncrypt);
// encrypt bytes
MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
byte[] hashBytes = md5.ComputeHash(bytes);
// Convert the encrypted bytes back to a string (base 16)
string hashString = «»;
for (int i = 0; i < hashBytes.Length; i++)
{
hashString += Convert.ToString(hashBytes[i], 16).PadLeft(2, ‘0’);
}
return hashString.PadLeft(32, ‘0’);
}
Regards,
Parth
In the scenario described in this post, you have encountered an error in your log that says the following:
Signing certificate has not private key or private key is not accessible. Make sure the account running your application has access to the private key
TL;DR; See how to convert your certificate key from CNG to RSA
Or maybe your haven’t seen this error message but have encountered an issue with Identity Server signing it tokens. If this is the case, I would highly recommend you stop and enable logging before you go any further, restart your application and check your logs for the error message above. Logging is key, we need to see what is going on in order to know how to fix it! Jump ahead to Enabling Logging in Identity Server V3 then come back to find out what the error is all about.
Assumptions
Now, this article assumes you have checked some of the obvious things. Run through the following list and if the answer is “Yes!” for every question then you may proceed 🙂
- Have you checked that the certificate you are using actually has a private key?
- Have you checked that the password you are using to access the private key is correct?
- Have you checked that the account your application is running under has permissions to access to the private key?
OK, so you have answered yes to all of these questions – so it is maybe beginning to be more likely that you are falling foul of a Cng Key issue.
What is a CNG Key?
Certificates in Windows are stored using Storage Providers. Windows has two of these providers, that are not compatible. The old style “Cryptographic Service Providers” or CSP in short and the new style “Cryptography API: Next Generation” or CNG. The CNG providers have been around since Windows Vista, and although it is more secure and easier to use many facets of software are still not compatible with CNG providers. This appears to also include the .NET Framework.
A possible workaround to this may be to use CryptoAPI/CNG API directly to deal with CNG keys. But if we want an easier and pure .NET solution which understands CNG, we need to find another solution (details to follow!).
How was my PFX file generated?
In this case, I used the powershell module New-SelfSignedCertificate to generate a self-signed certificate and then exported that certificate to a PFX file via the Management Console.
Proving out the issue
So let’s investigate what’s causing the “Signing certificate has not private key or private key is not accessible” error.
To help me figure this out, I created the following test stub which I used to load a certificate (from an embedded resource in this case) and attempt to access the private key.
using System; using System.IO; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using IdentityServer3.Core.Logging; using Security.Cryptography.X509Certificates; public class Certificate { private readonly static ILog Logger = LogProvider.For<Certificate>(); public static X509Certificate2 Load() { var assembly = typeof(Certificate).Assembly; using (var stream = assembly.GetManifestResourceStream("TestApp.MyCert.pfx")) { var file = Path.Combine(Path.GetTempPath(), "TestApp-" + Guid.NewGuid()); Logger.DebugFormat("Loading certificate from {0}", file); try { File.WriteAllBytes(file, ReadStream(stream)); var cert = new X509Certificate2(file, "MyReallyStrongPassword", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.Exportable); Logger.DebugFormat("Certificate Has Private Key: {0}", cert.HasPrivateKey); Logger.DebugFormat("Is Private Access Allowed: {0}", IsPrivateAccessAllowed(cert)); return cert; } finally { File.Delete(file); } } } private static byte[] ReadStream(Stream input) { var buffer = new byte[16 * 1024]; using (var ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } public static bool IsPrivateAccessAllowed(X509Certificate2 cert) { try { var privateKey = cert.PrivateKey; return true; } catch (CryptographicException ex) { Logger.ErrorException("Error accessing private key", ex); return false; } } }
Running this code results in the following entries in my log file
2016-05-11 15:56:45.473 +01:00 [Debug] Loading certificate from "C:WindowsTEMPTestApp-845cfe9c-a0d3-4bc7-bde1-53727c3c81c9" 2016-05-11 15:56:45.495 +01:00 [Debug] Certificate Has Private Key: True 2016-05-11 15:56:45.497 +01:00 [Debug] Is Private Access Allowed: False
Closer inspection of the error thrown when accessing the private key revealed the following exception being thrown.
System.Security.Cryptography.CryptographicException: Invalid provider type specified.
at System.Security.Cryptography.Utils.CreateProvHandle(CspParameters parameters, Boolean randomKeyContainer)
at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle& safeProvHandle, SafeKeyHandle& safeKeyHandle)
at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
at System.Security.Cryptography.X509Certificates.X509Certificate2.get_PrivateKey()
Now we seem to be getting somewhere!
GoogleFoo resulted in me discovering Alejandro Magencio’s blog post on this very exception. His post describes in detail the background to what is going on underneath the covers and why we are getting this exception.
In short, the .NET Framework being used does not like CNG keys. In order access them we need to either talk directly to the CryptoAPI/CNG API or we could use the CLR Security open source library.
Adding in usage of the CLR Security library allows me to interogate the type of private key that my certificate has.
using System; using System.IO; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using IdentityServer3.Core.Logging; using Security.Cryptography.X509Certificates; public class Certificate { private readonly static ILog Logger = LogProvider.For<Certificate>(); public static X509Certificate2 Load() { var assembly = typeof(Certificate).Assembly; using (var stream = assembly.GetManifestResourceStream("TestApp.MyCert.pfx")) { var file = Path.Combine(Path.GetTempPath(), "TestApp-" + Guid.NewGuid()); Logger.DebugFormat("Loading certificate from {0}", file); try { File.WriteAllBytes(file, ReadStream(stream)); var cert = new X509Certificate2(file, "MyReallyStrongPassword", X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.UserKeySet | X509KeyStorageFlags.Exportable); Logger.DebugFormat("Certificate Has Private Key: {0}", cert.HasPrivateKey); Logger.DebugFormat("HasCngKey: {0}", cert.HasCngKey()); Logger.DebugFormat("Is Private Access Allowed: {0}", IsPrivateAccessAllowed(cert)); return cert; } finally { File.Delete(file); } } } private static byte[] ReadStream(Stream input) { var buffer = new byte[16 * 1024]; using (var ms = new MemoryStream()) { int read; while ((read = input.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, read); } return ms.ToArray(); } } public static bool IsPrivateAccessAllowed(X509Certificate2 cert) { try { if (cert.HasCngKey()) { var privateKey = cert.GetCngPrivateKey(); } else { var privateKey = cert.PrivateKey; } return true; } catch (CryptographicException ex) { Logger.ErrorException("Error accessing private key", ex); return false; } } }
Which results in the following entries in my log file.
2016-05-11 15:56:45.473 +01:00 [Debug] Loading certificate from "C:WindowsTEMPTestApp-845cfe9c-a0d3-4bc7-bde1-53727c3c81c9" 2016-05-11 15:56:45.495 +01:00 [Debug] Certificate Has Private Key: True 2016-05-11 15:56:45.495 +01:00 [Debug] HasCngKey: True 2016-05-11 15:56:45.497 +01:00 [Debug] Is Private Access Allowed: True
This is great, but I would prefer to not have to code my way out of this. I would rather have a certificate in a format that can be readily accessed by my .NET code. So, let’s convert my certificate private key from CNG to RSA.
Converting your certificate key from CNG to RSA
Steps:
- Extract your public key and full certificate chain from your PFX file
- Extract the CNG private key
- Convert the private key to RSA format
- Merge public keys with RSA private key to a new PFX file
After changing your application to use the new PFX you just created, you should find that your issues have been resolved.
Now let’s see how to carry out these steps using OpenSSL (Get OpenSSL for Windows from here)
1. Extract your public key and full certificate chain from your PFX file
OpenSSL pkcs12 -in “yourcertificate.pfx” -nokeys -out “yourcertificate.cer” -passin “pass:myreallystrongpassword”
2. Extract the CNG private key
OpenSSL pkcs12 -in “yourcertificate.pfx” -nocerts –out “yourcertificate.pem” -passin “pass:myreallystrongpassword” -passout “pass:myreallystrongpassword”
3. Convert the private key to RSA format
OpenSSL rsa -inform PEM -in “yourcertificate.pem” -out “yourcertificate.rsa” -passin “pass:myreallystrongpassword” -passout “pass:myreallystrongpassword”
4. Merge public keys with RSA private key to a new PFX file
OpenSSL pkcs12 -export -in “yourcertificate.cer” -inkey “yourcertificate.rsa” -out “yourcertificate-converted.pfx” -passin “pass:myreallystrongpassword” -passout “pass:myreallystrongpassword”
Enabling Logging in Identity Server
Identity Server v3 provides a wealth of information to developers through it’s two logging features. Development time logging provides really low level details to assist developers diagnose issues during development and testing. Production-time logging comes in the form of a number of events being raised to assist in system monitoring and fault diagnosis. The reason there are two levels of logging is that it is possible that sensitive information may be exposed through development logging and this facility should therefor always be disabled when the system is in production.
To enable logging with Identity Server v3,
- Configure the logging framework of choice.
For example, you could configure Serilog via the following statement:
Log.Logger = new LoggerConfiguration() .MinimumLevel.Debug() .WriteTo.Trace() .CreateLogger();
- Configure Identity Server Logging settings
Here is a full list of the logging settings available for Identity Server V3.
var options = new IdentityServerOptions { LoggingOptions = new LoggingOptions() { EnableHttpLogging = true, EnableKatanaLogging = true, EnableWebApiDiagnostics = true, WebApiDiagnosticsIsVerbose = true }, EventsOptions = new EventsOptions() { RaiseInformationEvents = true, RaiseErrorEvents = true, RaiseFailureEvents = true, RaiseSuccessEvents = true, } };
- Enable Diagnostic Logging in your application configuration file
For example
<system.diagnostics> <trace autoflush="true" indentsize="4"> <listeners> <add name="myTraceListener" type="System.Diagnostics.TextWriterTraceListener" initializeData="Trace.log" /> <remove name="Default" /> </listeners> </trace> </system.diagnostics>
As is also recommended by the developers of Identity Server, I use BareTail to provide me with a great view of my log files.
For more details on Identity Server logging configuration, see the official Identity Server v3 documentation
Now that you have configured logging, build and rerun your application and confirm that a log file is being created. Then check the log file for error. You may now wish to return to reading about the certificate error upon which this post is based.