Below I try to send message in multicast socket through group and to provide encryption:
Encrypt the data with the symmetric key
Encrypt the symmetric key with rsa
send the encrypted key and the data
Decrypt the encrypted symmetric key with rsa
decrypt the data with the symmetric key
But I am getting this error
javax.crypto.BadPaddingException: Decryption error at java.base/sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:378) at java.base/sun.security.rsa.RSAPadding.unpad(RSAPadding.java:290) at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:366) at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392) at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2208) at Security.RSADecryption(Symmetra.java:63) at ReadThread.run(Symmetra.java:202) at java.base/java.lang.Thread.run(Thread.java:835)
I think I did not understood encryption decryption properly.
See below for the code:
class Security
{
public static SecretKey createAESKey() throws Exception
{
KeyGenerator generator = KeyGenerator.getInstance("AES");
generator.init(128); // The AES key size in number of bits
SecretKey key = generator.generateKey();
return key;
}
public static KeyPair generateRSAkeyPair() throws Exception
{
//SecureRandom secureRandom = new SecureRandom();
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
//KeyGenerator keyGenerator = KeyGenerator.getInstance("RSA");
keyPairGenerator.initialize(4096);
KeyPair pair = keyPairGenerator.generateKeyPair();
return pair;
}
public static byte[] AESEncryption(String plaintext, SecretKey secKey) throws Exception
{
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE,secKey);
byte[] cipherText = cipher.doFinal(plaintext.getBytes());
return cipherText;
}
public static byte[] RSAEncryption(PublicKey publicKey, SecretKey key) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//cipher.update(plaintext.getBytes());
byte [] encryptedKey = cipher.doFinal(key.getEncoded());
System.out.println(encryptedKey.length);
return encryptedKey;
}
public static byte[] RSADecryption(byte[] encryptedKey, PrivateKey privateKey) throws Exception
{
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte check[] = cipher.doFinal(encryptedKey);
return cipher.doFinal(encryptedKey);
}
public static String AESDecryption(byte[] decryptedKey, byte[] text) throws Exception
{
SecretKey originalKey = new SecretKeySpec(decryptedKey , 0, decryptedKey.length, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, originalKey);
byte[] plaintext = cipher.doFinal(text);
return new String(plaintext);
}
public static KeyPair generate() throws Exception
{
KeyPair keyPair = generateRSAkeyPair();
return keyPair;
}
}
public class TestDemo extends Security
{
public static void main(String args[])
{
KeyPair keyPair = generate();
SecretKey key = createAESKey();
byte[] cipherText = AESEncryption(message,key);
byte[] encryptedKey = RSAEncryption(keyPair.getPublic(), key);
DatagramPacket datagram = new
DatagramPacket(cipherText,cipherText.length,group,port); // It carries encrpyted message
// It carries symmetric key encrypted by RSA
DatagramPacket datagram2 = new
DatagramPacket(encryptedKey,encryptedKey.length,group,port);
socket.send(datagram);
socket.send(datagram2);
}
}
class ReadThread extends Security
{
KeyPair keyPair;
SecretKey key;
try
{
keyPair = generate();
key = createAESKey();
byte[] buffer = new byte[ReadThread.MAX_LEN];
DatagramPacket datagram = new DatagramPacket(buffer,buffer.length,group,port);
byte[] keyBuffer = new byte[512];
DatagramPacket datagram2 = new
DatagramPacket(keyBuffer,keyBuffer.length,group,port);
String message;
try
{
socket.receive(datagram);
socket.receive(datagram2);
byte[] decryptKey = RSADecryption(keyBuffer,keyPair.getPrivate());
String decryptText = AESDecryption(decryptKey, buffer);
message = decryptText;
if(!message.startsWith(Symmetra.name))
System.out.println(message);
}
catch(IOException e)
{
System.out.println("Socket closed!");
}
}
}
Related
I am trying a program to first encrypt and decrypt a string and in between encoding it into 64base and then decoding it into 64base(this is required). But I am getting the below error. What is the possible fix?
Exception in thread "main" javax.crypto.BadPaddingException: Decryption error
at java.base/sun.security.rsa.RSAPadding.unpadV15(RSAPadding.java:378)
at java.base/sun.security.rsa.RSAPadding.unpad(RSAPadding.java:290)
at java.base/com.sun.crypto.provider.RSACipher.doFinal(RSACipher.java:366)
at java.base/com.sun.crypto.provider.RSACipher.engineDoFinal(RSACipher.java:392)
at java.base/javax.crypto.Cipher.doFinal(Cipher.java:2202)
at CryptographyExample.decrypt(encryt_decrypt.java:53)
at CryptographyExample.main(encryt_decrypt.java:88)
My code
class CryptographyExamples {
private static final String ALGORITHM = "RSA";
public static byte[] encrypt(byte[] publicKey, byte[] inputData) throws Exception {
PublicKey key = KeyFactory.getInstance(ALGORITHM).generatePublic(new X509EncodedKeySpec(publicKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encryptedBytes = cipher.doFinal(inputData);
return encryptedBytes;
}
public static byte[] decrypt(byte[] privateKey, byte[] inputData) throws Exception {
PrivateKey key = KeyFactory.getInstance(ALGORITHM).generatePrivate(new PKCS8EncodedKeySpec(privateKey));
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedBytes = cipher.doFinal(inputData);
return decryptedBytes;
}
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
// 512 is keysize
keyGen.initialize(512, random);
KeyPair generateKeyPair = keyGen.generateKeyPair();
return generateKeyPair;
}
public static MessageDigest md;
public static void main(String[] args) throws Exception {
String originalMessage = "The message to be encrypted and sent";
md = MessageDigest.getInstance("SHA-256");
KeyPair generateKeyPair = generateKeyPair();
byte[] publicKey = generateKeyPair.getPublic().getEncoded();
byte[] privateKey = generateKeyPair.getPrivate().getEncoded();
byte[] encryptedData = encrypt(publicKey, originalMessage.getBytes());
byte[] shaEncryptedData = md.digest(encryptedData);
String shaEncryption64 = Base64.getEncoder().encodeToString(shaEncryptedData);
byte[] decryptedData = decrypt(privateKey, Base64.getDecoder().decode(shaEncryption64));
System.out.println("Decrypted Message: " + new String(decryptedData));
}
}
First of all, I'm a beginner programmer
I created a pair of keys(rsa) on the user's side(android). I intend to send the public key to the server for future operations as a base64 string, and with the public key I will encode the next data and send it to the user.I use the server side of the nodejs. Unfortunately, all the content written in The internet did not mention encrypt with the base64 public key or at least I did not see it. Can someone help me? Thank
this my java code:
public class GenKey {
private String stringPrivateKey;
private String stringPublicKey;
#RequiresApi(api = Build.VERSION_CODES.O)
public GenKey() throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512,new SecureRandom());//1024 or 2048
KeyPair kp = kpg.generateKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
this.stringPublicKey = Base64.encodeToString(publicKey.getEncoded(), DEFAULT);
this.stringPrivateKey =Base64.encodeToString(privateKey.getEncoded(), DEFAULT);
}
public String getPublicKey(){
return stringPublicKey;
}
public String getPrivateKey(){
return stringPrivateKey;
}
}
and:
public class EncryptDecrypt {
public static String encrypt(String publicKey, String cleartext) throws Exception {
X509EncodedKeySpec ks = new X509EncodedKeySpec(Base64.decode(publicKey,DEFAULT));
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey pub = kf.generatePublic(ks);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pub);
byte[] encMsgBinary = cipher.doFinal(cleartext.getBytes());
return Base64.encodeToString(encMsgBinary, DEFAULT);
}
public static String decrypt(String privateKey, String ciphertext) throws Exception {
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(Base64.decode(privateKey,DEFAULT));
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey pvt = kf.generatePrivate(ks);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pvt);
byte [] encrypted = Base64.decode(ciphertext,DEFAULT);
return new String(cipher.doFinal(encrypted));
}
}
solved.use node-rsa;
var NodeRSA = require('node-rsa');
var key = new NodeRSA();
var public="-----BEGIN PUBLIC KEY-----\n"+publicKey+"\n"+"-----END PUBLIC KEY-----";
key.importKey(public,"pkcs8-public-pem");
var encrypted = key.encrypt(text, 'base64');
return encrypted;
and in java EncryptDecrypt class
Cipher.getInstance("RSA/ECB/OAEPWithSHA1AndMGF1Padding");
instead of
Cipher.getInstance("RSA");
see:
enter link description here
I am trying to RSA encrypt data on Android and send it to server(spring).
getting BadPaddingException :
Approach:
server send public key in a string, which i convert to PublicKey Object and send data from App after encryption as a string.
server has a private key string , which is converted to PublicKey object and then data is decrypted.
Any Help would be much appreciated.
generation of key :
public static KeyPair generateKeyPairRSA() {
try {
SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(1024, random);
KeyPair keyPair = keyGen.generateKeyPair();
return keyPair;
} catch (Exception e) {
Log.d(TAG,e.getLocalizedMessage());
}
return null;
}
public byte[] RSAEncrypt(final String plain, PublicKey publicKey) throws Exception {
Cipher cipher = Cipher.getInstance(ALGO_RSA);
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedBytes = cipher.doFinal(plain.getBytes());
return encryptedBytes;
}
public static PublicKey loadPublicKey1(String stored) throws Exception{
byte[] data = Base64.decode(stored.getBytes());
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance(ALGO_RSA);
return fact.generatePublic(spec);
}
Server Methods :
public byte[] decryptRSA(String inputData) throws Exception {
byte[] inputBytes = Base64.decodeBase64(inputData);
PrivateKey key = loadPrivateKey(getPrivateKey());
Cipher cipher1 = Cipher.getInstance("RSA");
cipher1.init(Cipher.DECRYPT_MODE, key);
return cipher1.doFinal(inputBytes);
}
private PrivateKey loadPrivateKey(String key64) throws Exception {
byte[] pkcs8EncodedBytes = Base64.decodeBase64(key64);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8EncodedBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(keySpec);
}
Got it Working.
So diffrent libs have differenet implementation of Cipher.
so while calling
Cipher.getInstance("RSA/ECB/PKCS1Padding");
Explicitly mention encryption mode and padding.
Hope it helps somebody.
I am trying to encrypt something using AES and then save. The problem is that its working on my computer, but not on android. What is the problem?
This is main AES class:
public class AESUtils {
public static byte[] encrypt(SecretKeySpec skeySpec, byte[] clear) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
return encrypted;
}
public static byte[] decrypt(SecretKeySpec skeySpec, byte[] encrypted) throws Exception {
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(encrypted);
return decrypted;
}
public static SecretKeySpec getKey(String key) throws NoSuchAlgorithmException {
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(key.getBytes());
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, sr);
return new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
}
}
FileSaveClass:
public class FileUtils {
public static void save(FileHandle file, byte[] bytes) {
file.writeBytes(bytes, false);
}
public static byte[] load(FileHandle file) {
return file.readBytes();
}
}
And it's that i am trying to do:
SecretKeySpec skeySpec = AESUtils.getKey("Any key");
// if file not exist - create new, else open it, add any symbol and save it again
if (!fileHandle.exists()) {
byte[] encodedBytes = AESUtils.encrypt(skeySpec, text.getBytes());
SaveUtils.save(fileHandle, encodedBytes);
} else {
byte[] clearBytes = AESUtils.decrypt(skeySpec, SaveUtils.load(fileHandle));
text = new String(clearBytes);
text += "1";
byte[] encodedBytes = AESUtils.encrypt(skeySpec, text.getBytes());
SaveUtils.save(fileHandle, encodedBytes);
System.out.println(text);
}
Your device may have an API version greater than or equal to 17 (Jelly Bean). Changing the static method getKey(String key) to the following code may solve the problem:
public static SecretKeySpec getKey(String key) throws NoSuchAlgorithmException {
KeyGenerator kg = KeyGenerator.getInstance("AES");
final int JELLY_BEAN_4_2 = 17;
SecureRandom sr = null;
if (Gdx.app.getType() == ApplicationType.Android) {
if (Gdx.app.getVersion() >= JELLY_BEAN_4_2) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
} else if (Gdx.app.getType() == ApplicationType.iOS) {
sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
} else {
sr = SecureRandom.getInstance("SHA1PRNG");
}
sr.setSeed(key.getBytes());
kg.init(128, sr);
return new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");
}
I have code:
public PublicKey read_public_key(String path)
throws IOException, NoSuchAlgorithmException,
InvalidKeySpecException {
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
FileInputStream pubKeyStream = new FileInputStream(path);
byte[] pubKeyBytes = new byte[(int)path.length()];
pubKeyStream.read(pubKeyBytes);
pubKeyStream.close();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(pubKeyBytes);
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
return pubKey;
}
But I get invalid key format How do I get public key from .pub file? Later I need to:
private 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("RSA/None/PKCS1Padding");
// 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;
}