Encrypt in java and Decrypt in C# and reverse - bouncycastle

I have read some topic for my title, so I can't use them to fix my problem. So, i open a new topic...
I want to create 2 functions Encrypt and Decrypt in java (for Android app) and C# (my server) using symmetric encryption
Client (java) : Encrypt(ClearText1, Key)=secret --> Server : Decrypt(secret,Key)=ClearText1
and
Server (java) : Encrypt(ClearText2, Key)=secret --> Client: Decrypt(secret,Key)=ClearText2
I have used BouncyCastle Library For java and C#, but the byte in java is -128..127, while the byte in C# is 0..255, have not negative data. So client and Server encryption and decryption is fail.
Please help me (or share me the library for my problem). Thank you!
Here the code in C#:
How to use them in java? Note the data type "byte" in C# and java in not match
(of course, encrypt and decrypt data with 2 following funcions is true)
> public string _secretPhrase = "123abc456";
> public string EncryptData(string plainText)
> {
> DES des = new DESCryptoServiceProvider();
> des.Mode = CipherMode.ECB;
> des.Padding = PaddingMode.PKCS7;
>
> des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
> des.IV = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
>
> byte[] bytes = Encoding.UTF8.GetBytes(plainText);
> byte[] resultBytes = des.CreateEncryptor().TransformFinalBlock(bytes, 0, bytes.Length);
>
> return Convert.ToBase64String(resultBytes);
> }
>
> public string DecryptData(string encryptedText)
> {
> DES des = new DESCryptoServiceProvider();
> des.Mode = CipherMode.ECB;
> des.Padding = PaddingMode.PKCS7;
> des.Key = Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
> des.IV = System.Text.Encoding.UTF8.GetBytes(_secretPhrase.Substring(0, 8));
>
> byte[] bytes = Convert.FromBase64String(encryptedText);
> byte[] resultBytes = des.CreateDecryptor().TransformFinalBlock(bytes, 0, bytes.Length);
>
> return Encoding.UTF8.GetString(resultBytes);
> }

It doesn't look like you are using BouncyCastle. That looks like stock .NET Framework cryptography code. BouncyCastle uses naming conventions like DesEngine.
I recommend that you try using BouncyCastle for both C# and Java. I'm not convinced the byte difference will be a practical problem. The library should account for it correctly.
Also, single DES is now considered very weak. There are single day attacks against it on reasonable hardware, and it's no longer an approved standard. Look at AES instead.
Finally, I'm not sure using the same key and IV are wise. I'm not a cryptography expert, but using two distinct random numbers should be safer.

Related

Encrypt/Decrypt aes256cbc in Nodejs

