Encrypting exception: Given final block not properly padded - java

I'm trying to decrypt with my own key the following string:
"zW4%3D1p1%2AjR9E"
private static void init(String password) throws Exception {
PBEKeySpec PBEKeySpecification = new PBEKeySpec(password.toCharArray());
keyDES = SecretKeyFactory.getInstance(encrypted_algorithm).generateSecret(PBEKeySpecification);
myCipher = Cipher.getInstance(encrypted_algorithm);
algorithmSpecification = new PBEParameterSpec(salt, iterationCounter);
}
public static void main(String[] args) throws Exception {
String input = "zW4%3D1p1%2AjR9E";
String infoDesencriptada = null;
try {
init("abc123ab");
myCipher.init(2, keyDES, algorithmSpecification);
BASE64Decoder base64Enc = new BASE64Decoder();
byte[] arrayBase64Enc = base64Enc.decodeBuffer(input);
byte[] decryptedBytes = myCipher.doFinal(arrayBase64Enc);
infoDesencriptada = new String(decryptedBytes, "UTF8");
} catch (Exception var5) {
System.out.println("Some exception:" + var5.getMessage());
var5.printStackTrace();
}
}
I'm getting this error: javax.crypto.BadPaddingException: Given final block not properly padded
Any help?

In the question text the data is "zW4%3D1p1%2AjR9E" but in the code it is "zW4%3D1p1%2AjR9E7", note the extra trailing 7.
The input must be a multiple of the block size, 8-bytes for DES so it seems there is a simple entry error in the code.

Related

Porting python PKCS1_v1_5 encryption code to java generating different signatures

I am trying to port my working python code for generating signature to java but they both are producing different signatures. Here is my code for python which is generating the signature.
import pdb
pdb.set_trace()
signer = PKCS1_v1_5.new(priv_key)
digest = SHA256.new()
digest.update(message)
val = signer.sign(digest)
return val
I am calling this function using this statement
signature = b64encode(sign(msg1, private))
Here the msg1 is
msg1 = 'test'.encode("utf8")
and private is the private key which I am importing using
RSA.importKey("<Location of key>"
I am trying to write a similar java code for implementing the same functionality with this given code
public static void main(String[] args) throws Exception {
String payload = "test";
String dig = makeDigest( payload, "SHA-256");
Key k = getPrivateKey("private_key.der");
String signature = encrypt(dig, "RSA", k);
System.out.print(signature);
}
public static String makeDigest(String payload, String digestAlgo) {
String strDigest = "";
try {
MessageDigest md = MessageDigest.getInstance(digestAlgo);
byte[] p_b = payload.getBytes("UTF-8");
md.update(p_b);
byte[] digest = md.digest();
char[] encoded = Hex.encodeHex(digest);
strDigest = new String(encoded);
System.out.println(strDigest);
}
catch (Exception ex) {
ex.printStackTrace();
}
return strDigest;
}
public static String encrypt(String sha, String encryptAlgo, Key k) {
String strEncrypted = "";
try {
Security.addProvider(new BouncyCastleProvider());
Cipher cipher = Cipher.getInstance(encryptAlgo,"BC");
cipher.init(Cipher.ENCRYPT_MODE, k);
byte[] encrypted = cipher.doFinal(sha.getBytes("UTF-8"));
//System.out.println(new String(encrypted));
byte[] encoded = Base64.getEncoder().encode(encrypted);
strEncrypted = new String(encoded);
}
catch (Exception ex) {
ex.printStackTrace();
}
return strEncrypted;
}
public static PrivateKey getPrivateKey(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes);
Security.addProvider(new BouncyCastleProvider());
KeyFactory kf = KeyFactory.getInstance("RSA","BC");
return kf.generatePrivate(spec);
}
Both thee codes are generating different signatures. I feel something I am doing wrong in selecting the algorithm on Java side. I have tried with
RSA/NONE/PKCS1Padding
and
RSA/ECB/PKCS1Padding
but still, it is different signature as compared to python code.
Any lead on this will be very helpful.

