Google KMS giving error when decrypting data - c#

When i try to decrypt my data using the Google KMS i am getting this error. Below is my code for the decryption. The error is hitting on the line where there is string plaintext. Thanks in advance
Code
public static string Encrypt(string plaintext)
{
KeyManagementServiceClient client = KeyManagementServiceClient.Create();
//projects/progforthecloudt2020/locations/global/keyRings/pfckeyring001/cryptoKeys/pfckeys
CryptoKeyName kn = CryptoKeyName.FromUnparsed(new
Google.Api.Gax.UnparsedResourceName("GOOGLE RESOURCE ID REMOVED"));
string cipher = client.Encrypt(kn, ByteString.CopyFromUtf8(plaintext)).Ciphertext.ToBase64();
return cipher;
}
public static string Decrypt(string cipher)
{
KeyManagementServiceClient client = KeyManagementServiceClient.Create();
CryptoKeyName kn = CryptoKeyName.FromUnparsed(new Google.Api.Gax.UnparsedResourceName("GOOGLE RESOURCE ID REMOVED"));
string plaintext = client.Decrypt(kn, ByteString.CopyFromUtf8(cipher)).Plaintext.ToBase64();
return plaintext;
}
Error
Grpc.Core.RpcException: 'Status(StatusCode=InvalidArgument, Detail="Decryption failed: the ciphertext is invalid.")'

You’re base64 encoding the result of your encryption call, but then you aren’t base64 decoding it in your decrypt call. You shouldn’t need to base64 encode the data.
public static void Encrypt(string projectId, string locationId, string keyRingId, string cryptoKeyId, string plaintextFile, string ciphertextFile)
{
KeyManagementServiceClient client = KeyManagementServiceClient.Create();
CryptoKeyName cryptoKeyName =
new CryptoKeyName(projectId, locationId, keyRingId, cryptoKeyId);
byte[] plaintext = File.ReadAllBytes(plaintextFile);
EncryptResponse result = client.Encrypt(cryptoKeyName, ByteString.CopyFrom(plaintext));
// Output encrypted data to a file.
File.WriteAllBytes(ciphertextFile, result.Ciphertext.ToByteArray());
Console.Write($"Encrypted file created: {ciphertextFile}");
}
public static void Decrypt(string projectId, string locationId, string keyRingId, string cryptoKeyId, string ciphertextFile, string plaintextFile)
{
KeyManagementServiceClient client = KeyManagementServiceClient.Create();
CryptoKeyName cryptoKeyName =
new CryptoKeyName(projectId, locationId, keyRingId, cryptoKeyId);
byte[] ciphertext = File.ReadAllBytes(ciphertextFile);
DecryptResponse result = client.Decrypt(cryptoKeyName, ByteString.CopyFrom(ciphertext));
// Output decrypted data to a file.
File.WriteAllBytes(plaintextFile, result.Plaintext.ToByteArray());
Console.Write($"Decrypted file created: {plaintextFile}");
}

Related

C# Facing issue to encrypt and decrypt text by Base64

The text ZIRT which i encrypt by base64 this way
public static string encrypt(string ToEncrypt)
{
return Convert.ToBase64String(Encoding.ASCII.GetBytes(ToEncrypt));
}
after encrypt the text becomes V2tsU1ZB and when i try to decrypt using the below function
public static string decrypt(string cypherString)
{
//return Encoding.ASCII.GetString(Convert.FromBase64String(cypherString));
byte[] data = Convert.FromBase64String(cypherString);
string decodedString = Encoding.UTF8.GetString(data);
return decodedString;
}
then i am getting this text WklSVA but it suppose to be ZIRT
Please tell me what is wrong in my code ?
I am giving more code which fail to decrypt text
private void button1_Click(object sender, EventArgs e)
{
string strTxt = "ZIRT";
string ss = EnryptString(strTxt);
string ss1 = EnryptString(ss);
}
public string DecryptString(string encrString)
{
byte[] b;
string decrypted;
try
{
b = Convert.FromBase64String(encrString);
decrypted = System.Text.ASCIIEncoding.ASCII.GetString(b);
}
catch (FormatException fe)
{
decrypted = "";
}
return decrypted;
}
public string EnryptString(string strEncrypted)
{
byte[] b = System.Text.ASCIIEncoding.ASCII.GetBytes(strEncrypted);
string encrypted = Convert.ToBase64String(b);
return encrypted;
}
There is double encoding of the strings that explain the incorrect result. You are also using different text encodings when encrypting and decrypting. ASCII vs UTF8, this should be the same.
The following example provides the result I would expect:
byte[] b = System.Text.ASCIIEncoding.UTF8.GetBytes("test abc");
string base64Encoded = Convert.ToBase64String(b);
b = Convert.FromBase64String(base64Encoded);
Console.WriteLine( System.Text.ASCIIEncoding.UTF8.GetString(b));
// "test abc"
As mentioned in the comments, this is not encryption, but encoding.