I'm working on a porject where I need develop a Encrypt/Decrypt string in nodejs.
I receive the string the next format: pTS3JQzTxrSbd+cLESXHpg==
this string is generate from this page: https://encode-decode.com/aes-256-cbc-encrypt-online/
and use the aes-256-cbc standard
the code that i implemented is the next:
var CryptoJS = require("crypto-js");
var key = 'TEST_KEY';
var text = 'pTS3JQzTxrSbd+cLESXHpg==';
function decript(text, key) {
return CryptoJS.AES.decrypt(text.trim(), key);
}
console.log(decript(text, key).toString(CryptoJS.enc.Utf8));
But i always get an empty response.
could you say to me what is the issue?
thanks a lot!
As the documentation explains and I just answered yesterday, CryptoJS.AES when given a 'key' that is a string treats it as a password and uses password-based key derivation compatible with openssl enc. That is different from and incompatible with what your linked website does, which is not clearly stated, but based on the list of cipher names is almost certainly internally calling OpenSSL's 'EVP' interface, which means among other things that if you specify a key too short for the algorithm, as you did, it uses whatever happens to be adjacent in memory, which apparently was zero-value bytes (not unusual for programs run on operating systems newer than about 1980), and it either uses the default IV of zero bytes or similarly sets it to something that is zero bytes. And for CBC it uses PKCS5/7 padding, which is compatible with CryptoJS (and most other things). Therefore:
const CryptoJS = require('crypto-js');
var key = CryptoJS.enc.Latin1.parse("TEST_KEY\0\0\0\0\0\0\0\0"+"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
var iv = CryptoJS.enc.Latin1.parse("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0")
var ctx = CryptoJS.enc.Base64.parse("pTS3JQzTxrSbd+cLESXHpg==")
var enc = CryptoJS.lib.CipherParams.create({ciphertext:ctx})
console.log( CryptoJS.AES.decrypt (enc,key,{iv:iv}) .toString(CryptoJS.enc.Utf8) )
->
Test text

Application Cryptogram Generation and Validation Failure

I am working on a Master Card transaction processing app but still in the development stages. To be able to test my cryptogram validation app, I personalized a card using MChip with the following profile info:
MChip Jcop
app version 1.0
profile revision 1.0.11
requires universal OS.
After reading the contributions on these questions, Unable to Generate correct application Cryptogram and Generating Cryptogram Manually, I tried to check for my card's cryptogram version number but tag 0x9F10 was absent on my personalization data and there was no way I could add this tag before personalization. I have tried various cryptogram generation combinations on the Thales HSM but non is returning the same value as that returned by the card.
Being in the development stage with access to the development keys, I have checked to ensure the keys are good, same data passed for the cryptogram generation and at this stage I am completely clueless about what to do. I will appreciate any help I can get on this issue. Thanks
foreach (var tagLen in EMVTag.ParseDOL(crmDolstr))
{
requestData.Append(EMVData[tagLen.Split(',')[0]]);
dolData.AppendFormat("{0}|{1},", tagLen.Split(',')[0],
EMVData[tagLen.Split(',')[0]]);
}
string commandStr = string.Format("80 AE 8000 {0} {1} 00",
GetHexLen(requestData.ToString()), requestData.ToString());
byte[] hexData = Helpers.HexStringToBytes(commandStr);
apdu = new APDUCommand(hexData);
public APDUCommand(byte[] apdu)
{
if (apdu.Length < 5)
throw new Exception("Wrong APDU length.");
this.cla = apdu[OFFSET_CLA];
this.ins = apdu[OFFSET_INS];
this.p1 = apdu[OFFSET_P1];
this.p2 = apdu[OFFSET_P2];
this.lc = apdu[OFFSET_LC];
if (this.lc == apdu.Length - 5)
this.le = (byte) 0;
else if (this.lc == apdu.Length - 5 - 1)
this.le = apdu[apdu.Length - 1];
else
throw new Exception("Wrong LC value.");
this.data = new byte[this.lc];
System.Array.Copy(apdu, OFFSET_CDATA, this.data, 0,
this.data.Length);
}
The data you use (from CDOL) are not sufficient to generate cryptogram. Cryptogram usually includes AIP, ATC and CVR.
Please look at the response to the cryptogram generation for IAD as it usually contains also a dynamically generated CVR that is used in the cryptogram generation process.

Decode and unzip a Base64 encoded and Gziped compressed text

I am trying to read a text from XML node. The text is base 64 encrypted and Gzip compressed. I am trying in the following ways:
1. XmlNodeList nodeDebugs = xmlDoc.GetElementsByTagName("Debugs");
2. if (nodeDebugs != null)
3. {
4. for (int i = 0; i < nodeDebugs.Count; i++)
5. {
6. XmlNodeList childNodes = nodeDebugs.Item(i).ChildNodes;
7. String nodeName = childNodes.Item(i).Name;
8. if (nodeName == "Debug")
9. {
10. byte[] compressed = System.Text.Encoding.UTF8.GetBytes(childNodes.Item(i).InnerText.Trim());
11. using (var uncompressed = new MemoryStream())
12. using (var inStream = new MemoryStream(compressed))
13. using (var outStream = new GZipStream(inStream, CompressionMode.Decompress))
14. {
15. outStream .CopyTo(uncompressed);
16. Console.WriteLine(Encoding.UTF8.GetString(uncompressed.ToArray()));
17. }
Getting error at Line no 15, as "the magic number in gzip header is not correct."
Any help to resolve this issue is much appreciated. Thanks a lot in advance.
This is the problem, I suspect:
byte[] compressed = System.Text.Encoding.UTF8.GetBytes(childNodes.Item(i).InnerText.Trim());
You said that your data is compressed and then base64-encoded... but your code doesn't use base64 anywhere, which is a massive warning sign. I suspect you want:
string text = childNodes.Item(i).InnerText.Trim();
byte[] compressed = Convert.FromBase64String(text);
If that doesn't work, you should check each step of the transformation - you should have the same data during encoding and decoding, just in the reverse order. See my blog post about diagnosing reversible data transformations for more details - but hopefully the change above will fix it anyway.

Generating a random hex string (of length 50) in Java ME/J2ME

My app needs to generate a hex string to use as a session ID. Java's SecureRandom doesn't seem to be working ("java/lang/NoClassDefFoundError: java/security/SecureRandom: Cannot create class in system package")
I thought of doing something like this:
byte[] resBuf = new byte[50];
new Random().nextBytes(resBuf);
String resStr = new String(Hex.encode(resBuf));
But the method nextBytes(byte[] bytes) isn't available for some strange reason.
Does anyone have a means of generating a random hex number in Java ME/J2ME?
Many thanks.
Edit: The above generator seems to work when using Bouncy Castle lcrypto-j2me-145 (but not lcrypto-j2me-147).
JavaME is a subset of JavaSE, so many classes and methods in the desktop version are not available.
Looks like you are trying to get a random string of a given length. You can do something like this:
private String getRandomHexString(int numchars){
Random r = new Random();
StringBuffer sb = new StringBuffer();
while(sb.length() < numchars){
sb.append(Integer.toHexString(r.nextInt()));
}
return sb.toString().substring(0, numchars);
}

Convert.FromBase64String FormatException

I get a FormatException for this Convert.FromBase64String method. I don't mind about hardcoding the value. Anyone can explain why I get this exception.
// Instantiate a new RijndaelManaged object to perform string symmetric encryption
RijndaelManaged rijndaelCipher = new RijndaelManaged();
// Set key and IV
rijndaelCipher.Key = Convert.FromBase64String("TASK");
rijndaelCipher.IV = Convert.FromBase64String("0123");
Thank you.
Your strings aren't valid Base64.
You need to generate two cryptographically secure 256-bit random numbers, convert them to Base64, and embed them in your source.
For example:
var alg = new RijndaelManaged();
alg.BlockSize = alg.KeySize = 256;
Console.WriteLine("Key: " + Convert.ToBase64String(alg.Key));
Console.WriteLine("IV: " + Convert.ToBase64String(alg.IV));

Resources