Im trying to cycle through a byte array and decode it into a string, using RSA encryption, the encryption works with out an array but I am trying to make it usable for longer data, by encrypting each word of the string, but when doing this i get the error required String[] found String Java.
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
final PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String[][] decryptedText = new String[cipherText.length][];
for (int i = 0; i < cipherText.length; i++) {
**ERROR ON THIS LINE - required String[] found String Java**
decryptedText[i] = decrypt(cipherText[i], privateKey);
}
the decrypt method
public static String decrypt(byte[] text, PrivateKey key) {
byte[] dectyptedText = null;
try {
// 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);
dectyptedText = cipher.doFinal(text);
} catch (InvalidKeyException | NoSuchAlgorithmException | BadPaddingException |IllegalBlockSizeException | NoSuchPaddingException ex) {
}
return new String(dectyptedText);
}
Encrypt Method
public static byte[] encrypt(String text, PublicKey key) {
byte[] cipherText = null;
try {
// 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);
cipherText = cipher.doFinal(text.getBytes());
} catch (InvalidKeyException | NoSuchAlgorithmException | BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException e) {
}
return cipherText;
}
Problem is your decryptedText is a two dimensional array
String[][] decryptedText = new String[cipherText.length][];
so this line
decryptedText[i] = decrypt(cipherText[i], privateKey);
must put an array to the decryptedText. You can change declaration of decryptedText to fix this
String[] decryptedText = new String[cipherText.length];
Hope this helps.
decryptedText is declared as
String[][] decryptedText
It's thus an array of arrays of Strings.
Thus, decryptedText[i] is the ith element in this array of arrays. It's thus an array of Strings. And you try to initialize it with the returned value of decrypt(), which doesn't return an array of Strings, but a String. Hence the error.
I don't understand why you have a 2D array, and not simply an array of Strings.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 1 year ago.
Improve this question
I am trying to create a simple AES encryption/decryption module for use in a larger project, but I'm having trouble getting the AES methods to work. I've done a good amount of research, but I can't figure out what is going wrong within my code (I'm suspecting something simple that I'm missing).
Main:
public static byte[] genKey() {
// Create key generator
KeyGenerator keyGen;
try {
keyGen = KeyGenerator.getInstance("AES");
}
catch(GeneralSecurityException e) {
e.printStackTrace();
return null;
}
// Create random byte generator
SecureRandom r = new SecureRandom();
// Initialize key generator
keyGen.init(256, r);
SecretKey key = keyGen.generateKey();
return key.getEncoded();
}
public static void main(String[] args) throws GeneralSecurityException {
// write your code here
// Create AES handler
AES aes = new AES();
// Generate key
byte[] key = genKey();
// Set key for AES
aes.setKey(key);
Scanner in = new Scanner(System.in);
System.out.print("Please enter a phrase to encrypt: ");
String input = in.nextLine();
// Encrypt phrase
byte[][] encrypted = aes.encrypt(input);
// Decrypt phrase
String plaintext = aes.decrypt(encrypted[0], encrypted[1]);
// Print results
System.out.println("Ciphertext: " + encrypted[1]);
System.out.println("Plaintext: " + plaintext);
}
AES:
private Cipher cipher;
private SecretKey key;
public AES() {
// Create Cipher
try {
cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
} catch (GeneralSecurityException e) {
e.printStackTrace();
}
}
public void setKey(byte[] key) {
this.key = new SecretKeySpec(key, "AES");
}
public byte[][] encrypt(String plaintext) throws GeneralSecurityException {
System.out.println("Using key : " + key.getEncoded() + " to encrypt");
byte[][] values = new byte[2][];
// Decode plaintext into bytes
byte[] decodedPlaintext = new byte[0];
try {
decodedPlaintext = plaintext.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// Generate an IV and set up the Cipher to encrypt
byte[] ivBytes = new byte[16];
SecureRandom rand = new SecureRandom();
rand.nextBytes(ivBytes);
IvParameterSpec iv = new IvParameterSpec(ivBytes);
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
// Encrypt decoded plaintext
byte[] ciphertext = cipher.doFinal(decodedPlaintext);
values[0] = ivBytes;
values[1] = ciphertext;
return values;
}
public String decrypt(byte[] ivBytes, byte[] ciphertext) throws GeneralSecurityException {
System.out.println("Using key " + key.getEncoded() + " to decrypt");
// Set up cipher to decrypt
IvParameterSpec iv = new IvParameterSpec(ivBytes);
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] decodedPlaintext = cipher.doFinal(ciphertext);
// Encode plaintext
String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);
return plaintext;
}
Results:
Please enter a phrase to encrypt: test
Using key : [B#442d9b6e to encrypt
Using key [B#3d012ddd to decrypt
Ciphertext: [B#515f550a
Plaintext: dGVzdA==
I don't understand why my encryption/decryption seem to be using different keys when I only set the key once in the beginning. Am I creating a key wrong?
I've also tried:
byte[] key = new byte[32];
SecureRandom r = new SecureRandom();
r.nextBytes(key);
// Set key for AES
aes.setKey(key);
And run into the same issue.
If you trace this.key in AES class all the way through encode and decode using Arrays.toString(this.key.getEncoded()) it does look like it's using a persistent key.
this.key.getEncoded().toString()) returns a different representation each time but it seems like the actual byte array is the same.
I replaced
String plaintext = Base64.getEncoder().encodeToString(decodedPlaintext);
with
String plaintext = new String(decodedPlaintext, StandardCharsets.UTF_8);
and it seemed to work.
I have to decrypt some text which is encrypted in Node using AES/CBC/NOPADDING algorithm but end up getting some garbage value when decrypted in JAVA .. Please help...
Node Encryption code:
const iv = "0123456789012345";
ALGORITHM : 'aes-256-cbc',
ACCESS_CODE : MD5('Imgine#123$')
function encrypt(text) {
var cipher = crypto.createCipheriv(algorithm, key, iv);
var encrypted = cipher.update(text, "utf8", "base64");
encrypted += cipher.final("base64"); // to hex
return encrypted;
}
Java Decryption code:
private static final Charset UTF8 = Charset.forName("UTF-8");
public static String decrypt() throws NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException
{
String base64Cipher = "t7rCN8nBGlruCiSvpQ9DPg==";
byte [] iv = "0123456789012345".getBytes(UTF8);
byte [] secretBytes = "Imgine#123$".getBytes(UTF8);
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] thedigest = md.digest(secretBytes);
SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NOPADDING");
cipher.init(Cipher.DECRYPT_MODE, skey, new IvParameterSpec(iv));
return new String(cipher.doFinal(Base64.getDecoder().decode(base64Cipher))) ;
}
Result: e�J�,�d�|*�5Ҝ��
Eventually, I found the root cause, the culprit is converting key to MD5 which doesn't convert as required, the MessageDigest is converting the key to 128 bit, it has to be 256, am using the below method to convert the key as required which worked for me, Thanks for all your valuable inputs.
public static String getMd5(String input)
{
try {
// Static getInstance method is called with hashing MD5
MessageDigest md = MessageDigest.getInstance("MD5");
// digest() method is called to calculate message digest
// of an input digest() return array of byte
byte[] messageDigest = md.digest(input.getBytes());
// Convert byte array into signum representation
BigInteger no = new BigInteger(1, messageDigest);
// Convert message digest into hex value
String hashtext = no.toString(16);
while (hashtext.length() < 32) {
hashtext = "0" + hashtext;
}
return hashtext;
}
// For specifying wrong message digest algorithms
catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
I've wrote a method to encrypt/decrypt a string. Encryption is happening successfully but I cannot manage to make the decryption work... This is the code I have written:
public String encrypt(String a, int x) {
String ret = "";
String text = a;
String key = "Bar12345Bar12345"; // 128 bit key
try {
// Create key and cipher
Key aesKey = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
if(x == 0) { //x==0 means I want to encrypt
// encrypt the text
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
byte[] encrypted = cipher.doFinal(text.getBytes());
ret =new String(encrypted);
}
else { //if not 0 I want to decrypt
// decrypt the text
byte[] encrypted = text.getBytes(Charset.forName("UTF-8"));
cipher.init(Cipher.DECRYPT_MODE, aesKey);
String decrypted = new String(cipher.doFinal(encrypted));
ret=decrypted;
}
} catch(Exception e) {
e.printStackTrace();
}
return ret;
}
I think the problem arise when I'm trying to convert the string into byte array. The error I get is:
javax.crypto.BadPaddingException: Given final block not properly padded
So what is the problem ? If I am not converting the string into byte array in right way, how should I do it ?
I need to decrypt file in C++. What I have is byte array and pair of keys generated in Java using KeyPairGenerator from java.security;
Java Code:
public void generateKeys() {
try {
final KeyPairGenerator pairGenerator = KeyPairGenerator.getInstance(algorithmName);
pairGenerator.initialize(1024); //1024 - keysize
final KeyPair keyPair = pairGenerator.generateKeyPair();
savePublicKeyIntoFile(keyPair);
savePrivateKeyIntoFile(keyPair);
} catch (Exception e) {
System.err.println("Class EncryptionTool.generateKeys() ");
e.printStackTrace();
}
}
public static String encrypt() throws Exception {
// Encrypt the string using the public key
ObjectInputStream inputStream = null;
inputStream = new ObjectInputStream(new FileInputStream(publicKeyFilepath));
final PublicKey publicKey = (PublicKey) inputStream.readObject();
// get an RSA cipher object and print the provider
final Cipher cipher = Cipher.getInstance(algorithmName);
// encrypt the plain text using the public key
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] cipherText = null;
**cipherText = cipher.doFinal( loadPassword() );**
return changeByteArrayToString(cipherText);
}
I have generated keys saved in files and this cipherText array in C++.
What should I use to decrypt this ?
I want to encrypt and decrypt integers with AES but can't get it going.
To test the basic cryptographic process I wrote a simple method that takes input data, encrypts and decrypts it with the same parameters and returns the result.
Here is my failing JUnit test case that checks whether the input and the output data are equal.
#Test
public void test4() throws UnsupportedEncodingException {
Random random = new Random();
SecretKey secretKey = Tools.generateKey("secretKey".getBytes("UTF-8"));
byte[] initializationVector = Tools.intToByteArray(random.nextInt());
// ensuring that the initialization vector has the correct length
byte[] ivHash = Tools.hashMD5(initializationVector);
int value = random.nextInt();
byte[] input = Tools.intToByteArray(value);
byte[] received = Tools.enDeCrypt(input, secretKey, ivHash);
assertEquals(data.hashCode(), received.hashCode());
}
Method generateKey:
public static SecretKeySpec generateKey(byte[] secretKey) {
try {
// 256 bit key length
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(secretKey);
byte[] key = md.digest();
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
Method for int -> byte[] conversion:
public static byte[] intToByteArray(int a) {
// block size is 128 bit, thus I append zeros
byte[] intByte = ByteBuffer.allocate(4).putInt(a).array();
byte[] longerIntByte = new byte[16];
for (int i = 0; i < 4; i++) {
longerIntByte[i] = intByte[i];
}
for (int i = 4; i < longerIntByte.length; i++) {
longerIntByte[i] = 0;
}
return longerIntByte;
}
Here is the code for encryption and decryption:
public static byte[] enDeCrypt(byte[] data, SecretKey secretKey,
byte[] initialisationVector) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(initialisationVector);
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivSpec);
byte[] encrypted = cipher.doFinal(data);
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivSpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
} catch (NoSuchAlgorithmException | NoSuchPaddingException
| InvalidKeyException | InvalidAlgorithmParameterException
| IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException(e);
}
}
assertEquals(data.hashCode(), received.hashCode()) is very unlikely to pass unless data and received refer to the same object (since byte arrays inherit the identity hash code method from Object). I don't see where data comes from, but that is probably not the case here. You should use Arrays.equals(data, received).
Apart from that, there are various cryptographic issues here:
Random is not "random enough" for cryptographic purposes; you should use SecureRandom.
Key derivation using plain SHA-256 is dubious. You should consider using a key derivation algorithm that is specifically designed for this, like PBKDF2.
AES with 256-bit keys is not always better than 128-bit keys. Check this page. In this case it's completely bogus since passphrases rarely even reach 128 bits of entropy.
Random IVs – good, but why jump through hoops when you could just directly use SecureRandom.nextBytes(). Hashing the IV doesn't add anything useful.
There's no reason to do manual zero padding when you could instead let the library handle it. Just specify PKCS5Padding instead of NoPadding.