Cant successfully Save a SecretKey as a String - java

I'm trying to save a key in an XML file for later decryption of a encrypted string, the software can encrypt and return me at the "Encrypt()" method, but returns error when trying to use the "Decrypt()" method
Code
private static Cipher ecipher;
private static Cipher dcipher;
public static String[] encrypt(String str) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, UnsupportedEncodingException, IllegalBlockSizeException, BadPaddingException {
String Key, res;
SecretKey key;
String[] Return = new String[2];
key = KeyGenerator.getInstance("DES").generateKey();
ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
enc = BASE64EncoderStream.encode(enc);
res = new String(enc);
//Returning values 0 = Encrypted String 1 = Key For Storage in XML
Return[0] = res;
byte[] keyBytes = key.getEncoded();
Key = new String(keyBytes,"UTF8");
Return[1] = Key;
return Return;
}
public static String decrypt(String str, String Key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, UnsupportedEncodingException, BadPaddingException {
SecretKey key = new SecretKeySpec(Key.getBytes("UTF8"), "DES");
dcipher = Cipher.getInstance("DES");
dcipher.init(Cipher.DECRYPT_MODE, key);
byte[] dec = BASE64DecoderStream.decode(str.getBytes());
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF8");
}
Console Return :
run:
Encryped String : EB6uhzsBl08=
Key : �g�uX8p
Sep 07, 2014 6:35:17 PM Software.Software main
SEVERE: null
java.security.InvalidKeyException: Invalid key length: 12 bytes
at com.sun.crypto.provider.DESCipher.engineGetKeySize(DESCipher.java:373)
at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1062)
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1020)
at javax.crypto.Cipher.implInit(Cipher.java:796)
at javax.crypto.Cipher.chooseProvider(Cipher.java:859)
at javax.crypto.Cipher.init(Cipher.java:1229)
at javax.crypto.Cipher.init(Cipher.java:1166)
at Software.Encryption.decrypt(Encryption.java:51)
at Software.Software.main(main.java:30)
BUILD SUCCESSFUL (total time: 1 second)

You have to encode the key in base64
public static String[] encrypt(String str) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
UnsupportedEncodingException, IllegalBlockSizeException,
BadPaddingException {
String Key, res;
SecretKey key;
String[] Return = new String[2];
key = KeyGenerator.getInstance("DES").generateKey();
ecipher = Cipher.getInstance("DES");
ecipher.init(Cipher.ENCRYPT_MODE, key);
byte[] utf8 = str.getBytes("UTF8");
byte[] enc = ecipher.doFinal(utf8);
enc = BASE64EncoderStream.encode(enc);
res = new String(enc);
// Returning values 0 = Encrypted String 1 = Key For Storage in XML
Return[0] = res;
byte[] keyBytes = key.getEncoded();
Key = new String(BASE64EncoderStream.encode(keyBytes), "UTF8");
Return[1] = Key;
return Return;
}
public static String decrypt(String str, String Key)
throws NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException, IllegalBlockSizeException,
UnsupportedEncodingException, BadPaddingException {
SecretKey key = new SecretKeySpec(BASE64DecoderStream.decode(Key.getBytes("UTF8")), "DES");
dcipher = Cipher.getInstance("DES");
dcipher.init(Cipher.DECRYPT_MODE, key);
byte[] dec = BASE64DecoderStream.decode(str.getBytes());
byte[] utf8 = dcipher.doFinal(dec);
return new String(utf8, "UTF8");
}

Related

Java AES GCM AEAD Tag mismatch