Decrypt C# AES encrypted text in Java

I'm implementing in Java a third party application, but some part of the application I'm get a encrypt string like this: eGlhV2xNbmdqSFBkbEhkZDNpZ3gwQT09
and have to decrypt.
The guy who code this application is no longer here, so I need some help make a decrypt code in Java.
this is the password :CB=Z8#P#0!N2/8$%3K-9C(5S9*FDH+0Z
public static class SystemCriptografia
{
#region Atributos
private static string chave = "CB=Z8#P#0!N2/8$%3K-9C(5S9*FDH+0Z";
private static SymmetricAlgorithm algoritmo = new RijndaelManaged();
#endregion
#region Métodos
#region Métodos privados
private static string base64Encode(string data)
{
byte[] encData_byte = new byte[data.Length];
encData_byte = System.Text.Encoding.UTF8.GetBytes(data);
string encodedData = Convert.ToBase64String(encData_byte);
return encodedData;
}
private static string base64Decode(string data)
{
UTF8Encoding encoder = new UTF8Encoding();
Decoder utf8Decode = encoder.GetDecoder();
byte[] todecode_byte = Convert.FromBase64String(data);
int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
char[] decoded_char = new char[charCount];
utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
string result = new String(decoded_char);
return result;
}
private static string Criptografa(string valor, string chave)
{
byte[] ByteValor = Encoding.UTF8.GetBytes(valor);
// Seta a chave privada
algoritmo.Mode = CipherMode.CBC;
algoritmo.Key = Encoding.Default.GetBytes(chave);
algoritmo.IV = Encoding.Default.GetBytes("brasilshopsoft07");
// Interface de criptografia / Cria objeto de criptografia
ICryptoTransform cryptoTransform = algoritmo.CreateEncryptor();
MemoryStream _memoryStream = new MemoryStream();
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Write);
// Grava os dados criptografados no MemoryStream
_cryptoStream.Write(ByteValor, 0, ByteValor.Length);
_cryptoStream.FlushFinalBlock();
// Busca o tamanho dos bytes encriptados
byte[] cryptoByte = _memoryStream.ToArray();
// Converte para a base 64 string para uso posterior em um xml
return Convert.ToBase64String(cryptoByte, 0, cryptoByte.GetLength(0));
}
private static string Descriptografa(string valor, string chave)
{
// Converte a base 64 string em num array de bytes
byte[] cryptoByte = Convert.FromBase64String(valor);
// Seta a chave privada
algoritmo.Mode = CipherMode.CBC;
algoritmo.Key = Encoding.Default.GetBytes(chave);
algoritmo.IV = Encoding.Default.GetBytes("brasilshopsoft07");
// Interface de criptografia / Cria objeto de descriptografia
ICryptoTransform cryptoTransform = algoritmo.CreateDecryptor();
MemoryStream _memoryStream = new MemoryStream(cryptoByte, 0, cryptoByte.Length);
CryptoStream _cryptoStream = new CryptoStream(_memoryStream, cryptoTransform, CryptoStreamMode.Read);
// Busca resultado do CryptoStream
StreamReader _streamReader = new StreamReader(_cryptoStream);
return _streamReader.ReadToEnd();
}
#endregion
public static string ToCriptografa(this string valor)
{
return Criptografa(valor, chave);
}
public static string ToDescriptografa(this string valor)
{
return Descriptografa(valor, chave);
}
public static string ToCriptografaQueryString(this string valor)
{
return base64Encode(Criptografa(valor, chave));
}
public static string ToDescriptografaQueryString(this string valor)
{
return Descriptografa(base64Decode(valor), chave);
}
#endregion
}
and this is the java code that I'm trying to do :
public class Criptografia {
private static final String AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5PADDING";
private static final int KEY_SIZE = 256;
public static void main(final String[] args) throws Exception {
System.out.println(decryptAuthorizationString(
"eGlhV2xNbmdqSFBkbEhkZDNpZ3gwQT09", "CB=Z8#P#0!N2/8$%3K-9C(5S9*FDH+0Z"));
}
private static String decryptAuthorizationString(final String authString,
final String password) {
try {
// --- check if AES-256 is available
if (Cipher.getMaxAllowedKeyLength(AES_CBC_PKCS5PADDING) < KEY_SIZE) {
throw new IllegalStateException("Unlimited crypto files not present in this JRE");
}
// --- create cipher
final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
// --- create the key and initial vector bytes
final byte[] passwordEncoded = password.getBytes(UTF_16LE);
final byte[] keyData = Arrays.copyOf(passwordEncoded, KEY_SIZE
/ Byte.SIZE);
final byte[] ivBytes = Arrays.copyOf(keyData, cipher.getBlockSize());
// --- init cipher
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keyData, "AES"),
new IvParameterSpec(ivBytes));
// --- decode & decrypt authentication string
final byte[] authBytes = Base64.decode(authString);
final byte[] decryptedData = cipher.doFinal(authBytes);
// WARNING: may still decrypt to wrong string if
// authString or password are incorrect -
// BadPaddingException may *not* be thrown
return new String(decryptedData, UTF_16LE);
} catch (BadPaddingException | IllegalBlockSizeException e) {
// failure to authenticate
return null;
} catch (final GeneralSecurityException e) {
throw new IllegalStateException(
"Algorithms or unlimited crypto files not available", e);
}
}
}
The issues of your code:
Wrong character set chosen. If Encoding.Default is UTF-8 in C#, then the "password" and IV encodings must also be "UTF-8" in Java.
The IV is not derived from the key, but also a fixed value.
The ciphertext is actually doubly Base64 encoded. I guess somebody took "two is better than one" too literal.
Full code:
private static final String AES_CBC_PKCS5PADDING = "AES/CBC/PKCS5PADDING";
private static final int KEY_SIZE = 256;
private static String UTF_8 = "UTF-8";
public static void main(final String[] args) throws Exception {
System.out.println(decryptAuthorizationString(
"eGlhV2xNbmdqSFBkbEhkZDNpZ3gwQT09", "CB=Z8#P#0!N2/8$%3K-9C(5S9*FDH+0Z"));
}
private static String decryptAuthorizationString(final String authString,
final String password) throws UnsupportedEncodingException {
try {
// --- check if AES-256 is available
if (Cipher.getMaxAllowedKeyLength(AES_CBC_PKCS5PADDING) < KEY_SIZE) {
throw new IllegalStateException("Unlimited crypto files not present in this JRE");
}
// --- create cipher
final Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5PADDING);
// --- create the key and initial vector bytes
final byte[] passwordEncoded = password.getBytes(UTF_8);
final byte[] ivBytes = "brasilshopsoft07".getBytes(UTF_8);
// --- init cipher
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(passwordEncoded, "AES"),
new IvParameterSpec(ivBytes));
// --- decode & decrypt authentication string
final byte[] authBytes = Base64.decode(authString);
final byte[] authBytes2 = Base64.decode(authBytes);
final byte[] decryptedData = cipher.doFinal(authBytes2);
// WARNING: may still decrypt to wrong string if
// authString or password are incorrect -
// BadPaddingException may *not* be thrown
return new String(decryptedData, UTF_8);
} catch (BadPaddingException | IllegalBlockSizeException e) {
// failure to authenticate
return null;
} catch (final GeneralSecurityException e) {
throw new IllegalStateException(
"Algorithms or unlimited crypto files not available", e);
}
}
Output:
1
Notes:
Using a fixed IV is insecure. The IV must be chosen randomly in order reach semantic security. It doesn't have to be secret, so it can be sent along with the ciphertext. A common way is to prepend it to the ciphertext and slice it off before decryption.
Lose the second Base64 encoding. It just takes away space, but doesn't provide any useful feature.
Always use a specific encoding. Encoding.Default is nice for testing, but it may change depending on the machine it's running on and you will lose compatibility between multiple clients/servers.
Authenticate ciphertexts! If you don't add a message authentication code or use an authenticated mode like GCM or EAX, then an attacker may manipulate the ciphertext and you will not be able to determine this. This can go so far as to completely recover the plaintext of specific encrypted messages (padding oracle attack).

