How can I create a RSA Encrypter with a String Public Key - java

I have a System that generates a PublicKey, then encrypts a password, then they are both stored in a database.
PK Generator
public PublicKey GetPK() {
try {
KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA");
generator.initialize(2048);
KeyPair pair = generator.generateKeyPair();
return pair.getPublic();
} catch(Exception e) {
return null;
}
}
Password Encryption
public static String EncryptPassword(PublicKey publicKey, String password) {
try {
Cipher encryptCipher = Cipher.getInstance("RSA");
encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] secretMessageBytes = password.getBytes(StandardCharsets.UTF_8);
byte[] encryptedMessageBytes = encryptCipher.doFinal(secretMessageBytes);
return Base64.getEncoder().encodeToString(encryptedMessageBytes);
} catch(Exception e) {
return null;
}
}
Then, what I try to make Login , I retrieve this Public key, encrypt my login form's password using this Public Key, and it Just don't give me the same encrypted password.
PuclicKey return
public PublicKey ReturnPK(String keyFromDatabase) throws InvalidKeySpecException, NoSuchAlgorithmException {
KeyFactory kf = KeyFactory.getInstance("RSA");
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(keyFromDatabase));
return kf.generatePublic(keySpec);
}
Compare Passwords
PublicKey pk = encryption.ReturnHash(GetUsers().getHashCode());
String encryptedPw = encryption.EncryptPassword(pk, pwd);
boolean loginState = encryptedPw.equals(dbPwd);
The var loginState always returns false. Can someone help me?

Related

How to read public/private key files for encryption when they are Base64?