Im trying to write a program to encrypt any type of file. I had my encryption classes already done, when I noticed (at first it worked) that I am getting an AEADBadTagException whenever I try to decrypt any of my files.
Here is my encryption/decryption class:
class Encryptor {
private static final String algorithm = "AES/GCM/NoPadding";
private final int tagLengthBit = 128; // must be one of {128, 120, 112, 104, 96}
private final int ivLengthByte = 12;
private final int saltLengthByte = 64;
protected final Charset UTF_8 = StandardCharsets.UTF_8;
private CryptoUtils crypto = new CryptoUtils();
// return a base64 encoded AES encrypted text
/**
*
* #param pText to encrypt
* #param password password for encryption
* #return encoded pText
* #throws Exception
*/
protected byte[] encrypt(byte[] pText, char[] password) throws Exception {
// 64 bytes salt
byte[] salt = crypto.getRandomNonce(saltLengthByte);
// GCM recommended 12 bytes iv?
byte[] iv = crypto.getRandomNonce(ivLengthByte);
// secret key from password
SecretKey aesKeyFromPassword = crypto.getAESKeyFromPassword(password, salt);
Cipher cipher = Cipher.getInstance(algorithm);
// ASE-GCM needs GCMParameterSpec
cipher.init(Cipher.ENCRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv));
byte[] cipherText = cipher.doFinal(pText);
// prefix IV and Salt to cipher text
byte[] cipherTextWithIvSalt = ByteBuffer.allocate(iv.length + salt.length + cipherText.length).put(iv).put(salt)
.put(cipherText).array();
Main.clearArray(password, null);
Main.clearArray(null, salt);
Main.clearArray(null, iv);
Main.clearArray(null, cipherText);
aesKeyFromPassword = null;
cipher = null;
try {
return cipherTextWithIvSalt;
} finally {
Main.clearArray(null, cipherTextWithIvSalt);
}
}
// für Files
protected byte[] decrypt(byte[] encryptedText, char[] password)
throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
// get back the iv and salt from the cipher text
ByteBuffer bb = ByteBuffer.wrap(encryptedText);
byte[] iv = new byte[ivLengthByte];
bb.get(iv);
byte[] salt = new byte[saltLengthByte];
bb.get(salt);
byte[] cipherText = new byte[bb.remaining()];
bb.get(cipherText);
// get back the aes key from the same password and salt
SecretKey aesKeyFromPassword;
aesKeyFromPassword = crypto.getAESKeyFromPassword(password, salt);
Cipher cipher;
cipher = Cipher.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, aesKeyFromPassword, new GCMParameterSpec(tagLengthBit, iv));
byte[] plainText = cipher.doFinal(cipherText);
Main.clearArray(password, null);
Main.clearArray(null, iv);
Main.clearArray(null, salt);
Main.clearArray(null, cipherText);
aesKeyFromPassword = null;
cipher = null;
bb = null;
try {
return plainText;
} finally {
Main.clearArray(null, plainText);
}
}
protected void encryptFile(String file, char[] pw) throws Exception {
Path pathToFile = Paths.get(file);
byte[] fileCont = Files.readAllBytes(pathToFile);
byte[] encrypted = encrypt(fileCont, pw);
Files.write(pathToFile, encrypted);
Main.clearArray(pw, null);
Main.clearArray(null, fileCont);
Main.clearArray(null, encrypted);
}
protected void decryptFile(String file, char[] pw)
throws IOException, InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
Path pathToFile = Paths.get(file);
byte[] fileCont = Files.readAllBytes(pathToFile);
byte[] decrypted = decrypt(fileCont, pw);
Files.write(pathToFile, decrypted);
Main.clearArray(pw, null);
Main.clearArray(null, fileCont);
Main.clearArray(null, decrypted);
}
}
The corresponding CryptoUtils class:
class CryptoUtils {
protected byte[] getRandomNonce(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
try {
return nonce;
} finally {
Main.clearArray(null, nonce);
}
}
// Password derived AES 256 bits secret key
protected SecretKey getAESKeyFromPassword(char[] password, byte[] salt)
throws NoSuchAlgorithmException, InvalidKeySpecException {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
// iterationCount = 65536
// keyLength = 256
KeySpec spec = new PBEKeySpec(password, salt, 65536, 256);
SecretKey secret = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
try {
return secret;
} finally {
secret = null;
}
}
// hex representation
protected String hex(byte[] bytes) {
StringBuilder result = new StringBuilder();
for (byte b : bytes) {
result.append(String.format("%02x", b));
}
try {
return result.toString();
} finally {
result.delete(0, result.length() - 1);
}
}
// print hex with block size split
protected String hexWithBlockSize(byte[] bytes, int blockSize) {
String hex = hex(bytes);
// one hex = 2 chars
blockSize = blockSize * 2;
// better idea how to print this?
List<String> result = new ArrayList<>();
int index = 0;
while (index < hex.length()) {
result.add(hex.substring(index, Math.min(index + blockSize, hex.length())));
index += blockSize;
}
try {
return result.toString();
} finally {
result.clear();
}
}
}
The Exception occurs at byte[] plainText = cipher.doFinal(cipherText); in the decrypt method.
Im unsure if the tagLenthBit must be the ivLengthByte * 8, I did try it though and it didnt make any difference.
I'm providing my own example code for AES 256 GCM file encryption with PBKDF2 key derivation because I'm too lazy to check all parts of your code :-)
The encryption is done with CipherInput-/Outputstreams because that avoids "out of memory errors" when encrypting larger files (your code is reading the complete plaintext / ciphertext in a byte array).
Please note that the code has no exception handling, no clearing of sensitive data/variables and the encryption/decryption result is a simple "file exist" routine but I'm sure you can use it as a good basis for your program.
That's a sample output:
AES 256 GCM-mode PBKDF2 with SHA512 key derivation file encryption
result encryption: true
result decryption: true
code:
import javax.crypto.*;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
public class AesGcmEncryptionInlineIvPbkdf2BufferedCipherInputStreamSoExample {
public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, IOException,
InvalidKeyException, InvalidKeySpecException, InvalidAlgorithmParameterException {
System.out.println("AES 256 GCM-mode PBKDF2 with SHA512 key derivation file encryption");
char[] password = "123456".toCharArray();
int iterations = 65536;
String uncryptedFilename = "uncrypted.txt";
String encryptedFilename = "encrypted.enc";
String decryptedFilename = "decrypted.txt";
boolean result;
result = encryptGcmFileBufferedCipherOutputStream(uncryptedFilename, encryptedFilename, password, iterations);
System.out.println("result encryption: " + result);
result = decryptGcmFileBufferedCipherInputStream(encryptedFilename, decryptedFilename, password, iterations);
System.out.println("result decryption: " + result);
}
public static boolean encryptGcmFileBufferedCipherOutputStream(String inputFilename, String outputFilename, char[] password, int iterations) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException {
SecureRandom secureRandom = new SecureRandom();
byte[] salt = new byte[32];
secureRandom.nextBytes(salt);
byte[] nonce = new byte[12];
secureRandom.nextBytes(nonce);
Cipher cipher = Cipher.getInstance("AES/GCM/NOPadding");
try (FileInputStream in = new FileInputStream(inputFilename);
FileOutputStream out = new FileOutputStream(outputFilename);
CipherOutputStream encryptedOutputStream = new CipherOutputStream(out, cipher);) {
out.write(nonce);
out.write(salt);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keySpec = new PBEKeySpec(password, salt, iterations, 32 * 8); // 128 - 192 - 256
byte[] key = secretKeyFactory.generateSecret(keySpec).getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, nonce);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, gcmParameterSpec);
byte[] buffer = new byte[8096];
int nread;
while ((nread = in.read(buffer)) > 0) {
encryptedOutputStream.write(buffer, 0, nread);
}
encryptedOutputStream.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
public static boolean decryptGcmFileBufferedCipherInputStream(String inputFilename, String outputFilename, char[] password, int iterations) throws
IOException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException {
byte[] salt = new byte[32];
byte[] nonce = new byte[12];
Cipher cipher = Cipher.getInstance("AES/GCM/NOPadding");
try (FileInputStream in = new FileInputStream(inputFilename); // i don't care about the path as all is lokal
CipherInputStream cipherInputStream = new CipherInputStream(in, cipher);
FileOutputStream out = new FileOutputStream(outputFilename)) // i don't care about the path as all is lokal
{
byte[] buffer = new byte[8192];
in.read(nonce);
in.read(salt);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512");
KeySpec keySpec = new PBEKeySpec(password, salt, iterations, 32 * 8); // 128 - 192 - 256
byte[] key = secretKeyFactory.generateSecret(keySpec).getEncoded();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(16 * 8, nonce);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, gcmParameterSpec);
int nread;
while ((nread = cipherInputStream.read(buffer)) > 0) {
out.write(buffer, 0, nread);
}
out.flush();
}
if (new File(outputFilename).exists()) {
return true;
} else {
return false;
}
}
}