Recaptcha stoken generation (convert from Java to Ruby)

Google have provided the following example code showing how to generate a secure token for their second version of Recaptcha:
public class STokenUtils {
private static final String CIPHER_INSTANCE_NAME = "AES/ECB/PKCS5Padding";
public static final String createSToken(String siteSecret) {
String sessionId = UUID.randomUUID().toString();
String jsonToken = createJsonToken(sessionId);
return encryptAes(jsonToken, siteSecret);
}
private static final String createJsonToken(String sessionId) {
JsonObject obj = new JsonObject();
obj.addProperty("session_id", sessionId);
obj.addProperty("ts_ms", System.currentTimeMillis());
return new Gson().toJson(obj);
}
private static String encryptAes(String input, String siteSecret) {
try {
SecretKeySpec secretKey = getKey(siteSecret);
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_NAME);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return BaseEncoding.base64Url().omitPadding().encode(cipher.doFinal(input.getBytes("UTF-8")));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decryptAes(String input, String key) throws Exception {
SecretKeySpec secretKey = getKey(key);
Cipher cipher = Cipher.getInstance(CIPHER_INSTANCE_NAME);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
return new String(cipher.doFinal(
BaseEncoding.base64Url().omitPadding().decode(input)), "UTF-8");
}
private static SecretKeySpec getKey(String siteSecret){
try {
byte[] key = siteSecret.getBytes("UTF-8");
key = Arrays.copyOf(MessageDigest.getInstance("SHA").digest(key), 16);
return new SecretKeySpec(key, "AES");
} catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
}
The full code can be found at: https://github.com/google/recaptcha-java
I'm wanting to generate this token in Ruby 2.1+ and have got this far but it outputs incorrect data. I'm trying to slowly debug it, but in the meantime I'm wondering if anyone can see any obvious flaws in my process?
stoken_json = hash_to_json({'session_id' => SecureRandom.uuid, 'ts_ms' => Time.now.to_i})
cipher = OpenSSL::Cipher::AES128.new(:ECB)
private_key_digest = Digest::SHA1.hexdigest(private_key)[0...16]
cipher.encrypt
cipher.key = private_key_digest
encrypted_stoken = cipher.update(stoken_json) << cipher.final
encoded_stoken = Base64.urlsafe_encode64(encrypted_stoken).gsub(/\=+\Z/, '')
Turns out I was close. I needed to digest not hexdigest the private key:
private_key_digest = Digest::SHA1.digest(private_key)[0...16]
So the final code is:
stoken_json = hash_to_json({'session_id' => SecureRandom.uuid, 'ts_ms' => (Time.now.to_f * 1000).to_i})
cipher = OpenSSL::Cipher::AES128.new(:ECB)
private_key_digest = Digest::SHA1.digest(private_key)[0...16]
cipher.encrypt
cipher.key = private_key_digest
encrypted_stoken = cipher.update(stoken_json) << cipher.final
encoded_stoken = Base64.urlsafe_encode64(encrypted_stoken).gsub(/\=+\Z/, '')
There didn't seem to be a built-in way to strip the padding from the base64 string, thus the .gsub at the end.
I also needed the timestamp in milliseconds so that part has been modified too.
In the recaptcha gem there is a method hash_to_json that I'm using, otherwise I suspect you'd use the JSON gem.

How to pass args when calling one method from another

I have written the following code to create a key pair, store the private key locally, and then read the private key from that file.
When I try to call the methods savePrivateKey(); and retrievePrivateKey(); from testData(View view) I get an error that says (String[]) cannot be applied to (). I want to be able to call both of the above mentioned functions in testData(View view);
public class EncryptionActivity extends ActionBarActivity {
private static final String TAG = EncryptionActivity.class.getSimpleName();
TextView textPublicKey;
TextView textPrivateKey;
Button buttonTest;
TextView privateKey;
Integer n;
String FILENAME = "privateKey";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_encryption);
// output keys to screen
textPrivateKey = (TextView)findViewById(R.id.textPrivateKey);
textPrivateKey.setMovementMethod(new ScrollingMovementMethod());
// textPublicKey = (TextView)findViewById(R.id.textPublicKey);
}
private void AsymmetricAlgorithmRSA() {
// Generate key pair for 1024-bit RSA encryption and decryption
Key publicKey = null;
Key privateKey = null;
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
publicKey = kp.getPublic();
privateKey = kp.getPrivate();
} catch (Exception e) {
Log.e(TAG, "RSA key pair error");
}
//textPublicKey.setText(String.valueOf(publicKey));
//textPrivateKey.setText(String.valueOf(privateKey));
}
public void savePrivateKey(String[] args) throws FileNotFoundException {
try {
// store private key locally
String string = String.valueOf(privateKey);
FileOutputStream fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(string.getBytes());
fos.close();
}
catch (Exception e) {
Log.e(TAG, "Error saving file.");
}
}
public void retrievePrivateKey(String[] args) throws FileNotFoundException {
try {
FileInputStream fis = openFileInput(FILENAME);
StringBuffer fileContent = new StringBuffer("");
byte[] buffer = new byte[1024];
while ((n = fis.read(buffer)) != -1) ;
{
fileContent.append(new String(buffer, 0, n));
}
textPrivateKey.setText(String.valueOf(fileContent));
}
catch(IOException e) {
Log.e(TAG, "Error opening file.");
}
}
public void testData(View view){
AsymmetricAlgorithmRSA();
savePrivateKey();
retrievePrivateKey();
}
Both savePrivateKey and retrievePrivateKey accept a String[], although they do not use them. Just drop these redundant parameter specifications and you should be fine:
public void savePrivateKey() throws FileNotFoundException {
// code here...
}
public void retrievePrivateKey() throws FileNotFoundException {
// code here...
}
savePrivateKey(); --> method which has no arguments. But you have implemented a method with arguments as String[] public void savePrivateKey(String[] args) throws FileNotFoundException.. Pass as String[] as argument or change the method signature.

