I'm having problems when encrypting data to be sent to a SOAP service.
I suppose the problem is in the SecretKey generation, because the response is still the same with an incorrect password.
The current code is:
WServiceSoap ws = new WService().getWServiceSoap();
MessageDigest md = MessageDigest.getInstance("md5");
byte[] digestOfPassword = md.digest("12345678".getBytes("utf-8"));
final byte[] keyBytes = Arrays.copyOf(digestOfPassword, 24);
for (int j = 0, k = 16; j < 8;) {
keyBytes[k++] = keyBytes[j++];
}
SecretKey opKey = new SecretKeySpec(keyBytes, "DESede");
byte[] opIV = { 0, 0, 0, 1, 2, 3, 4, 5 };
Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, opKey, new IvParameterSpec(opIV));
byte[] encrypted = c.doFinal(
ClientDirectOperacionCTMS.DATOS_OPERACION.getBytes("UTF-8"));
String encryptedDatosOperacion= Base64.encodeBase64String(encrypted);
String result= ws.operacionCTMS(encryptedDatosOperacion);
System.out.println(result);
, and the exception is
Exception in thread "main" javax.xml.ws.soap.SOAPFaultException: Server was unable to process request. ---> La operación de pago con tarjeta no ha sido satisfactoria. ---> Additional non-parsable characters are at the end of the string.
at com.sun.xml.internal.ws.fault.SOAP11Fault.getProtocolException(SOAP11Fault.java:178)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:111)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:108)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:78)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:107)
I have also tried this code without success:
final byte[] keyBytes = Arrays.copyOf(Base64.decodeBase64("12345678"), 24);
SecretKey opKey = new SecretKeySpec(keyBytes, "DESede");
The decryption done by the server is
CheckKey(ref rgbKey);
cryptoProvider = new TripleDESCryptoServiceProvider();
cryptoTransform = cryptoProvider.CreateDecryptor(rgbKey, s_rgbIV);
memoryStream = new MemoryStream();
using (CryptoStream cryptoStream = new CryptoStream(
memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(rgbEncryptedText, 0, rgbEncryptedText.Length);
}
originalText = Encoding.UTF8.GetString(memoryStream.ToArray());
, where CheckKey is
private static void CheckKey(ref Byte[] rgbKey)
{
if (rgbKey.Length > KEY_MAX_LENGTH)
{
Array.Resize(ref rgbKey, KEY_MAX_LENGTH);
}
else if (rgbKey.Length < KEY_MAX_LENGTH)
{
Byte fill = 0x41;
Int32 offset = rgbKey.Length;
Array.Resize(ref rgbKey, KEY_MAX_LENGTH);
for (Int32 index = offset; index < KEY_MAX_LENGTH; index++)
{
rgbKey[index] = fill++;
}
}
}
Related
So I've made a desktop application (before the website) were i've made a login and a register system in it and an encryption ofcourse. And now I've had an idea to make a website with the register and login system because i thought it would be easier but the problem is i've made the website after the desktop application which means i've made a C# encryption/decryption before website and I want to convert the C# encryption to the PHP (if it is even possible) to match my database users information (password, username, mail etc.). This is my C# encryption and decryption code:
Encryption:
private static byte[] AesEncrypt(byte[] bytesToBeEncrypted, byte[]
passwordBytes)
{
byte[] encryptedBytes;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // min 8
using (var ms = new MemoryStream())
{
using (var aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
Decryption:
private static byte[] AesDecrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes;
var saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 }; // min 8
using (var ms = new MemoryStream())
{
using (var aes = new RijndaelManaged())
{
aes.KeySize = 256;
aes.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
aes.Key = key.GetBytes(aes.KeySize / 8);
aes.IV = key.GetBytes(aes.BlockSize / 8);
aes.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
Method which I use to encrypt data:
public static string Encrypt(string clearText, string password, byte[] salt = null)
{
var baPwd = Encoding.UTF8.GetBytes(password);
var baPwdHash = SHA256.Create().ComputeHash(baPwd);
var baText = Encoding.UTF8.GetBytes(clearText);
byte[] baSalt;
baSalt = salt;
var baEncrypted = new byte[baSalt.Length + baText.Length];
for (var i = 0; i < baSalt.Length; i++)
baEncrypted[i] = baSalt[i];
EncryptionSalt = baSalt.ToString();
for (var i = 0; i < baText.Length; i++)
baEncrypted[i + baSalt.Length] = baText[i];
baEncrypted = AesEncrypt(baEncrypted, baPwdHash);
var result = Convert.ToBase64String(baEncrypted);
EncryptionSalt = baSalt.ToString();
return result;
}
}
Method which I use to decrypt data:
public static string Decrypt(string cipherText, string password)
{
var baPwd = Encoding.UTF8.GetBytes(password);
var baPwdHash = SHA256.Create().ComputeHash(baPwd);
var baText = Convert.FromBase64String(cipherText);
var baDecrypted = AesDecrypt(baText, baPwdHash);
const int saltLength = 12;
var baResult = new byte[baDecrypted.Length - saltLength];
for (var i = 0; i < baResult.Length; i++)
baResult[i] = baDecrypted[i + saltLength];
var result = Encoding.UTF8.GetString(baResult);
return result;
}
An example of using C# encryption in my C# code:
Encryption.Encrypt(password, Encryption.RandomBytes().ToString(), salt));
And the RandomBytes method:
public static byte[] RandomBytes()
{
const int saltLength = 12;
var ba = new byte[saltLength];
RandomNumberGenerator.Create().GetBytes(ba);
return ba;
}
Firstly I need to know if it's possible, secondly if anyone wants to you could give me an example of this encryption in PHP or give me the code.
Im using the following code to encrypt and decrypt a small file using RSA and safely transfer them using usb drive (I know, RSA is not the best for encrypting files...)
But for some reason it wont work anymore. Im trying to decrypt my file and it keeps throwing a "The parameter is incorrect" exception
The keys did not changed (both private and public)
The code did not changed (both encrypt and decrypt)
Anybody have an idea of what could be wrong?
static int SegmentLength = 213; //85; // keysize/8 -42 -1
public static byte[] EncryptRSA(string publicKey, byte[] data)
{
CspParameters cspParams = new CspParameters { ProviderType = 1 };
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(2048, cspParams);
rsaProvider.ImportCspBlob(Convert.FromBase64String(publicKey));
//byte[] plainBytes = data;
//byte[] encryptedBytes = rsaProvider.Encrypt(plainBytes, false);
var length = data.Length / SegmentLength + 1;
MemoryStream stream = new MemoryStream();
for (var i = 0; i < length; i++)
{
int lengthToCopy;
if (i == length - 1 || data.Length < SegmentLength)
lengthToCopy = data.Length - (i * SegmentLength);
else
lengthToCopy = SegmentLength;
//var segment = decryptedData.Substring(i * SegmentLength, lengthToCopy);
byte[] segment = new byte[lengthToCopy];
Buffer.BlockCopy(data, i * SegmentLength, segment, 0, lengthToCopy);
byte[] encrypted = rsaProvider.Encrypt(segment,false);
stream.Write(encrypted,0,encrypted.Length);
}
return stream.ToArray();
}
private const int EncryptedLength = 256; //keylen * 8
public static byte[] DecryptRSA(string privateKey, byte[] data)
{
CspParameters cspParams = new CspParameters { ProviderType = 1 };
RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(2048, cspParams);
rsaProvider.ImportCspBlob(Convert.FromBase64String(privateKey));
var rsainfo = rsaProvider.ExportParameters(true);
var length = data.Length / EncryptedLength;
MemoryStream stream = new MemoryStream();
for (var i = 0; i < length; i++)
{
byte[] segment = new byte[EncryptedLength];
Buffer.BlockCopy(data, i * EncryptedLength, segment, 0, EncryptedLength);
byte[] decrypted = rsaProvider.Decrypt(segment, false);
stream.Write(decrypted, 0, decrypted.Length);
}
//string plainText = Encoding.UTF8.GetString(plainBytes, 0, plainBytes.Length);
return stream.ToArray();
}
System.Security.Cryptography.CryptographicException occurred
HResult=0x80070057 Message=Parâmetro incorreto.
Source=mscorlib StackTrace: 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) at Decriptor.Program.DecryptRSA(String
privateKey, Byte[] data) in
Program.cs:line 149
at Decriptor.Program.Main(String[] args) in
Program.cs:line 45
rsainfo {System.Security.Cryptography.RSAParameters} System.Security.Cryptography.RSAParameters
D {byte[256]} byte[]
DP {byte[128]} byte[]
DQ {byte[128]} byte[]
Exponent {byte[3]} byte[]
InverseQ {byte[128]} byte[]
Modulus {byte[256]} byte[]
P {byte[128]} byte[]
Q {byte[128]} byte[]
I got my data encrypted in MySQL, I store it as BLOB, then I need to decrypt it in C#, but I don't get the expected result.
The BLOB in MYSQL:
This is my result:
It should be just PD001KY6900430
Here's My Code in C#
string ConnectionString = "Data Source=win-3doecchgfbt;Initial Catalog=DWH;User id=sa;Password=Password123;";
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
string query = "SELECT * FROM tb_investor";
SqlDataAdapter adapter = new SqlDataAdapter();
var command = new SqlCommand(query, connection);
adapter.SelectCommand = command;
DataTable dTable = new DataTable();
adapter.Fill(dTable);
for(var x =0; x < dTable.Rows.Count; x++)
{
var dr = dTable.Rows;
byte[] accNoByte = (byte[])dr[x].ItemArray[1];
byte[] key = mkey("satu");
var rkey = BitConverter.ToString(key).Replace("-", "");
var decAccNo = decrypt_function(accNoByte, key);
}
}
Here is the mkey method :
Encoding winLatinCodePage = Encoding.GetEncoding(1252);
byte[] key = Encoding.UTF8.GetBytes(skey);
byte[] k = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
for (int i = 0; i < key.Length; i++)
{
k[i % 16] = (byte)(k[i % 16] ^ key[i]);
}
return k;
Here is the decrypt_function method :
RijndaelManaged Crypto = null;
MemoryStream MemStream = null;
ICryptoTransform Decryptor = null;
CryptoStream Crypto_Stream = null;
StreamReader Stream_Read = null;
string Plain_Text;
try
{
Crypto = new RijndaelManaged();
Crypto.Key = Key;
Crypto.Mode = CipherMode.ECB;
Crypto.Padding = PaddingMode.None;
MemStream = new MemoryStream(Cipher_Text);
Crypto.GenerateIV();
//Create Decryptor make sure if you are decrypting that this is here and you did not copy paste encryptor.
Decryptor = Crypto.CreateDecryptor(Crypto.Key, Crypto.IV);
//This is different from the encryption look at the mode make sure you are reading from the stream.
Crypto_Stream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read);
//I used the stream reader here because the ReadToEnd method is easy and because it return a string, also easy.
Stream_Read = new StreamReader(Crypto_Stream);
Plain_Text = Stream_Read.ReadToEnd();
}
finally
{
if (Crypto != null)
Crypto.Clear();
MemStream.Flush();
MemStream.Close();
}
return Plain_Text;
Please show me the mistake I've made.
"PD001KY6900430" is 14 bytes, AES(RijndaelManaged default) block size is 16-bytes so the input data needs to be padded to a block size multiple, that is the last two 0x02 bytes of PKCS#7 padding. Thus the two last bytes of: "PD001KY6900430\u0002\u0002" (where \u0002 represents a single byte of 0x02 in UTF-16) is the padding.
This is usually handled (removed) by specifying PKCS#7 padding to the decryption method.
The Fix:
Change
Crypto.Padding = PaddingMode.None;
to
Crypto.Padding = PaddingMode.PKCS7;
It is always best to fully specify all options.
I have ASP .NET C# project and I want to encrypt file with multiple public keys from certificates using X509Store and I am using this function to encrypt the file its fine but I need it for group of certificates:
private static void EncryptFile(string inFile, RSACryptoServiceProvider rsaPublicKey)
{
using (AesManaged aesManaged = new AesManaged())
{
// Create instance of AesManaged for
// symetric encryption of the data.
aesManaged.KeySize = 256;
aesManaged.BlockSize = 128;
aesManaged.Mode = CipherMode.CBC;
using (ICryptoTransform transform = aesManaged.CreateEncryptor())
{
RSAPKCS1KeyExchangeFormatter keyFormatter = new RSAPKCS1KeyExchangeFormatter(rsaPublicKey);
byte[] keyEncrypted = keyFormatter.CreateKeyExchange(aesManaged.Key, aesManaged.GetType());
// Create byte arrays to contain
// the length values of the key and IV.
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = aesManaged.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
// Write the following to the FileStream
// for the encrypted file (outFs):
// - length of the key
// - length of the IV
// - ecrypted key
// - the IV
// - the encrypted cipher content
int startFileName = inFile.LastIndexOf("\\") + 1;
// Change the file's extension to ".enc"
string outFile = encrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc";
Directory.CreateDirectory(encrFolder);
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(aesManaged.IV, 0, lIV);
// Now write the cipher text using
// a CryptoStream for encrypting.
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
// By encrypting a chunk at
// a time, you can save memory
// and accommodate large files.
int count = 0;
int offset = 0;
// blockSizeBytes can be any arbitrary size.
int blockSizeBytes = aesManaged.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}
}
}
I am having some trouble getting a asp.net C# file encryption / decryption process to work. I can get the file uploaded and ecrypted, but cannot get the decryption to work.
I get the error: Exception Details: System.Security.Cryptography.CryptographicException: Bad Data. on the decryption line:
byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);
Here is my encrypt function:
private void EncryptFile(string inFile)
{
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
ICryptoTransform transform = rjndl.CreateEncryptor();
byte[] keyEncrypted = rsa.Encrypt(rjndl.Key, false);
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
int lKey = keyEncrypted.Length;
LenK = BitConverter.GetBytes(lKey);
int lIV = rjndl.IV.Length;
LenIV = BitConverter.GetBytes(lIV);
int startFileName = inFile.LastIndexOf("\\") + 1;
// Change the file's extension to ".enc"
string outFile = EncrFolder + inFile.Substring(startFileName, inFile.LastIndexOf(".") - startFileName) + ".enc";
lblDecryptFileName.Text = outFile;
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
outFs.Write(LenK, 0, 4);
outFs.Write(LenIV, 0, 4);
outFs.Write(keyEncrypted, 0, lKey);
outFs.Write(rjndl.IV, 0, lIV);
using (CryptoStream outStreamEncrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
int count = 0;
int offset = 0;
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
int bytesRead = 0;
using (FileStream inFs = new FileStream(inFile, FileMode.Open))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamEncrypted.Write(data, 0, count);
bytesRead += blockSizeBytes;
}
while (count > 0);
inFs.Close();
}
outStreamEncrypted.FlushFinalBlock();
outStreamEncrypted.Close();
}
outFs.Close();
}
}
And here is the decrypt function where the error occurs.
private void DecryptFile(string inFile)
{
// Create instance of Rijndael for
// symetric decryption of the data.
RijndaelManaged rjndl = new RijndaelManaged();
rjndl.KeySize = 256;
rjndl.BlockSize = 256;
rjndl.Mode = CipherMode.CBC;
byte[] LenK = new byte[4];
byte[] LenIV = new byte[4];
string outFile = DecrFolder + inFile.Substring(0, inFile.LastIndexOf(".")) + ".txt";
using (FileStream inFs = new FileStream(EncrFolder + inFile, FileMode.Open))
{
inFs.Seek(0, SeekOrigin.Begin);
inFs.Seek(0, SeekOrigin.Begin);
inFs.Read(LenK, 0, 3);
inFs.Seek(4, SeekOrigin.Begin);
inFs.Read(LenIV, 0, 3);
int lenK = BitConverter.ToInt32(LenK, 0);
int lenIV = BitConverter.ToInt32(LenIV, 0);
int startC = lenK + lenIV + 8;
int lenC = (int)inFs.Length - startC;
// Create the byte arrays for
// the encrypted Rijndael key,
// the IV, and the cipher text.
byte[] KeyEncrypted = new byte[lenK];
byte[] IV = new byte[lenIV];
// Extract the key and IV
// starting from index 8
// after the length values.
inFs.Seek(8, SeekOrigin.Begin);
inFs.Read(KeyEncrypted, 0, lenK);
inFs.Seek(8 + lenK, SeekOrigin.Begin);
inFs.Read(IV, 0, lenIV);
Directory.CreateDirectory(DecrFolder);
byte[] KeyDecrypted = rsa.Decrypt(KeyEncrypted, false);
ICryptoTransform transform = rjndl.CreateDecryptor(KeyDecrypted, IV);
using (FileStream outFs = new FileStream(outFile, FileMode.Create))
{
int count = 0;
int offset = 0;
int blockSizeBytes = rjndl.BlockSize / 8;
byte[] data = new byte[blockSizeBytes];
inFs.Seek(startC, SeekOrigin.Begin);
using (CryptoStream outStreamDecrypted = new CryptoStream(outFs, transform, CryptoStreamMode.Write))
{
do
{
count = inFs.Read(data, 0, blockSizeBytes);
offset += count;
outStreamDecrypted.Write(data, 0, count);
}
while (count > 0);
outStreamDecrypted.FlushFinalBlock();
outStreamDecrypted.Close();
}
outFs.Close();
}
inFs.Close();
}
}
Any help on this would be great! I am not an RSA encryption expert and have been reading a lot of posts but still not able to come up with a solution.
I have finally figured this out. The code worked well in a desktop application when I tried it there. It just didn't work in the asp.net 4 web application I was trying to write. The issue was the RSA object wasn't persisted through the session. So, the RSA object was created okay. The file was encrypted okay. But when I went to decrypt the file the RSA object was not there. The error message of System.Security.Cryptography.CryptographicException: Bad Data is misleading as that wasn't really the issue, the data was fine.
So, when creating the key and the RSA object I used the following:
rsa = new RSACryptoServiceProvider(cspp);
Session["rsa"] = rsa;
Next, when the decryption function is called I added in:
if (rsa == null)
rsa = (RSACryptoServiceProvider)Session["rsa"];
Of course, there is a little more code around this also so catch if there is no key for the RSA session, but this is the high level solution for the issue I was having.
If anyone is looking for this let me know and I can share more of the code.