Could not write JSON: Input length must be multiple of 8 when decrypting with padded cipher

I have followed a guide to simply encrypt and decrypt a string but I can't somehow make it work
I want to have a constant key so I don't need to save it to my database and waste space
I just want to encrypt some personal data not password
do you guys have any idea?
I'm following this guide please it
public String getAction() throws Exception {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes();
decodedKey.length, "DES");
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
byte[] text = action.getBytes();
byte[] textEncrypted = desCipher.doFinal(text);
String getAct = ""+textEncrypted;
return getAct;
}
public void setAction(String action) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes();
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
byte[] text = action.getBytes();
desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
byte[] textEncrypted = desCipher.doFinal(text);
String setAct = ""+textEncrypted;
this.action = setAct;
}
Full error here
2018-04-12 17:06:34.587 WARN 1572 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Input length must be multiple of 8 when decrypting with padded cipher; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Input length must be multiple of 8 when decrypting with padded cipher (through reference chain: com.capstone.codegum.Codegum.Objects.Logs["action"])
I have modified your code a bit and able to run it. Here is a running example:
Pojo.java
package com.test;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class Pojo {
private byte[] action = null;
private SecretKey myDesKey = null;
private String encodedKey = "eightkey";
public String getAction() throws Exception {
Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
byte[] text = action;
byte[] textEncrypted = desCipher.doFinal(text);
String getAct = new String(textEncrypted);
return getAct;
}
public void setAction(String action) throws Exception {
Cipher desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
byte[] key = encodedKey.getBytes();
this.myDesKey = new SecretKeySpec(key, "DES");
desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
byte[] text = action.getBytes();
byte[] textEncrypted = desCipher.doFinal(text);
this.action = textEncrypted;
}
}
MainClass.java
package com.test;
public class MainClass {
public static void main(String[] args) throws Exception {
Pojo p = new Pojo();
p.setAction("hello");
String s = p.getAction();
System.out.println(s);
p.setAction("world");
s = p.getAction();
System.out.println(s);
}
}
Output:
hello
world
Use byte[] actionBytes instead of String action something of the sort:
private byte[] actionBytes;
public String getAction() throws Exception {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes("UTF8");
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
byte[] textEncrypted = desCipher.doFinal(actionBytes);
return new String(textEncrypted);
}
public void setAction(String action) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes("UTF8");
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
byte[] text = action.getBytes("UTF8");
desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
byte[] textEncrypted = desCipher.doFinal(text);
actionBytes = textEncrypted;
}
Or if you want to keep using String action then you should do this:
public String action;
public String getAction() throws Exception {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes("UTF8");
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
desCipher.init(Cipher.DECRYPT_MODE, myDesKey);
byte[] textEncrypted = desCipher.doFinal(action.getBytes("UTF8"));
return new String(textEncrypted);
}
public void setAction(String action) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException, UnsupportedEncodingException {
String encodedKey = "eightkey";
byte[] key = encodedKey.getBytes("UTF8");
SecretKey myDesKey = new SecretKeySpec(key, "DES");
Cipher desCipher;
desCipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
byte[] text = action.getBytes("UTF8");
desCipher.init(Cipher.ENCRYPT_MODE, myDesKey);
byte[] textEncrypted = desCipher.doFinal(text);
action = new String(textEncrypted, "UTF8");
}