I'm trying to learn RSA public/private key-pair encryption in Java.
I have the code below working. It generates a private & public key pair, writes the keys to disk, encrypts the string with the public key from disk, the decrypts with the private key from disk, and then it outputs the decrypted string.
All works great.
The next thing is, I want the key files to be the readable "-----BEGIN RSA PRIVATE KEY-----" type of key files ... so I wrote the method saveKeysToDiskBase64.
The problem is, when I write the files using saveKeysToDiskBase64, the methods that read the key files fail. That is loadPrivateKey and loadPublicKey can't read the Base64 files.
What am I missing?
public class EncryptionTest1 {
public void execute() throws Exception {
String filename = "test1";
KeyPair keyPair = EncryptionUtil.generateKeyPair();
EncryptionUtil.saveKeysToDisk(filename, keyPair);
// EncryptionUtil.saveKeysToDiskBase64(filename, keyPair);
String pvtKeyFilename = filename+".key";
String pubKeyFilename = filename+".pub";
PrivateKey privateKey = EncryptionUtil.loadPrivateKey(pvtKeyFilename);
byte[] bPrivateKey = privateKey.getEncoded();
PublicKey publicKey = EncryptionUtil.loadPublicKey(pubKeyFilename);
byte[] bPublicKey = publicKey.getEncoded();
String sOriginal = "hi this is plain text";
byte[] encryptedData = EncryptionUtil.encrypt(bPublicKey, sOriginal.getBytes());
byte[] decryptedData = EncryptionUtil.decrypt(bPrivateKey, encryptedData);
String sEncrypted = new String(encryptedData);
String sDecrypted = new String(decryptedData);
System.out.println("sOriginal = "+sOriginal);
System.out.println("sEncrypted = "+sEncrypted);
System.out.println("sDecryptedData = "+sDecrypted);
}
public static void main(String[] args) {
try {
new EncryptionTest1().execute();
} catch (Exception x) {
x.printStackTrace();
}
}
}
...
public class EncryptionUtil {
private static final String ALGORITHM = "RSA";
public static KeyPair generateKeyPair() throws NoSuchAlgorithmException, NoSuchProviderException {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance(ALGORITHM);
SecureRandom random = SecureRandom.getInstance("SHA1PRNG", "SUN");
// 2048 is keysize
keyGen.initialize(2048, random);
KeyPair generateKeyPair = keyGen.generateKeyPair();
return generateKeyPair;
}
public static void saveKeysToDisk(String name, KeyPair keyPair) {
try {
String privateFileName = name+".key";
FileOutputStream out1 = new FileOutputStream(privateFileName);
out1.write(keyPair.getPrivate().getEncoded());
out1.close();
String publicFileName = name+".pub";
FileOutputStream out2 = new FileOutputStream(publicFileName);
out2.write(keyPair.getPublic().getEncoded());
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write("-----BEGIN RSA PRIVATE KEY-----\n");
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write("\n-----END RSA PRIVATE KEY-----\n");
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write("-----BEGIN RSA PUBLIC KEY-----\n");
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write("\n-----END RSA PUBLIC KEY-----\n");
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKey(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKey(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}
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;
}
}
Great thanks to #President James K. Polk who gave me the correct answer in a comment.
Here is the Base64 related code that that worked for me ...
private static String PRIVATE_HEADER = "-----BEGIN PRIVATE KEY-----\n";
private static String PRIVATE_FOOTER = "\n-----END PRIVATE KEY-----\n";
private static String PUBLIC_HEADER = "-----BEGIN PUBLIC KEY-----\n";
private static String PUBLIC_FOOTER = "\n-----END PUBLIC KEY-----\n";
public static void saveKeysToDiskBase64(String name, KeyPair keyPair) {
try {
Base64.Encoder encoder = Base64.getEncoder();
String privateFileName = name+".key";
Writer out = new FileWriter(privateFileName);
out.write(PRIVATE_HEADER);
out.write(encoder.encodeToString(keyPair.getPrivate().getEncoded()));
out.write(PRIVATE_FOOTER);
out.close();
String publicFileName = name+".pub";
Writer out2 = new FileWriter(publicFileName);
out2.write(PUBLIC_HEADER);
out2.write(encoder.encodeToString(keyPair.getPublic().getEncoded()));
out2.write(PUBLIC_FOOTER);
out2.close();
} catch (Exception x) {
x.printStackTrace();
}
}
public static PrivateKey loadPrivateKeyBase64(String keyFile) {
PrivateKey pvt = null;
try {
/* Read all bytes from the private key file */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PRIVATE_HEADER, "");
s = s.replace(PRIVATE_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate private key. */
PKCS8EncodedKeySpec ks = new PKCS8EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pvt = kf.generatePrivate(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pvt;
}
public static PublicKey loadPublicKeyBase64(String keyFile) {
PublicKey pub = null;
try {
/* Read all the public key bytes */
Path path = Paths.get(keyFile);
byte[] bytes = Files.readAllBytes(path);
String s = new String(bytes);
s = s.replace(PUBLIC_HEADER, "");
s = s.replace(PUBLIC_FOOTER, "");
bytes = Base64.getDecoder().decode(s.getBytes());
/* Generate public key. */
X509EncodedKeySpec ks = new X509EncodedKeySpec(bytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
pub = kf.generatePublic(ks);
} catch (Exception x) {
x.printStackTrace();
}
return pub;
}

Encrypt with base64 rsa public key in Node.js

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

Decrypting returns, javax.crypto.BadPaddingException: Given final block not properly padded

Im trying to decrypt the encrypted xml file. Im getting it as a inputstream as follows.I have the correct encrypt key. but each time my program returns empty string. Every time i enter the correct key. but each time it returns Badpadding Exception.
try{
InputStream is = new ByteArrayInputStream(decryption.getFileData().getBytes());
String xmlEncryptedStr = getStringFromInputStream(is);
String xmlStr = CipherUtils.decrypt(xmlEncryptedStr, new Long(key));
.......
here is my CipherUtils.java class
.........
public static String decrypt(String strToDecrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("decrypt keyString :"+keyString);
return decrypt(strToDecrypt, keyString.getBytes());
}
public static String decrypt(String strToDecrypt,byte[] key)
{
if(strToDecrypt==null)
return strToDecrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
final String decryptedString = new String(cipher.doFinal(Base64.decodeBase64(strToDecrypt)));
System.out.println("CipherUtils.decryptedString :"+decryptedString);
return decryptedString;
}
catch (Exception e)
{
log.error("Ops!", e);
}
return null;
}
.......
For more information here is my encrypting code
public static String encrypt(String strToEncrypt,Long key)
{
String keyString=String.format("%016d", key);
//System.out.println("encrypt keyString :"+keyString);
return encrypt(strToEncrypt,keyString.getBytes());
}
public static String encrypt(String strToEncrypt,byte[] key)
{
if(strToEncrypt==null)
return strToEncrypt;
try
{
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
final SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
final String encryptedString = Base64.encodeBase64String(cipher.doFinal(strToEncrypt.getBytes()));
// System.out.println("CipherUtils.encrypt :"+encryptedString);
return encryptedString;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
I am sorry I couldn't comment so I am writing in answers section.
I faced this issue when I was using different keys though I was passing the same but i used CBC methodology.
Just to note that have you checked that encryption is also done by the AES/ECB/PKCS5Padding and not other format like AES/CBC/PKCS5Padding
Also check if key format for encryption is also having the same format like %016d of your keyValue. Also the key is 16 char long.
I created a simple AES and DESede encryption utility and it worked fine.
private static final byte[] keyValue = new String(
"CjxI&S#V&#DSA_S0dA-SDSA$").getBytes();
public static void main(String[] args) throws Exception {
Client cli = new Client();
System.out.println(cli.encrypt("your password for encryption"));
Client cli1 = new Client();
System.out.println(cli1.decrypt("fTsgVQtXvv49GynHazT4OGZ4Va1H57d+6AM+44Ex040="));
}
public String encrypt(String Data) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(Data.getBytes());
String encryptedValue = DatatypeConverter.printBase64Binary(encVal);
// String encryptedValue = new BASE64Encoder().encode(encVal);
return encryptedValue;
}
public String decrypt(String encryptedData) throws Exception {
Key key = new SecretKeySpec(keyValue, "AES");
Cipher c = Cipher.getInstance("AES/ECB/PKCS5Padding");
c.init(Cipher.DECRYPT_MODE, key);
byte[] decordedValue = DatatypeConverter
.parseBase64Binary(encryptedData);
byte[] decValue = c.doFinal(decordedValue);
String decryptedValue = new String(decValue);
return decryptedValue;
}

RSA Bad Padding Exception

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.

read public key invalid key format java

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;
}

Categories

Resources