RSA Decryption fails due to input string [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
I have the following problem.
I have 2 functions in my code which are intended to encrypt / decrypt simple string.
SO:
I have to pass a string "someString" to the function:
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
the function doEncryption("someString") returns "[B#61decc8c"
Now I have to embed this string in a url and the server side code should get it from there.
So far it is all good , but when I call the function
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
the doDecryption("[B#61decc8c") screams with the following exception:
javax.crypto.BadPaddingException: Data must start with zero
at sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:325)
at sun.security.rsa.RSAPadding.unpad(RSAPadding.java:272)
at com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:356)
at com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:382)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at rsaendecryptor.RSAService.decrypt(RSAService.java:132)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
java.lang.NullPointerException
at java.lang.String.<init>(String.java:556)
at rsaendecryptor.RSAService.decrypt(RSAService.java:138)
at rsaendecryptor.RSAService.doDecryption(RSAService.java:180)
at rsaendecryptor.RSAEnDecrypt.main(RSAEnDecrypt.java:20)
Is there any way I can work around this? I have to pass string between the client and the server side because they can be even in different domains. Not to mention that the string will be actually generated from .Net logic and send to Java server side. Encryption to string works fine... What should I do to fix the decryption.
Here is the full class code:
public class RSAService {
/**
* String to hold name of the encryption algorithm.
*/
public static final String ALGORITHM = "RSA";
/**
* String to hold the name of the private key file.
*/
public static final String PRIVATE_KEY_FILE = "private.key";
/**
* String to hold name of the public key file.
*/
public static final String PUBLIC_KEY_FILE = "public.key";
/**
* Generate key which contains a pair of private and public key using 1024
* bytes. Store the set of keys in Prvate.key and Public.key files.
*
*/
public static void generateKey() {
try {
final KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
keyGen.initialize(1024);
final KeyPair key = keyGen.generateKeyPair();
File privateKeyFile = new File(PRIVATE_KEY_FILE);
File publicKeyFile = new File(PUBLIC_KEY_FILE);
// Create files to store public and private key
privateKeyFile.createNewFile();
if (publicKeyFile.getParentFile() != null) {
publicKeyFile.getParentFile().mkdirs();
}
publicKeyFile.createNewFile();
// Saving the Public key in a file
ObjectOutputStream publicKeyOS = new ObjectOutputStream(
new FileOutputStream(publicKeyFile));
publicKeyOS.writeObject(key.getPublic());
publicKeyOS.close();
// Saving the Private key in a file
ObjectOutputStream privateKeyOS = new ObjectOutputStream(
new FileOutputStream(privateKeyFile));
privateKeyOS.writeObject(key.getPrivate());
privateKeyOS.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* The method checks if the pair of public and private key has been
* generated.
*
* #return flag indicating if the pair of keys were generated.
*/
public static boolean areKeysPresent() {
File privateKey = new File(PRIVATE_KEY_FILE);
File publicKey = new File(PUBLIC_KEY_FILE);
if (privateKey.exists() && publicKey.exists()) {
return true;
}
return false;
}
/**
* Encrypt the plain text using public key.
*
* #param text : original plain text
* #param key :The public key
* #return Encrypted text
* #throws java.lang.Exception
*/
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 (Exception e) {
e.printStackTrace();
}
return cipherText;
}
/**
* Decrypt text using private key.
*
* #param text :encrypted text
* #param key :The private key
* #return plain text
* #throws java.lang.Exception
*/
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 (Exception ex) {
ex.printStackTrace();
}
return new String(dectyptedText);
}
public static String doEncryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Encrypt the string using the public key
inputStream = new ObjectInputStream(new FileInputStream(PUBLIC_KEY_FILE));
PublicKey publicKey = (PublicKey) inputStream.readObject();
byte[] cipherText = RSAService.encrypt(input, publicKey);
return cipherText.toString();
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Public key file is probably missing";
}
public static String doDecryption(String input) {
try {
if (!RSAService.areKeysPresent()) {
RSAService.generateKey();
}
ObjectInputStream inputStream;
// Decrypt the cipher text using the private key.
inputStream = new ObjectInputStream(new FileInputStream(PRIVATE_KEY_FILE));
PrivateKey privateKey = (PrivateKey) inputStream.readObject();
String out = decrypt(input.getBytes(), privateKey);
return out;
} catch (Exception e) {
e.printStackTrace();
}
return "ERROR: Private key file is probably missing or doesn't match the public key";
}
}
public static String doEncryption(String input)
Stop right there. String is not a container for binary data, and therefore shouldn't have been used to contain the ciphertext in the first place. It should have been passed around as a byte[].
NB when you get an exception, don't guess at what the condition was and return a string that says what it 'probably' was. It makes debugging a guessing came. Use the message that came with the exception.
Thanks to shikjohari and this article here I was able to fix my code!
in the doEncryption() method I modified the return as follows:
return (Base64.encode(cipherText)).toString();
and in doDecryption() method I modified the return as follows:
String out = decrypt(Base64.decode(input), privateKey);
return out;
You can get the full code from my first post and just edit the returns of the two methods as per this post. Hope this helps.

Categories