java.lang.IllegalArgumentException: Null input buffer

I am getting java.lang.IllegalArgumentException: Null input buffer exception while i am calling decode input string function. here is my function
public String decodeInputString(String inputString) throws NoSuchAlgorithmException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchPaddingException {
byte[] salt = "MyKey".getBytes();
SecretKey secretKey = new SecretKeySpec(salt, 0, 16, "AES");
byte[] encryptedTextByte = Base64.decode(inputString);
cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] decryptedByte = cipher.doFinal(encryptedTextByte);
String decryptedText = new String(decryptedByte);
return decryptedText;
}
while i am calling decodeInputString("s8aCvIy4pcgc Y Gu/MSAw==") i am getting java.lang.IllegalArgumentException: Null input buffer exception.

InvalidKeyException: Illegal key size

Before you mark this as a duplicate, please read the full question.
I've looked through countless questions here about this problem, and every answer said to install JCE. However, if I want to send the program to someone else, another computer, virtually anything off the development computer, they have to install JCE too.
Is there a way I can use a smaller keysize without having to install anything?
My encryption method;
public static String encrypt(String in) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, IOException {
String out = " ";
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("AES");
keygen.init(128);
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
// build the initialization vector
SecureRandom random = new SecureRandom();
byte iv[] = new byte[16]; //generate random 16 byte IV. AES is always 16bytes
random.nextBytes(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
saveKey(key, iv); //<-- save to file
// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
byte[] encrypted = cipher.doFinal(in.getBytes());
out = asHex(encrypted);
return out;
}
And my decrypt method:
public static String decrypt(String in) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException,
IllegalBlockSizeException, BadPaddingException, IOException, KeyFileNotFoundException, UnknownKeyException {
String out = " ";
byte[] key = readKey("key").clone(); //<--from file
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
byte[] iv = readKey("iv"); //<-- from file
IvParameterSpec ivspec = new IvParameterSpec(iv);
//initialize the cipher for decryption
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivspec);
// decrypt the message
byte[] decrypted = cipher.doFinal(in.getBytes());
out = asHex(decrypted);
return out;
}
My saveKey() method:
private static void saveKey(byte[] key, byte[] iv) throws FileNotFoundException, IOException {
File keyFile = new File(Logging.getCurrentDir() + "\\cikey.key");
keys.setProperty("key", asHex(key));
keys.setProperty("iv", asHex(iv));
keys.store(new FileOutputStream(keyFile.getAbsolutePath(), false), null);
}
My readKey() method:
private static byte[] readKey(String request) throws KeyFileNotFoundException, UnknownKeyException, FileNotFoundException, IOException {
File keyFile = new File(Logging.getCurrentDir() + "\\cikey.key");
byte[] storage;
keys.load(new FileInputStream(keyFile));
if (!keyFile.exists())
throw new KeyFileNotFoundException("Key file not located.");
if (keys.containsKey(request) == false)
throw new UnknownKeyException("Key not found.");
else
storage = keys.getProperty(request).getBytes();
return storage;
}
asHex() method (transferring array to String):
public static String asHex(byte buf[]) {
StringBuilder strbuf = new StringBuilder(buf.length * 2);
for (int i = 0; i < buf.length; i++) {
if (((int) buf[i] & 0xff) < 0x10)
strbuf.append("0");
strbuf.append(Long.toString((int) buf[i] & 0xff, 16));
}
return strbuf.toString();
}
Is there a way I can use a smaller keysize without having to install anything?
You can't use AES with keys sizes smaller than 128 bit, but there are other ciphers available: DES, Blowfish, etc. They aren't as secure as AES, but still can do the trick if your application (as most apps do) does not worth complicated hacking effort. Here's an example for 56 bit DES:
public static String encrypt(String in) throws Exception {
String out = " ";
// generate a key
KeyGenerator keygen = KeyGenerator.getInstance("DES");
keygen.init(56);
byte[] key = keygen.generateKey().getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(key, "DES");
// build the initialization vector
SecureRandom random = new SecureRandom();
byte iv[] = new byte[8]; //generate random 8 byte IV.
random.nextBytes(iv);
IvParameterSpec ivspec = new IvParameterSpec(iv);
// initialize the cipher for encrypt mode
Cipher cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivspec);
byte[] encrypted = cipher.doFinal(in.getBytes());
out = asHex(encrypted);
return out;
}
There is also a problem with storing and reading the keys in the code. You're storing them as hex, but reading as symbols from default platform encoding. Here's an example how to make both operations uniform:
private static void saveKey(byte[] key, byte[] iv) throws IOException {
File keyFile = new File("C:/cikey.key");
keys.setProperty("key", toHexString(key));
keys.setProperty("iv", toHexString(iv));
keys.store(new FileOutputStream(keyFile.getAbsolutePath(), false), null);
}
private static byte[] readKey(String request) throws IOException {
File keyFile = new File("C:/cikey.key");
keys.load(new FileInputStream(keyFile));
return toByteArray(keys.getProperty(request));
}
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}

