I have an encrypted file, which is encrypted in java using RC4 Encryption. Below is the code in java.
public class ata {
public static byte[] a(byte[] bArr, String str) {
try {
return ata.a(bArr, str.getBytes("UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static byte[] a(byte[] bArr, byte[] bArr2) {
try {
Cipher instance = Cipher.getInstance("RC4");
instance.init(2, new SecretKeySpec(bArr2, "RC4"));
return instance.update(bArr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return null;
} catch (NoSuchPaddingException e2) {
e2.printStackTrace();
return null;
} catch (InvalidKeyException e3) {
e3.printStackTrace();
return null;
}
}
}
I need to decrypt the file in C# so i need equivalent class of the java code in C#. Is anybody have any idea how to do it ?
Related
I have implemented rsa Encryption and Decryption in Java which works totally fine. But my problem is, when I write my encrypted string to a JTextField, I can't get the correct value back out of the JTextField in order to decrypt the message again.
Here is my code, I believe I am doing something wrong at the conversion of my values (byte[] and string):
public static byte[] encrypt(String message, PublicKey pk) {
Cipher cipher= null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pk);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
byte[] chiffrat = null;
try {
chiffrat = cipher.doFinal(message.getBytes());
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return chiffrat;
}
public static String decrypt(byte[] chiffrat, PrivateKey sk)
{
byte[] dec = null;
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, sk);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
try {
dec = cipher.doFinal(chiffrat);
} catch (IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
}
return new String(dec);
}
And in my Window class:
Writing encrypted string in my TextField
JButton btnEncrypt = new JButton("Plaintext -> RSA");
btnEncrypt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
txtEncryptionRSA.setText(new String(rsa.encrypt(pwboxEncryptionPlain.getText(), rsa.key.getPublic())));
}
});
This writes d¿Åád6×Ãö† G0|ôw;-3—?Ó^xudC\Ö>Ós`H9ÅóÛ`¥ in my TextField.
Trying to decrypt and write in another TextField:
JButton btnDecrypt = new JButton("RSA -> Plaintext");
btnDecrypt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
byte[] encryptedmsg = txtEncryptionRSA.getText().getBytes();
System.out.println(encryptedmsg);
pwboxEncryptionPlain.setText(rsaClass.decrypt(encryptedmsg, rsa.key.getPrivate()));
}
});
This prints out: [B#abd4af7 and Encryption fails.
I have a test function that returns a byte[] in one Java class, FirstClass:
public static byte[] testA(){
CipherClass crypto = new CipherClass();
byte[] a = crypto.encrypt("helloWorld");
return a;
}
Where CipherClass contains my java.crypto.Cipher methods to encrypt and decrypt inputs.
In another Java class, SecondClass, I instantiate my previous FirstClass and call its testA() method which I save to a byte[] variable and then try to decrypt it:
FirstClass fc = new FirstClass();
byte[] b = fc.testA();
System.out.println(crypto.decrypt(b)); //Outputs BadPaddingError
Why does encrypting a String in one Java file and then passing the resulting byte[] into another Java file to decrypt it causes a BadPaddingError?
What can be done to fix a way around this?
Why does the Cipher only work if both encryption and decryption are in the same class as follows?:
CipherClass crypto = new CipherClass();
byte[] a = crypto.encrypt("helloWorld"); //Outputs [B#5474c6c
byte[] b = a;
System.out.println(crypto.decrypt(b)); //Outputs "helloWorld"
EDIT: My CipherClass code as requested below.
SecretKey and IVParameterSpec generator:
public List<KeyGenerator> getKeyGenerator(){
List<KeyGenerator> list = new ArrayList<KeyGenerator>();
KeyGenerator keyGenerator;
int keyBitSize = 128;
try
{
SecureRandom secureRandom = new SecureRandom();
keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(keyBitSize, secureRandom);
list.add(keyGenerator);
return list;
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return list;
}
public List<SecretKey> getSecretKey(List<KeyGenerator> keygen) {
List<SecretKey> list = new ArrayList<SecretKey>();
KeyGenerator keyGenerator;
SecretKey secretKey;
keyGenerator = keygen.get(0);
secretKey = keyGenerator.generateKey();
list.add(secretKey);
return list;
}
public List<IvParameterSpec> getIvSpec(List<SecretKey> secretKey) {
List<IvParameterSpec> list = new ArrayList<IvParameterSpec>();
Cipher cipher;
byte[] iv;
try
{
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivSpec = new IvParameterSpec(iv);
list.add(ivSpec);
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return list;
}
List<KeyGenerator> kgList = getKeyGenerator();
List<SecretKey> skList = getSecretKey(kgList); //skList.get(0) is the SecretKey
List<IvParameterSpec> ivList = getIvSpec(skList); //ivList.get(0) is the IVParameterSpec
My encrypt() method:
public byte[] encrypt(String inputStr) {
Cipher cipher;
SecretKey secretKey = skList.get(0);
IvParameterSpec ivSpec = ivList.get(0);
byte[] plainText;
byte[] cipherText = new byte[]{};
try
{
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
try
{
secretKey = skList.get(0);
ivSpec = ivList.get(0);
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
try
{
plainText = inputStr.getBytes("UTF-8");
cipherText = cipher.doFinal(plainText);
return cipherText;
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace();
}
catch (BadPaddingException e)
{
e.printStackTrace();
}
catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
}
catch (InvalidKeyException e)
{
e.printStackTrace();
}
catch (InvalidAlgorithmParameterException e1)
{
e1.printStackTrace();
}
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return cipherText;
}
My decrypt() method:
public String decrypt(byte[] cipherText){
Cipher cipherDe;
SecretKey secretKey = skList.get(0);
IvParameterSpec ivSpec = ivList.get(0);
byte[] deciByte;
String decryptText = "";
try
{
cipherDe = Cipher.getInstance("AES/CBC/PKCS5Padding");
try
{
secretKey = skList.get(0);
ivSpec = ivList.get(0);
cipherDe.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
try
{
//De-cryption
deciByte = cipherDe.doFinal(cipherText);
decryptText = new String(deciByte);
return decryptText;
}
catch (IllegalBlockSizeException e)
{
e.printStackTrace();
}
catch (BadPaddingException e)
{
e.printStackTrace();
}
}
catch (InvalidKeyException e)
{
e.printStackTrace();
}
//De-cryption
catch (InvalidAlgorithmParameterException e1)
{
e1.printStackTrace();
}
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
catch (NoSuchPaddingException e)
{
e.printStackTrace();
}
return decryptText;
}
Here are my encryption settings
public static final String ALGORITHM = "RSA";
public static final String CIPHER = "RSA/ECB/PKCS1Padding";
public static final String HASH_ALGORITHM = "SHA-256";
public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";
public static final int KEY_SIZE = 1048;
Here is my code to encrypt
public byte[] encrypt(byte[] toEncrypt, String keyPath){
int keyLength = KEY_SIZE/8 - 11;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String toEncryptString = new String(toEncrypt,StandardCharsets.UTF_8);
String[] lines = toEncryptString.split("(?<=\\G.{" + keyLength + "})");
byte[] encryptedData = new byte[0];
try{
inputStream = new ObjectInputStream(new FileInputStream(keyPath));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
final Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
if(toEncrypt.length >= keyLength){
for(String line : lines){
byteArrayOutputStream.write(cipher.doFinal(line.getBytes("UTF-8")));
}
}else{
byteArrayOutputStream.write(cipher.doFinal(toEncrypt));
}
encryptedData = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
byte[] cipheredData = base64Encoder(encryptedData);
System.out.println(Arrays.toString(cipheredData));
return cipheredData;
}
Here is my code to decrypt
public byte[] decrypt(byte[] toDecrypt, String keyPath) {
byte[] decypherText = base64Decoder(toDecrypt);
System.out.println(toDecrypt.length);
System.out.println(decypherText.length);
int keyLength = KEY_SIZE/8 - 11;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
String toEncryptString = Arrays.toString(decypherText);
String[] lines = toEncryptString.split("(?<=\\G.{" + keyLength + "})");
byte[] decipheredData = new byte[0];
try{
inputStream = new ObjectInputStream(new FileInputStream(keyPath));
final PrivateKey privateKey = (PrivateKey) inputStream.readObject();
final Cipher cipher = Cipher.getInstance(CIPHER);
cipher.init(Cipher.DECRYPT_MODE,privateKey);
if(decypherText.length >= keyLength){
for(String line : lines){
byteArrayOutputStream.write(cipher.doFinal(line.getBytes("UTF-8")));
}
}else{
byteArrayOutputStream.write(cipher.doFinal(decypherText));
}
decipheredData = byteArrayOutputStream.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
System.out.println(Arrays.toString(decipheredData));
return decipheredData;
}
I'm trying to encrypt a Public Key "A" with the Public Key "B". Encryption is successful, but when I try to decrypt it with the Private Key "B", it gives me that error.
The code looks fine to me, already reviewed it several times, these past 16 hours, already searched through several posts in here, and did not found a suitable answer for my problem.
Also, it already gave me BadPaddingException when decrypting. "Data must not be longer than 131 bytes". However, I'm using a Cipher with padding, so it can only decrypt data with 120 bytes. Why this error, if the Public key ciphered is splitted into blocks of 120 bytes?
Edit: before anyone else says that encrypting a Public Key is a mistery, have in your mind that it's the purpose of the project.. to have a Public Key as an ID and, as such, the need to encrypt so that no one discovers the ID of the user.
Your code doesn't make sense. You're trying to split the ciphertext on a plaintext string. It isn't there. It got removed when you split the string. In any case the data has been encrypted, so searching for a plaintext in it is futile.
You should be base64-decoding, decrypting, reading objects, and then recombining them using "(?<=\\G.{" + keyLength + "})" as a delimiter.
In fact why you're splitting in the first place and then encrypting multiple lines is a mystery.
And why you're serializing is another. Just encrypt the entire thing, without splitting, base64-encode it, and save that. When decrypting, just base64-decode it and decrypt it.
And, finally, why you're encrypting a public key at all is a complete mystery. It's PUBLIC. Not a secret.
I have DESCrypto in C# and Java as follows. I get the correct results when using C#. I get problem when using Java. How to resolved this problem?
// This is in the main function which will call the crypto function in the security class (C#).
private void button1_Click(object sender, EventArgs e)
{
string plainText = "0123456789";
Debug.WriteLine("plainText:" + plainText );
// plainText:0123456789
byte[] encrypted = Security.Encrypt(Encoding.ASCII.GetBytes(plainText));
Debug.WriteLine("encrypted:" + Security.GetString(encrypted));
// encrypted:4F792B474936462B6A4F62635A6142464D54782F4E413D3D
byte[] decrypted = Security.Decrypt(encrypted);
Debug.WriteLine("decrypted:" + Encoding.ASCII.GetString(decrypted)); //
// decrypted:0123456789
}
// This is a security class (C#)
public class Security
{
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
public static byte[] GetBytes(string value)
{
SoapHexBinary shb = SoapHexBinary.Parse(value);
return shb.Value;
}
public static string GetString(byte[] value)
{
SoapHexBinary shb = new SoapHexBinary(value);
return shb.ToString();
}
public static byte[] Decrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream(Convert.FromBase64String(Encoding.ASCII.GetString(value)));
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateDecryptor(KEY_64, IV_64), CryptoStreamMode.Read);
StreamReader reader = new StreamReader(cstream);
return Encoding.ASCII.GetBytes(reader.ReadToEnd());
}
public static byte[] Encrypt(byte[] value)
{
MemoryStream mstream = new MemoryStream();
CryptoStream cstream = new CryptoStream(mstream, new DESCryptoServiceProvider().CreateEncryptor(KEY_64, IV_64), CryptoStreamMode.Write);
StreamWriter writer = new StreamWriter(cstream);
writer.Write(Encoding.UTF8.GetString(value));
writer.Flush();
cstream.FlushFinalBlock();
mstream.Flush();
return Encoding ASCII.GetBytes(Convert.ToBase64String(mstream.GetBuffer(), 0, Convert.ToInt32(mstream.Length)));
}
}
// This is in the main function which will call the crypto function in the security class (Java).
String plainText = "0123456789";
Log.d("test", String.format("plainText:%s\n", plainText));
// plainText:0123456789
byte[] encrypted = Security.Encrypt(plainText.getBytes());
Log.d("test", String.format("encrypted:%s\n", Security.GetString(encrypted)));
// encrypted:3B2F8623A17E8CE6DC65A045313C7F34
byte[] decrypted = Security.Decrypt(encrypted);
Log.d("test", String.format("decrypted: %s\n", String.valueOf(decrypted)));
// decrypted:[B#6801b34
//This is a security class (JAVA)
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Security {
private static byte[] IV_64 = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
private static byte[] KEY_64 = new byte[] { 7, 1, 7, 7, 5, 5, 4, 7 };
private static String KEY_TYPE = "DES";
private static String ALGORITHM = "DES/CBC/PKCS5Padding";
public static String GetString(byte[] value) {
StringBuilder builder = new StringBuilder();
for (byte i : value) {
builder.append(String.format("%02X", i & 0xff));
}
return builder.toString();
}
public static byte[] GetByte(String value) {
StringBuilder builder = new StringBuilder();
for (char i : value.toCharArray()) {
builder.append(String.format("%02X", i & 0xff));
}
return String.valueOf(builder).getBytes();
}
public static byte[] Encrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
public static byte[] Decrypt(byte[] value) {
try {
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(KEY_64, KEY_TYPE), new IvParameterSpec(IV_64));
return cipher.doFinal(value);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
}
return null;
}
}
In java, when plainText = "0123456789", expected output from encryption is 4F792B474936462B6A4F62635A6142464D54782F4E413D3D (like in C#), but I get 3B2F8623A17E8CE6DC65A045313C7F34.
In C#, you're encoding the ciphertext with Base64 inside of the Security class and then you encode it again with Hex outside of it. In Java, you're only doing the Hex encoding. You should stick to one encoding and not combine two.
Other considerations:
DES should really not be used nowadays. It's rather easy to brute-force.
If you use CBC mode, then you need to use a new and unpredictable IV every time (randomly generated). It doesn't have to be secret, so you can prepend it to the ciphertext and slice it off before decryption.
You really should be thinking about adding authentication to the ciphertext. Otherwise, it may be possible to run a padding oracle attack in your system. Either use an authenticated mode like GCM or EAX, or use an encrypt-then-MAC scheme with a strong MAC like HMAC-SHA256.
I created a simple java chat application . Below is the follow
Run ChatClient.java - Dialog box is shown where user enters username. Then private key and public key are generated and stored in C:/username/publickey,C:/username/privatekey.
Above step repeats when we run ChatClient.java again.
Then user1 sends message to User2 in encrypted form using User2 public key (Which is working fine)(after encryption , message is stored in text file) then User2 clicks decrypt button which decrypts the text (reads the encrypted text from file) using User 2 private key then display in textarea.
When I trying to decrypt I am getting "Not PKCS#1 block type 2 or Zero padding" exception
public static byte[] encrypt(String text, PublicKey key) throws {
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] cipherText = cipher.doFinal(text.getBytes("UTF8"));
return org.apache.commons.codec.binary.Base64.encodeBase64(cipherText);
}
public static String decrypt(String text, PrivateKey key) throws {
byte[] dectyptedText = null;
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(ALGORITHM);
// decrypt the text using the private key
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] byteCipherText =org.apache.commons.codec.binary.Base64.decodeBase64(text):
byte[] cipherData = cipher.doFinal(byteCipherText);
return new String(dectyptedText);
}
private void btnDecryptActionPerformed(ActionEvent evt) throws {
String name11 = this.getTitle();
String test90 = null;
String PRIVATE_KEY_FILE = "C:/keys/"+name11+"/private.key";
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("cipher.txt"));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
while(in.ready())
{
String stest= in.readLine();
test90 = stest;
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
ObjectInputStream inputStream = null;
try {
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
PrivateKey privateKey = null;
try {
privateKey = (PrivateKey) inputStream.readObject();
} catch (ClassNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
PrivateKey privatekey = (PrivateKey) inputStream.readObject();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
String plainText;
// byte[] test100 = test90.getBytes();
// out.println(test100);
plainText = decrypt(test90, privateKey); (Getting Error Here)
decryptText.append(plainText);
}
The highlighted code below means test90 only contains the last line in the cipher.txt file. Does cipher.txt contain 1 line only? If you want to read in everything, you need to concatenate each line as you read it in.
while(in.ready())
{
String stest= in.readLine();
test90 = stest;
}
It is also a good idea to System.out the variable test90 in the decrypt method to be sure that you're getting the expected base64 data to be decrypted.