Throwing an exception when convert string to base64

I have two methods, where I need to convert string to base64 at begin and reverse this operation at the end. Problem is when my input string lenght is not divisible by 4 an conversion method throws exception.
public class Hashing
{
public string Encrypt(string encrypted)
{
byte[] byteData = Convert.FromBase64String(encrypted);
byte[] byteResult = Encrypt(byteData); // pt.1
return Convert.ToBase64String(byteResult);
}
public string Decrypt(string decrypted)
{
byte[] byteData = Convert.FromBase64String(decrypted);
byte[] byteResult = Decrypt(byteData); //pt.2
return Convert.ToBase64String(byteResult);
}
/*
...
*/
}
class Program
{
static void Main(string[] args)
{
Hashing cryptographyContext = new Hashing();
var cryptoTest = "123456789"; //someStringThatNotGonnaBeConverted;
string enc = cryptographyContext.Encrypt(password);
string dec = cryptographyContext.Decrypt(enc);
Console.WriteLine(dec);
Console.ReadLine();
}
}
Problem is I need base64 format at input of Decrypt and Encrypt methods (these at pt. 1 and 2) And I need returning strings from these methods. Do someone have an idea how to workaround this behaviour?
You are using base-64 incorrectly; base-64 translates:
forwards, arbitrary byte[] to structured string
backwards, structured string to the original byte[]
Conversely, a regular text encoding works the other way:
forwards, arbitrary string to structured byte[]
backwards, structured byte[] to the original string
You are trying to use base-64 to get a byte[] from an arbitrary string, which isn't a thing that it does. For that, you want a regular text encoding, such as UTF-8. Try using Encoding.UTF8.GetBytes() etc instead for one half, and base-64 for the other:
public string Encrypt(string plainText)
{
byte[] byteData = Encoding.UTF8.GetBytes(plainText);
byte[] byteResult = Encrypt(byteData);
return Convert.ToBase64String(byteResult);
}
public string Decrypt(string cipherText)
{
byte[] byteData = Convert.FromBase64String(cipherText);
byte[] byteResult = Decrypt(byteData);
return Encoding.UTF8.GetString(byteResult);
}

RSA encrypt by PHP and decrypt by C#

