I would like some help as this is my first time in coding cryptography code.
The encryption code appears to be working correctly, but the decryption throws an error.
The error I get is:
de.flexiprovider.api.exceptions.BadPaddingException: invalid ciphertext
in the decrypt function towards the end of the code, which is marked as a comment
// ERROR THROWN HERE! ..............................
I have included all the imports, please excuse this, as thought it maybe relevant to the issue.
Any help as to what I am doing wrong will be greatly appreciated, thanks very much.
Code:
import java.io.UnsupportedEncodingException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Security;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import android.app.Activity;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import de.flexiprovider.common.ies.IESParameterSpec;
import de.flexiprovider.core.FlexiCoreProvider;
import de.flexiprovider.ec.FlexiECProvider;
import de.flexiprovider.ec.parameters.CurveParams;
import de.flexiprovider.ec.parameters.CurveRegistry.BrainpoolP384r1;
import de.flexiprovider.pki.PKCS8EncodedKeySpec;
import de.flexiprovider.pki.X509EncodedKeySpec;
public class MainActivity extends Activity {
private static PublicKey PublicKey;
private static PrivateKey PrivateKey;
private static String PubKey;
private static String PrvKey;
private static String message = "Hello World";
private static String encryptedMessage;
private static String decryptedMessage;
private final static String TAG = "ERROR: ";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
try {
Security.addProvider(new FlexiCoreProvider());
Security.addProvider(new FlexiECProvider());
// instantiate the elliptic curve key pair generator
KeyPairGenerator kpg = KeyPairGenerator.getInstance("ECIES", "FlexiEC");
// choose the curve
CurveParams ecParams = new BrainpoolP384r1();
// Initialize the key pair generator
kpg.initialize(ecParams, new SecureRandom());
KeyPair keyPair = kpg.generateKeyPair();
// generate the public key
PublicKey = keyPair.getPublic();
// generate private key
PrivateKey = keyPair.getPrivate();
}
catch (Exception e) {
Log.e(TAG, e.toString());
}
// I'm converting keys to strings here as the public keys will be stored on a server
// database and the private keys will be stored in the application preferences file
// this private key storage is maybe not optimum, but at this point I just want to
// simulate a messaging encryption/decryption process for testing purposes
// convert public key to a string
PubKey = Base64.encodeToString(PublicKey.getEncoded(), Base64.DEFAULT);
Log.d("PubKey: ", PubKey);
// convert private key to a string
PrvKey = Base64.encodeToString(PrivateKey.getEncoded(), Base64.DEFAULT);
Log.d("PrvKey: ", PrvKey);
// encrypt the message with the public key
encryptedMessage = encryptMessage(PubKey, message);
// report if the public key has not been regenerated correctly
if (encryptedMessage == null) {
Log.d("PUBLIC_KEY_REGENERATE_ERROR: ", encryptedMessage);
}
// decrypt the message with the private key
decryptedMessage = decryptMessage(PrvKey, encryptedMessage);
// report if the private key has not been regenerated correctly
if (encryptedMessage == null) {
Log.d("PRIVATE_KEY_REGENERATE_ERROR: ", decryptedMessage);
}
}
// encrypt function
public static String encryptMessage(String publicKey, String message) {
KeyFactory keyFactory = null;
PublicKey pubkey = null;
Cipher cipher = null;
byte[] PLAINTEXT_MESSAGE = message.getBytes();
Log.d("PLAINTEXT_MESSAGE: ", message);
Security.addProvider(new FlexiCoreProvider());
Security.addProvider(new FlexiECProvider());
// Base64 decode the publicKey string into a byte array
byte[] decodedPublicKey = Base64.decode(publicKey, Base64.DEFAULT);
try {
// instantiate a X509EncodedKeySpec
X509EncodedKeySpec X509spec = new X509EncodedKeySpec(decodedPublicKey);
keyFactory = KeyFactory.getInstance("ECIES", "FlexiEC");
// re-generate the public key
pubkey = keyFactory.generatePublic(X509spec);
// sanity check, return null on inequality
if (!pubkey.equals(PublicKey)) {
return null;
}
cipher = Cipher.getInstance("ECIES", "FlexiEC");
IESParameterSpec IESspec = new IESParameterSpec("AES256_CBC", "HmacSHA512", null, null);
cipher.init(Cipher.ENCRYPT_MODE, pubkey, IESspec);
}
catch (Exception e) {
Log.e(TAG, e.toString());
}
// encrypt the message
byte[] encryptedData = null;
try {
encryptedData = cipher.doFinal(PLAINTEXT_MESSAGE);
}
catch (IllegalBlockSizeException e) {
Log.e(TAG, e.toString());
}
catch (BadPaddingException e) {
Log.e(TAG, e.toString());
}
String encryptedMessage = null;
try {
encryptedMessage = new String(encryptedData, "UTF-8");
}
catch (UnsupportedEncodingException e) {
Log.e(TAG, e.toString());
}
Log.d("encryptedMessage: ", encryptedMessage);
return encryptedMessage;
}
// decrypt function
public static String decryptMessage(String privateKey, String message) {
KeyFactory keyFactory = null;
PrivateKey prvkey = null;
Cipher cipher = null;
byte[] ENCRYPTED_MESSAGE = message.getBytes();
Log.d("ENCRYPTED_MESSAGE: ", message);
Security.addProvider(new FlexiCoreProvider());
Security.addProvider(new FlexiECProvider());
try {
// Base64 decode the privateKey string into a byte array
byte[] decodedPrivateKey = Base64.decode(privateKey, Base64.DEFAULT);
// instantiate a PKCS8EncodedKeySpec
PKCS8EncodedKeySpec PKCS8spec = new PKCS8EncodedKeySpec(decodedPrivateKey);
keyFactory = KeyFactory.getInstance("ECIES", "FlexiEC");
// re-generate the private key
prvkey = keyFactory.generatePrivate(PKCS8spec);
// sanity check, return null on inequality
if (!prvkey.equals(PrivateKey)) {
return null;
}
cipher = Cipher.getInstance("ECIES", "FlexiEC");
IESParameterSpec IESspec = new IESParameterSpec("AES256_CBC", "HmacSHA512", null, null);
cipher.init(Cipher.DECRYPT_MODE, prvkey, IESspec);
}
catch (Exception e) {
Log.e(TAG, e.toString());
}
// decrypt the message
byte[] decryptedData = null;
try {
decryptedData = cipher.doFinal(ENCRYPTED_MESSAGE);
// ERROR THROWN HERE! ..............................
// de.flexiprovider.api.exceptions.BadPaddingException: invalid ciphertext
}
catch (IllegalBlockSizeException e) {
Log.e(TAG, e.toString());
}
catch (BadPaddingException e) {
Log.e(TAG, e.toString());
}
String decryptedMessage = null;
try {
decryptedMessage = new String(decryptedData, "UTF-8");
}
catch (UnsupportedEncodingException e) {
Log.e(TAG, e.toString());
}
Log.d("decryptedMessage: ", decryptedMessage);
return decryptedMessage;
}
}
You cannot just use the cipher text as input for the String
constructor, as you are doing in this line:
encryptedMessage = new String(encryptedData, "UTF-8");
You will have to use an encoding such as Base 64 as you did with the keys, if you want to communicate the cipher text using strings instead of bytes.
Encryption will result in data that looks like random bytes. Not all bytes have a character equivalent. The result of the conversion depends on the character encoding. UTF-8 may use many bytes, and many combinations won't result in correct characters. Java silently converts these, check the Charset
and related classes for more information.
来源:https://stackoverflow.com/questions/13713991/badpaddingexception-invalid-ciphertext