Java: Bad Padding Exception in RSA

I am running the following code I am getting a Bad Padding Exception - Data must start with zero. Any ideas?
Here is the code
public class test {
public static void main(String[] args) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidKeyException,
SignatureException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException {
KeyPair k=Utilities.keys(2048);
PublicKey public_key=Utilities.public_key(k);
PrivateKey private_key=Utilities.private_key(k);
String hex1=Lib.stringToHex("test1/test2/test3");
byte[] plaintext=Lib.toByteArray(hex1);
byte [] cipher=Utilities.Encrypt_RSA(plaintext, public_key);
System.out.println(cipher.length);
byte[] newArray = new byte[128];
byte[] newArray2 = new byte[128];
// System.arraycopy(cipher, 0, newArray, 0, 512);
for (int i=0;i<cipher.length;i++){
if(i<cipher.length/2){
newArray[i]=cipher[i];
}
else if((i>cipher.length/2)&&(i<cipher.length)){
newArray2[i-128]=cipher[i];
}
}
// System.arraycopy(cipher, 512, newArray2, 0, 512);
byte[] cipher2=Utilities.Encrypt_RSA_Pr(newArray, private_key);
byte[] cipher3=Utilities.Encrypt_RSA_Pr(newArray2, private_key);
System.out.println(cipher2.length+" cipher2");
System.out.println(cipher3.length+" cipher3");
byte [] plain1=Utilities.Decrypt_RSA_Pub(cipher2,public_key);
byte [] plain2=Utilities.Decrypt_RSA_Pub(cipher3,public_key);
System.out.println(plain1.length);
System.out.println(plain2.length);
byte[] finald=new byte[256];
for(int i=0;i<256;i++){
if(i<128){
finald[i]=plain1[i];
}
else{
finald[i]=plain2[i-128];
}
}
for(int i=0;i<plain1.length;i++){
if(i>=64){
plain1[i]='\0';
}
}
System.out.println(plain1.length);
System.out.println(finald.length;
byte[] plainfinal=Utilities.Decrypt_RSA(finald, private_key);
Here are the methods that I use for encrypt/decrypt:
public static byte[] Encrypt_RSA(byte[] plaintext,PublicKey key) throws
InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException,NoSuchProviderException{
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
c.init(Cipher.ENCRYPT_MODE,key);
byte [] ciphertext = c.doFinal(plaintext);
return ciphertext;
}
public static byte[] Decrypt_RSA(byte []ciphertext,PrivateKey key) throws
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException,NoSuchProviderException{
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
c.init(Cipher.DECRYPT_MODE,key);
byte [] plaintext=c.doFinal(ciphertext);
return plaintext;
}
public static byte[] Encrypt_RSA_Pr(byte[] plaintext,PrivateKey key) throws
NoSuchAlgorithmException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException, InvalidKeyException{
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
c.init(Cipher.ENCRYPT_MODE,key);
byte [] ciphertext = c.doFinal(plaintext);
return ciphertext;
}
public static byte[] Decrypt_RSA_Pub(byte []ciphertext,PublicKey key) throws
NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException,BadPaddingException,NoSuchProviderException{
Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding");
c.init(Cipher.DECRYPT_MODE,key);
byte [] plaintext=c.doFinal(ciphertext);
return plaintext;
}
You meant to split cipher into two halves but you did it wrong. I suspect this line:
else if((i>cipher.length/2)&&(i<cipher.length)){
should instead be
else if((i>=cipher.length/2)&&(i<cipher.length)){

Categories