I'm trying to encryption and decrpytion process between C# and PHP.
My C# code:
this.EncryptData("123456", 1024, this.PublicKey);
public byte[] Encrypt(byte[] byte_0, int keysize, string publicKey)
{
byte[] numArray;
using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(keysize))
{
rSACryptoServiceProvider.FromXmlString(publicKey);
numArray = rSACryptoServiceProvider.Encrypt(byte_0, this.bool_0);
}
return numArray;
}
public string EncryptData(string string_0, int keysize, string publicKey)
{
string base64String;
try
{
byte[] numArray = this.Encrypt(Encoding.UTF8.GetBytes(string_0), keysize, publicKey);
base64String = Convert.ToBase64String(numArray);
}
catch (Exception exception)
{
base64String = string.Empty;
}
return base64String;
}
public byte[] Decrypt(byte[] byte_0, int keysize, string Key)
{
byte[] numArray;
using (RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider(keysize))
{
rSACryptoServiceProvider.FromXmlString(Key);
numArray = rSACryptoServiceProvider.Decrypt(byte_0, this.bool_0);
}
return numArray;
}
public string DecryptData(string string_0, int keysize, string Key)
{
string str;
try
{
byte[] numArray = this.Decrypt(Convert.FromBase64String(string_0), keysize, Key);
str = Encoding.UTF8.GetString(numArray);
}
catch (Exception exception)
{
str = string.Empty;
}
return str;
}
and my PHP: lib(https://github.com/membersuite/sdk-php/blob/master/APISample/SSOWithSDK/phpseclib/Crypt/RSA_XML.php)
$rsa = new Crypt_RSA_XML();
$plaintext = '123456';
$rsa->loadKeyfromXML($publicKey);
$ciphertext = base64_encode(strrev($rsa->encrypt($plaintext)));
code after PHP encrypt cant decrypt by c# code. anyone can help?
Although Microsoft uses little endian notation for numbers, RSA has been defined by PKCS#1 / RFC 3447. That explicitly defines how to do padding and such, but it also defines how the resulting octet string should look like using I2OSP or the integer-to-octet-string primitive. This primitive specifies the output as fixed size (key size) byte array in big endian format. This is also the encoding that PHP uses, so you should not reverse the output.
In other words, you should not have to use strrev.

Bitstamp - new authentication in C# - signature

The new authentication of bitstamp says the following:
Signature is a HMAC-SHA256 encoded message containing: nonce, client ID and API key. The HMAC-SHA256 code must be generated using a secret key that was generated with your API key. This code must be converted to it's hexadecimal representation (64 uppercase characters).Example (Python):
message = nonce + client_id + api_key
signature = hmac.new(API_SECRET, msg=message, digestmod=hashlib.sha256).hexdigest().upper()
Source: link
I've got the following code to add the new signature (and other parameters):
public void AddApiAuthentication(RestRequest restRequest)
{
var nonce = DateTime.Now.Ticks;
var signature = GetSignature(nonce, apiKey, apiSecret, clientId);
restRequest.AddParameter("key", apiKey);
restRequest.AddParameter("signature", signature);
restRequest.AddParameter("nonce", nonce);
}
private string GetSignature(long nonce, string key, string secret, string clientId)
{
string msg = string.Format("{0}{1}{2}", nonce,
clientId,
key);
return ByteArrayToString(SignHMACSHA256(secret, StrinToByteArray(msg))).ToUpper();
}
public static byte[] SignHMACSHA256(String key, byte[] data)
{
HMACSHA256 hashMaker = new HMACSHA256(Encoding.ASCII.GetBytes(key));
return hashMaker.ComputeHash(data);
}
public static byte[] StrinToByteArray(string str)
{
byte[] bytes = new byte[str.Length * sizeof(char)];
System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
return bytes;
}
public static string ByteArrayToString(byte[] hash)
{
return BitConverter.ToString(hash).Replace("-", "").ToLower();
}
And then I get this error:
{"error": "Invalid signature"}
Anyone got an idea what the problem could be? I checked my parameters a 100 times and those aren't wrong. Maybe somebody got a working piece of code (in C#) for the new authentication?
UPDATE
Abhinav was right, the StringToByteArray method was wrong (not only the typo :P) the working code is:
public static byte[] StrinToByteArray(string str)
{
return System.Text.Encoding.ASCII.GetBytes(str);
}
You are using str.ToCharArray() in StrinToByteArray which is incorrect (correct ONLY when used on the same system). You need to use ASCII encoding or something.

Bad data exception when decrypting using RSA with correct private and public key pair in C#

This is my code for decryption process:
private RSACryptoServiceProvider _rsa;
private string _privateKey;
private string _publicKey;
public RsaLibrary()
{
//initialsing the RSA object taking the option of a 1024 key size
_rsa = new RSACryptoServiceProvider(1024);
_privateKey = _rsa.ToXmlString(true);
_publicKey = _rsa.ToXmlString(false);
}
public string Decrypt(string ciphertext, string privateKey_ = null)
{
if (String.IsNullOrEmpty(privateKey_))
{
return DecryptToBytes(ciphertext, _privateKey);
}
else
{
return DecryptToBytes(ciphertext, privateKey_);
}
}
private string DecryptToBytes(string ciphertext, string privateKey)
{
if (String.IsNullOrEmpty(privateKey))
{
throw new ArgumentNullException("Error: No key provided.");
}
if (ciphertext.Length<=0)
{
throw new ArgumentNullException("Error: No message to decrypt.");
}
byte[] plaintext;
byte[] ciphertext_Bytes = Encoding.Unicode.GetBytes(ciphertext);
_rsa.FromXmlString(privateKey);
plaintext = _rsa.Decrypt(ciphertext_Bytes, false);
return Encoding.Unicode.GetString(plaintext);
}
The encryption code:
private string EncryptToByte(string plaintext, string publicKey)
{
if (String.IsNullOrEmpty(publicKey))
{
throw new ArgumentNullException("Error: No key provided.");
}
if (plaintext.Length<=0)
{
throw new ArgumentNullException("Error: No message to incrypt");
}
byte[] ciphertext;
byte[] plaintext_Bytes = Encoding.Unicode.GetBytes(plaintext);
_rsa.FromXmlString(publicKey);
ciphertext = _rsa.Encrypt(plaintext_Bytes, false);
return Convert.ToBase64String(ciphertext);
}
I can not see where I am going wrong. I have made sure that the keys are correct. The public one which i extracted using this line in the constructor:
_publicKey = _rsa.ToXmlString(false);
This public key is displayed on the form that I created. The private i used the "true" instead of false.
Any ideas?
Ciphertext is very unlikely to be genuinely UTF-16-encoded text. Assuming that the encryption side had something like:
string encryptedText = Encoding.Unicode.GetString(encryptedBytes);
you've basically lost data. The result of encryption is not text - it's arbitrary binary data. If you want to convert that to text for some transport reason, you should use Base64, e.g.
string base64EncryptedText = Convert.ToBase64String(encryptedBytes);
Then use Convert.FromBase64String to recover the original encrypted binary data which is ready to decrypt.

Categories

Resources