I've tried everything I found cross the web, but I couldn't figure out what is the problem. I have these methods to encrypt/decrypt strings:
public static class SecurityUtils {
public static readonly string EncryptionKey = "my.key." + Guid.NewGuid();
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
public static string Encrypt(this string stringToEncrypt, string key) {
if (string.IsNullOrEmpty(stringToEncrypt)) {
throw new ArgumentException("An empty string value cannot be encrypted.");
}
if (string.IsNullOrEmpty(key)) {
throw new ArgumentException("Cannot encrypt using an empty key. Please supply an encryption key.");
}
var cspp = new CspParameters { KeyContainerName = key, Flags = CspProviderFlags.UseMachineKeyStore };
var rsa = new RSACryptoServiceProvider(cspp) { PersistKeyInCsp = true };
byte[] bytes = rsa.Encrypt(System.Text.Encoding.UTF8.GetBytes(stringToEncrypt), true);
return BitConverter.ToString(bytes);
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Assert, Unrestricted = true)]
public static string Decrypt(this string stringToDecrypt, string key) {
if (string.IsNullOrEmpty(stringToDecrypt)) {
throw new ArgumentException("An empty string value cannot be encrypted.");
}
if (string.IsNullOrEmpty(key)) {
throw new ArgumentException("Cannot decrypt using an empty key. Please supply a decryption key.");
}
var cspp = new CspParameters { KeyContainerName = key, Flags = CspProviderFlags.UseMachineKeyStore };
var rsa = new RSACryptoServiceProvider(cspp) { PersistKeyInCsp = true };
var decryptArray = stringToDecrypt.Split(new[] { "-" }, StringSplitOptions.None);
var decryptByteArray = Array.ConvertAll(decryptArray, (s => Convert.ToByte(byte.Parse(s, System.Globalization.NumberStyles.HexNumber))));
byte[] bytes = rsa.Decrypt(decryptByteArray, true);
string result = System.Text.Encoding.UTF8.GetString(bytes);
return result;
}
}
I'm using this code for months in several projects and it seems perfect. Until a project I'm working on now. It works local just as I want to. But when I publish it to my server, I get this error:
Error occurred while decoding OAEP padding.
Stack Trace:
[CryptographicException: Error occurred while decoding OAEP padding.]
System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey) +0
System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP) +214
myNamespace.SecurityUtils.Decrypt(String stringToDecrypt, String key) +260
... the rest...
Do you have any idea please? Thanks in advance.
Related
I got "The account name or password that you have entered is incorrect" error when trying login using this api endpoint: https://steamcommunity.com/login/dologin/
I am using the credentials I use when logging in via Steam app or Steam web, so I don't think I have a problem with my credentials.
Here code which code I use:
public bool DoLogin(string username, string password)
{
var data = new NameValueCollection { { "username", username } };
// First get the RSA key with which we will encrypt our password.
string response = Fetch("https://steamcommunity.com/login/getrsakey", "POST", data, false);
GetRsaKey rsaJson = JsonConvert.DeserializeObject<GetRsaKey>(response);
// Validate, if we could get the rsa key.
if (!rsaJson.success)
{
return false;
}
// RSA Encryption.
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
RSAParameters rsaParameters = new RSAParameters
{
Exponent = HexToByte(rsaJson.publickey_exp),
Modulus = HexToByte(rsaJson.publickey_mod)
};
rsa.ImportParameters(rsaParameters);
// Encrypt the password and convert it.
byte[] bytePassword = Encoding.ASCII.GetBytes(password);
byte[] encodedPassword = rsa.Encrypt(bytePassword, false);
string encryptedBase64Password = Convert.ToBase64String(encodedPassword);
SteamResult loginJson = null;
CookieCollection cookieCollection;
string steamGuardText = "";
string steamGuardId = "";
// Do this while we need a captcha or need email authentification. Probably you have misstyped the captcha or the SteamGaurd code if this comes multiple times.
do
{
Console.WriteLine("SteamWeb: Logging In...");
bool captcha = loginJson != null && loginJson.captcha_needed;
bool steamGuard = loginJson != null && loginJson.emailauth_needed;
string time = Uri.EscapeDataString(rsaJson.timestamp);
string capGid = string.Empty;
// Response does not need to send if captcha is needed or not.
// ReSharper disable once MergeSequentialChecks
if (loginJson != null && loginJson.captcha_gid != null)
{
capGid = Uri.EscapeDataString(loginJson.captcha_gid);
}
data = new NameValueCollection { { "password", encryptedBase64Password }, { "username", username } };
// Captcha Check.
string capText = "";
if (captcha)
{
Console.WriteLine("SteamWeb: Captcha is needed.");
System.Diagnostics.Process.Start("https://steamcommunity.com/public/captcha.php?gid=" + loginJson.captcha_gid);
Console.WriteLine("SteamWeb: Type the captcha:");
string consoleText = Console.ReadLine();
if (!string.IsNullOrEmpty(consoleText))
{
capText = Uri.EscapeDataString(consoleText);
}
}
data.Add("captchagid", captcha ? capGid : "-1");
data.Add("captcha_text", captcha ? capText : "");
// Captcha end.
// Added Header for two factor code.
data.Add("twofactorcode", "");
// Added Header for remember login. It can also set to true.
data.Add("remember_login", "false");
// SteamGuard check. If SteamGuard is enabled you need to enter it. Care probably you need to wait 7 days to trade.
// For further information about SteamGuard see: https://support.steampowered.com/kb_article.php?ref=4020-ALZM-5519&l=english.
if (steamGuard)
{
Console.WriteLine("SteamWeb: SteamGuard is needed.");
Console.WriteLine("SteamWeb: Type the code:");
string consoleText = Console.ReadLine();
if (!string.IsNullOrEmpty(consoleText))
{
steamGuardText = Uri.EscapeDataString(consoleText);
}
steamGuardId = loginJson.emailsteamid;
// Adding the machine name to the NameValueCollection, because it is requested by steam.
Console.WriteLine("SteamWeb: Type your machine name:");
consoleText = Console.ReadLine();
var machineName = string.IsNullOrEmpty(consoleText) ? "" : Uri.EscapeDataString(consoleText);
data.Add("loginfriendlyname", machineName != "" ? machineName : "defaultSteamBotMachine");
}
data.Add("emailauth", steamGuardText);
data.Add("emailsteamid", steamGuardId);
// SteamGuard end.
// Added unixTimestamp. It is included in the request normally.
var unixTimestamp = (int)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
// Added three "0"'s because Steam has a weird unix timestamp interpretation.
data.Add("donotcache", unixTimestamp + "000");
data.Add("rsatimestamp", time);
// Sending the actual login.
using (HttpWebResponse webResponse = Request("https://steamcommunity.com/login/dologin/", "POST", data, false))
{
var stream = webResponse.GetResponseStream();
if (stream == null)
{
return false;
}
using (StreamReader reader = new StreamReader(stream))
{
string json = reader.ReadToEnd();
loginJson = JsonConvert.DeserializeObject<SteamResult>(json);
cookieCollection = webResponse.Cookies;
}
}
} while (loginJson.captcha_needed || loginJson.emailauth_needed);
// If the login was successful, we need to enter the cookies to steam.
if (loginJson.success)
{
_cookies = new CookieContainer();
foreach (Cookie cookie in cookieCollection)
{
_cookies.Add(cookie);
}
SubmitCookies(_cookies);
return true;
}
else
{
Console.WriteLine("SteamWeb Error: " + loginJson.message);
return false;
}
}
enter image description here
Is there another solution how to login to steam and get html?
Ok, so I checked your encrypting and it looks fine. It is a little bit of chaos in your code so i will explain it with my:
I prefer to use RestSharp and Newton Soft JSON to do this, so a little mandatory stuff in Class body:
private IRestClient restClientTemporary;
private string getKeysURL = "/login/getrsakey/";
private string loginWithKey = "/login/dologin/";
Create RestClient, and RestRequests:
restClientTemporary = new RestClient("https://steamcommunity.com");
var request = new RestRequest(getKeysURL, Method.POST);
request.AddParameter("username", "YourSteamLogin");
var resp = restClientTemporary.Execute(request);
GetRsaResult response = Newtonsoft.Json.JsonConvert.DeserializeObject<GetRsaResult>(resp.Content);
Then i used your code as method to encrypt:
public static string EncryptionSof(string password, GetRsaResult response)
{
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
RSAParameters rsaParameters = new RSAParameters
{
Exponent = HexToByte(response.publickey_exp),
Modulus = HexToByte(response.publickey_mod)
};
rsa.ImportParameters(rsaParameters);
// Encrypt the password and convert it.
byte[] bytePassword = Encoding.ASCII.GetBytes(password);
byte[] encodedPassword = rsa.Encrypt(bytePassword, false);
return Convert.ToBase64String(encodedPassword);
}
And then used this method:
string password = EncryptionSof("admin123/*its your steam password i think*/", response);
Next step is make request to get login data:
var loginRequest = new RestRequest(loginWithKey);
loginRequest.AddParameter("username", "YourSteamLogin");
loginRequest.AddParameter("password", password);
loginRequest.AddParameter("rsatimestamp", response.timestamp);
loginRequest.AddParameter("remember_login", false);
//Captcha stuff if needed:
loginRequest.AddParameter("captchagid", 3086601225255895896);
loginRequest.AddParameter("captcha_text", "LHYJ2P");
And finally execute it:
var responseFinal = restClientTemporary.Execute(loginRequest);
In response i received everything i need in responseFinal.Content:
{
"success":true,
"requires_twofactor":false,
"login_complete":true,
"transfer_urls":[
"https:\\/\\/store.steampowered.com\\/login\\/transfer",
"https:\\/\\/help.steampowered.com\\/login\\/transfer"
],
"transfer_parameters":{
"steamid":"12344567898765432",
"token_secure":"xDDDDDDDDD",
"auth":"LOOOOOL",
"remember_login":false
}
}
GetRsaResult model looks like:
public class GetRsaResult
{
public bool success { get; set; }
public string publickey_mod { get; set; }
public string publickey_exp { get; set; }
public string timestamp { get; set; }
public string token_gid { get; set; }
}
Ah, and i forget about changing 16-string to byte[], its method found on Stackoverflow:
public static byte[] HexToByte(string hex)
{
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
And you have to remember one thing You never want to send plaintext password to steam. First request /login/getrsakey/ is just only for get keys to encrypt password. Steam gives you key to encrypt your password. So, you will use your plaintext password (in my sample its admin123 ) in your program to encrypt it with keys you received from Steam.
In second request /login/dologin/ you must send encrypted password (result of EncryptionSoF method)
I am trying to walk through the sample code using the values in the "Example: Browser-Based Upload using HTTP POST (Using AWS Signature Version 4)" page, but could not get the same signature value posted on the page.
The page does not show the value for the signing key. Does anybody know what it supposed to be? Thanks.
namespace TestAWSSignature
{
class Program
{
// Values from aws example page.
const string aKey = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY";
const string anID = "AKIAIOSFODNN7EXAMPLE";
const string aRegion = "us-east-1";
const string aService = "s3";
const string aBucket = "sigv4examplebucket";
const string HMACSHA256 = "HMACSHA256";
const string aDate = "20151229";
const string SCHEME = "AWS4";
const string ALGORITHM = "HMAC-SHA256";
const string TERMINATOR = "aws4_request";
static void Main(string[] args)
{
// Initial to value from aws example page.
string base64PolicyString = "eyAiZXhwaXJhdGlvbiI6ICIyMDE1LTEyLTMwVDEyOjAwOjAwLjAwMFoiLA0KICAiY29uZGl0aW9ucyI6IFsNCiAgICB7ImJ1Y2tldCI6ICJzaWd2NGV4YW1wbGVidWNrZXQifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAidXNlci91c2VyMS8iXSwNCiAgICB7ImFjbCI6ICJwdWJsaWMtcmVhZCJ9LA0KICAgIHsic3VjY2Vzc19hY3Rpb25fcmVkaXJlY3QiOiAiaHR0cDovL3NpZ3Y0ZXhhbXBsZWJ1Y2tldC5zMy5hbWF6b25hd3MuY29tL3N1Y2Nlc3NmdWxfdXBsb2FkLmh0bWwifSwNCiAgICBbInN0YXJ0cy13aXRoIiwgIiRDb250ZW50LVR5cGUiLCAiaW1hZ2UvIl0sDQogICAgeyJ4LWFtei1tZXRhLXV1aWQiOiAiMTQzNjUxMjM2NTEyNzQifSwNCiAgICB7IngtYW16LXNlcnZlci1zaWRlLWVuY3J5cHRpb24iOiAiQUVTMjU2In0sDQogICAgWyJzdGFydHMtd2l0aCIsICIkeC1hbXotbWV0YS10YWciLCAiIl0sDQoNCiAgICB7IngtYW16LWNyZWRlbnRpYWwiOiAiQUtJQUlPU0ZPRE5ON0VYQU1QTEUvMjAxNTEyMjkvdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LA0KICAgIHsieC1hbXotYWxnb3JpdGhtIjogIkFXUzQtSE1BQy1TSEEyNTYifSwNCiAgICB7IngtYW16LWRhdGUiOiAiMjAxNTEyMjlUMDAwMDAwWiIgfQ0KICBdDQp9";
byte[] policyStringBytes = Convert.FromBase64String(base64PolicyString);
// compute the signing key
KeyedHashAlgorithm kha = KeyedHashAlgorithm.Create(HMACSHA256);
kha.Key = DeriveSigningKey(HMACSHA256, aKey, aRegion, aDate, aService);
Console.WriteLine(String.Format("Signing Key: {0}.\n", System.Convert.ToBase64String(kha.Key)));
// SigningKey value is: y87x6+rvyCzOZTC58KmuWYhGBl9cW64GdL1evEulLSg=
// Is this the correct value?
// Compute the signature.
byte[] signature = kha.ComputeHash(policyStringBytes);
string signatureString = ToHexString(signature, true);
Console.WriteLine(String.Format("Signature: {0}.\n", signatureString));
// The computed signature value is:
// 00e98ae3199cdbfeba701f9efa66510f23f0295ab6d6f4d14202f8ef2d11956c
// But according to the aws example page it should be:
// 8afdbf4008c03f22c2cd3cdb72e4afbb1f6a588f3255ac628749a66d7f09699e
Console.WriteLine("Done.");
}
// Functions below are straight from AWSSignatureV4-S3-Sample code.
/// Compute and return the multi-stage signing key for the request.
static byte[] DeriveSigningKey(string algorithm, string awsSecretAccessKey, string region, string date, string service)
{
const string ksecretPrefix = SCHEME;
char[] ksecret = null;
ksecret = (ksecretPrefix + awsSecretAccessKey).ToCharArray();
byte[] hashDate = ComputeKeyedHash(algorithm, Encoding.UTF8.GetBytes(ksecret), Encoding.UTF8.GetBytes(date));
byte[] hashRegion = ComputeKeyedHash(algorithm, hashDate, Encoding.UTF8.GetBytes(region));
byte[] hashService = ComputeKeyedHash(algorithm, hashRegion, Encoding.UTF8.GetBytes(service));
return ComputeKeyedHash(algorithm, hashService, Encoding.UTF8.GetBytes(TERMINATOR));
}
/// Compute and return the hash of a data blob using the specified algorithm and key
static byte[] ComputeKeyedHash(string algorithm, byte[] key, byte[] data)
{
var kha = KeyedHashAlgorithm.Create(algorithm);
kha.Key = key;
return kha.ComputeHash(data);
}
/// Helper to format a byte array into string
static string ToHexString(byte[] data, bool lowercase)
{
var sb = new StringBuilder();
for (var i = 0; i < data.Length; i++)
{
sb.Append(data[i].ToString(lowercase ? "x2" : "X2"));
}
return sb.ToString();
}
}
}
What should be the format (.pfx, .cer or something else) of the file here in the first parameter?
public X509Certificate2(
string fileName,
SecureString password,
X509KeyStorageFlags keyStorageFlags
)
More context :
I am getting following error while trying to get a certificate using the following function -
Function:
public static X509Certificate2 AuthenticationCertificate(string AuthenticationCertificateAsBase64String, string AuthenticationCertificatePassword)
{
if (!string.IsNullOrEmpty(AuthenticationCertificateAsBase64String) &&
AuthenticationCertificatePassword != null)
{
Console.WriteLine("AuthenticationCertificateAsBase64String: " + AuthenticationCertificateAsBase64String);
Console.WriteLine("AuthenticationCertificatePassword: " + AuthenticationCertificatePassword);
return new X509Certificate2(Convert.FromBase64String(AuthenticationCertificateAsBase64String),
AuthenticationCertificatePassword);
}
return null;
}
Error:
{System.Security.Cryptography.CryptographicException: The specified network password is not correct.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.X509Certificates.X509Utils._LoadCertFromBlob(Byte[] rawData, IntPtr password, UInt32 dwFlags, Boolean persistKeySet, SafeCertContextHandle& pCertCtx)
at System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromBlob(Byte[] rawData, Object password, X509KeyStorageFlags keyStorageFlags)
at System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(Byte[] rawData, String password)
at CryptoPlay.Program.AuthenticationCertificate(String AuthenticationCertificateAsBase64String, String AuthenticationCertificatePassword) in d:\personal\CryptoPlay\CryptoPlay\Program.cs:line 154
at CryptoPlay.Program.Main(String[] args) in d:\personal\CryptoPlay\CryptoPlay\Program.cs:line 59
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()}
The error indicates towards the password being not correct but that is not true. If someone is interested, here is the full code for reference (replacing the filenames and passwords to generic names as example)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography.Pkcs;
namespace CryptoPlay
{
class Program
{
static void Main(string[] args)
{
X509Certificate2 spCert = GetCertificateForUse();
X509Certificate2 encryptCert = GetCertificateUsedForEncryption();
string AuthenticationCertificatePasswordBase64String = EncryptAsBase64String(encryptCert, "Password1!");
Console.WriteLine("AuthenticationCertificatePasswordBase64String:");
Console.WriteLine(AuthenticationCertificatePasswordBase64String);
string AuthenticationCertificatePassword = DecryptFromBase64String(AuthenticationCertificatePasswordBase64String);
Console.WriteLine("AuthenticationCertificatePassword:");
Console.WriteLine(AuthenticationCertificatePassword);
string CertificateAsBase64String = EncryptAsBase64String(encryptCert, spCert);
Console.WriteLine("CertificateAsBase64String");
Console.WriteLine(CertificateAsBase64String);
byte[] rawdata = DecryptBytesFromBase64String(CertificateAsBase64String);
Console.WriteLine("Raw data: " + PrintBytes(rawdata));
string AuthenticationCertificateAsBase64String = Convert.ToBase64String(DecryptBytesFromBase64String(CertificateAsBase64String));
Console.WriteLine("AuthenticationCertificateAsBase64String:");
Console.WriteLine(AuthenticationCertificateAsBase64String);
byte[] rawdata2 = Convert.FromBase64String(AuthenticationCertificateAsBase64String);
Console.WriteLine("Raw data: " + PrintBytes(rawdata2));
if (ByteArrayCompare(rawdata, rawdata2))
Console.WriteLine("Raw data are same");
X509Certificate2 certFromConfig = AuthenticationCertificate(AuthenticationCertificateAsBase64String, AuthenticationCertificatePassword);
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static byte[] DecryptBytesFromBase64String(string payloadBase64String, X509Certificate2 decryptingCert = null)
{
try
{
var env = new EnvelopedCms();
env.Decode(Convert.FromBase64String(payloadBase64String));
if (decryptingCert != null)
{
env.Decrypt(new X509Certificate2Collection(decryptingCert));
}
else
{
env.Decrypt();
}
return env.ContentInfo.Content;
}
catch (Exception e)
{
throw new CryptographicException("Failed to decrypt: " + payloadBase64String, e);
}
}
public static string DecryptFromBase64String(string payloadBase64String, X509Certificate2 decryptingCert = null)
{
return Encoding.UTF8.GetString(DecryptBytesFromBase64String(payloadBase64String, decryptingCert));
}
public static string EncryptAsBase64String(X509Certificate2 cert, string payload)
{
return EncryptAsBase64String(cert, Encoding.UTF8.GetBytes(payload));
}
public static string EncryptAsBase64String(X509Certificate2 cert, byte[] payload)
{
var ci = new ContentInfo(payload);
var env = new EnvelopedCms(ci);
env.Encrypt(new CmsRecipient(cert));
return Convert.ToBase64String(env.Encode());
}
public static string EncryptAsBase64String(X509Certificate2 encryptingCert, X509Certificate2 payload)
{
byte[] bytes = payload.Export(X509ContentType.Pfx);
return EncryptAsBase64String(encryptingCert, bytes);
}
private static X509Certificate2 GetCertificateUsedForEncryption()
{
string certPath = "D:\\encryptcert.pfx";
string certPassword = "P#ssword123";
var cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.Exportable);
return cert;
}
private static X509Certificate2 GetCertificateForUse()
{
string certPath = "D:\\securecert.pfx";
string certPassword = "Password1!";
var cert = new X509Certificate2(certPath, certPassword, X509KeyStorageFlags.Exportable);
return cert;
}
public static X509Certificate2 AuthenticationCertificate(string AuthenticationCertificateAsBase64String, string AuthenticationCertificatePassword)
{
if (!string.IsNullOrEmpty(AuthenticationCertificateAsBase64String) &&
AuthenticationCertificatePassword != null)
{
Console.WriteLine("AuthenticationCertificateAsBase64String: " + AuthenticationCertificateAsBase64String);
Console.WriteLine("AuthenticationCertificatePassword: " + AuthenticationCertificatePassword);
return new X509Certificate2(Convert.FromBase64String(AuthenticationCertificateAsBase64String),
AuthenticationCertificatePassword);
}
return null;
}
public static string PrintBytes(byte[] byteArray)
{
var sb = new StringBuilder("new byte[] { ");
for (var i = 0; i < byteArray.Length; i++)
{
var b = byteArray[i];
sb.Append(b);
if (i < byteArray.Length - 1)
{
sb.Append(", ");
}
}
sb.Append(" }");
return sb.ToString();
}
static bool ByteArrayCompare(byte[] a1, byte[] a2)
{
if (a1.Length != a2.Length)
return false;
for (int i = 0; i < a1.Length; i++)
if (a1[i] != a2[i])
return false;
return true;
}
}
}
Your initial question is about the overloads which take a string as the first parameter, but your code uses the ones that use byte[].
The easy answer is that the string one is just a filename to load as a byte array and then call the other one (it's a bit more nuanced than that, e.g. the file one doesn't like symbolic links).
The following types are known (by me) to work:
PFX/PKCS#12, DER-encoded
X.509 certificate, DER encoded
X.509 certificate, PEM+DER encoded (-----BEGIN CERTIFICATE-----\n[etc]\n-----END CERTIFICATE-----)
PKCS#7 ContentInfo(SignedData), BER encoded (uses the embedded certificate identified by the first signer)
PKCS#7 ContentInfo(SignedData), PEM+BER encoded (-----BEGIN PKCS7-----\n...) (uses the embedded certificate identified by the first signer)
Authenticode-signed files (.exe, .dll, .msi, .msp, ...) (it uses the certificate of the first signer)
Whether or not you pass in a password has no bearing on what file format the blob gets identified as. Unless your profile or temp directory is on a SMB/CIFS share, Windows reporting ERROR_BAD_PASSWORD means it thinks your bytes represented a PFX, but that the PFX MAC could not be validated using the input password as the key. I'd recommend checking your password variable for embedded newline or linefeed characters (or nulls); or leading or trailing spaces.
I don't have deep information about cryptography ,but as I gathered some information,as an asymmetric solution I want to use RSA and here is the code which I found,I want to store an encrypted password into database and decrypt it whenever I want to get the user information,I mean these two actions don't happen respectively and whenever I like I can select from database and decrypt the previously save data.I know that there is something wrong with the generated keys,but because of low knowledge on this subject I cannot handle it.
I get the following Exception on decryption.
The parameter is incorrect.
at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
at System.Security.Cryptography.RSACryptoServiceProvider.DecryptKey(SafeKeyHandle pKeyContext, Byte[] pbEncryptedKey, Int32 cbEncryptedKey, Boolean fOAEP, ObjectHandleOnStack ohRetDecryptedKey)
at System.Security.Cryptography.RSACryptoServiceProvider.Decrypt(Byte[] rgb, Boolean fOAEP)
Encryption Class:
public static class AsymmetricEncryption
{
private static bool _optimalAsymmetricEncryptionPadding = false;
public static void GenerateKeys(int keySize, out string publicKey, out string publicAndPrivateKey)
{
using (var provider = new RSACryptoServiceProvider(keySize))
{
publicKey = provider.ToXmlString(false);
publicAndPrivateKey = provider.ToXmlString(true);
}
}
public static string EncryptText(string text, int keySize, string publicKeyXml)
{
var encrypted = Encrypt(Encoding.UTF8.GetBytes(text), keySize, publicKeyXml);
return Convert.ToBase64String(encrypted);
}
public static byte[] Encrypt(byte[] data, int keySize, string publicKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
int maxLength = GetMaxDataLength(keySize);
if (data.Length > maxLength) throw new ArgumentException(String.Format("Maximum data length is {0}", maxLength), "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicKeyXml)) throw new ArgumentException("Key is null or empty", "publicKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicKeyXml);
return provider.Encrypt(data, _optimalAsymmetricEncryptionPadding);
}
}
public static string DecryptText(string text, int keySize, string publicAndPrivateKeyXml)
{
var decrypted = Decrypt(Convert.FromBase64String(text), keySize, publicAndPrivateKeyXml);
return Encoding.UTF8.GetString(decrypted);
}
public static byte[] Decrypt(byte[] data, int keySize, string publicAndPrivateKeyXml)
{
if (data == null || data.Length == 0) throw new ArgumentException("Data are empty", "data");
if (!IsKeySizeValid(keySize)) throw new ArgumentException("Key size is not valid", "keySize");
if (String.IsNullOrEmpty(publicAndPrivateKeyXml)) throw new ArgumentException("Key is null or empty", "publicAndPrivateKeyXml");
using (var provider = new RSACryptoServiceProvider(keySize))
{
provider.FromXmlString(publicAndPrivateKeyXml);
return provider.Decrypt(data, _optimalAsymmetricEncryptionPadding);
}
}
public static int GetMaxDataLength(int keySize)
{
if (_optimalAsymmetricEncryptionPadding)
{
return ((keySize - 384) / 8) + 7;
}
return ((keySize - 384) / 8) + 37;
}
public static bool IsKeySizeValid(int keySize)
{
return keySize >= 384 &&
keySize <= 16384 &&
keySize % 8 == 0;
}
}
Encrypt usage:
const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.EncryptText(text, keySize, publicKey);
Decrypt usage:
const int keySize = 1024;
string publicAndPrivateKey;
string publicKey;
AsymmetricEncryption.GenerateKeys(keySize, out publicKey, out publicAndPrivateKey);
string text = "text for encryption";
string encrypted = AsymmetricEncryption.DecryptText(text, keySize, publicKey);
I read the encrypted text from a table.And I like to decrypt it.
Please help me solve this issue.
Thanks in advance
Snippet link
Let me stop you right here, before you actually figure out the exception.
IT IS A HORRIBLE IDEA TO STORE PASSWORDS REVERSIBLY, regardless what encryption you use. There are memory scrubbers and a million other problems with that scheme.
Passwords are to be HASHED, NOT ENCRYPTED. The difference is that hashes are hard to reverse if implemented properly. Use BCrypt or SHA2 or SHA3 or some other good hashing algorithms, use proper salt.
Here's an example, but consult someone knowledgeable before using in production, I may have bugs, the methods are coded for simplicity and may be too simple:
public string GetHash(string secret, string salt = null)
{
var hasher = SHA256Managed.Create();
salt = salt ?? Guid.NewGuid().ToString("N"); // 128 bit salt
var hashResult = hasher.ComputeHash(Encoding.UTF8.GetBytes(salt+"|"+what));
return "SHA256|" + salt + "|" + Convert.ToBase64String(hashResult);
}
Now you can store the string you get from this function in your DB and the next time a password comes in (over HTTPS, I hope) you can check it by getting the salt from the string stored in DB:
public bool CheckSecretHash(string secret, string hashFromDB){
var hashParts = hashFromDB.Split('|'); // string[3]
var rehash = GetHash(secret, hashParts[1]);
return hashFromDB == rehash;
}
Bonus points: challenge-response. ALWAYS USE HTTPS.
in c#
public static string HashToString(string message, byte[] key)
{
byte[] b=new HMACSHA512(key).ComputeHash(Encoding.UTF8.GetBytes(message));
return Convert.ToBase64String(b);
}
client.DefaultRequestHeaders.Add("X-Hash", hash);
var encryptedContent = DataMotion.Security.Encrypt(key, Convert.FromBase64String(iv), serializedModel);
var request = client.PostAsync(ApiUrlTextBox.Text,encryptedContent,new JsonMediaTypeFormatter());
in java:
protected String hashToString(String serializedModel, byte[] key) {
String result = null;
Mac sha512_HMAC;
try {
sha512_HMAC = Mac.getInstance("HmacSHA512");
SecretKeySpec secretkey = new SecretKeySpec(key, "HmacSHA512");
sha512_HMAC.init(secretkey);
byte[] mac_data = sha512_HMAC.doFinal(serializedModel.getBytes("UTF-8"));
result = Base64.encodeBase64String(mac_data);
}catch(Exception e){
}
}
o/p: ye+AZPqaKrU14pui4U5gBCiAbegNvLVjzVdGK3rwG9QVzqKfIgyWBDTncORkNND3DA8jPba5xmC7B5OUwZEKlQ==
i have written hashtostring method in java based on c# code. is this currect? (output is different because every time process is dynamic in both cases.)
With different C# encoding
public static string SHA512_ComputeHash(string text, string secretKey)
{
var hash = new StringBuilder(); ;
byte[] secretkeyBytes = Encoding.UTF8.GetBytes(secretKey);
byte[] inputBytes = Encoding.UTF8.GetBytes(text);
using (var hmac = new HMACSHA512(secretkeyBytes))
{
byte[] hashValue = hmac.ComputeHash(inputBytes);
foreach (var theByte in hashValue)
{
hash.Append(theByte.ToString("x2"));
}
}
return hash.ToString();
}
Both java and C# code are giving same result(same hash code). You should check again.
Replace following line in java code at end
result = Base64.getEncoder().encodeToString(mac_data);
In c#
public static string HMACSHA512(this string Key, string TextToHash)
{
string HmacHashed = "";
if (string.IsNullOrEmpty(Key))
throw new ArgumentNullException("HMACSHA512: Key", "Parameter cannot be empty.");
if (string.IsNullOrEmpty(TextToHash))
throw new ArgumentNullException("HMACSHA512: TextToHash", "Parameter cannot be empty.");
if (Key.Length % 2 != 0 || Key.Trim().Length < 2)
{
throw new ArgumentNullException("HMACSHA512: Key", "Parameter cannot be odd or less than 2 characters.");
}
try
{
using (var HMACSHA512 = new HMACSHA512(Encoding.ASCII.GetBytes(Key)))
{
HmacHashed = BitConverter.ToString(HMACSHA512.ComputeHash(Encoding.ASCII.GetBytes(TextToHash))).Replace("-", string.Empty);
}
return HmacHashed;
}
catch (Exception ex)
{
throw new Exception("HMACSHA512: " + ex.Message);
}
}