I am implementing RSA in java I have encountered a code which is given below it is showing plaintext in numeric form after decrypting the plaintext, but I want it in simple english which I entered. I don't want to use the java api.
TestRsa.Java
import java.io.IOException;
import java.math.BigInteger;
import java.util.Random;
public class TestRsa {
private BigInteger p, q;
private BigInteger n;
private BigInteger PhiN;
private BigInteger e, d;
public TestRsa() {
initialize();
}
public void initialize() {
int SIZE = 512;
/* Step 1: Select two large prime numbers. Say p and q. */
p = new BigInteger(SIZE, 15, new Random());
q = new BigInteger(SIZE, 15, new Random());
/* Step 2: Calculate n = p.q */
n = p.multiply(q);
/* Step 3: Calculate ø(n) = (p - 1).(q - 1) */
PhiN = p.subtract(BigInteger.valueOf(1));
PhiN = PhiN.multiply(q.subtract(BigInteger.valueOf(1)));
/* Step 4: Find e such that gcd(e, ø(n)) = 1 ; 1 < e < ø(n) */
do {
e = new BigInteger(2 * SIZE, new Random());
} while ((e.compareTo(PhiN) != 1)
|| (e.gcd(PhiN).compareTo(BigInteger.valueOf(1)) != 0));
/* Step 5: Calculate d such that e.d = 1 (mod ø(n)) */
d = e.modInverse(PhiN);
}
public BigInteger encrypt(BigInteger plaintext) {
return plaintext.modPow(e, n);
}
public BigInteger decrypt(BigInteger ciphertext) {
return ciphertext.modPow(d, n);
}
public static void main(String[] args) throws IOException {
TestRsa app = new TestRsa();
int plaintext;
System.out.println("Enter any character : ");
plaintext = System.in.read();
BigInteger bplaintext, bciphertext;
bplaintext = BigInteger.valueOf((long) plaintext);
bciphertext = app.encrypt(bplaintext);
System.out.println("Plaintext : " + bplaintext.toString());
System.out.println("Ciphertext : " + bciphertext.toString());
bplaintext = app.decrypt(bciphertext);
System.out.println("After Decryption Plaintext : "
+ bplaintext.toString());
}
}
My RSA Class:
package com.infovale.cripto;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class RSA {
static String kPublic = "";
static String kPrivate = "";
public RSA()
{
}
public String Encrypt(String plain) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
String encrypted;
byte[] encryptedBytes;
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
kPublic = bytesToString(publicKeyBytes);
kPrivate = bytesToString(privateKeyBytes);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
encryptedBytes = cipher.doFinal(plain.getBytes());
encrypted = bytesToString(encryptedBytes);
return encrypted;
}
public String Decrypt(String result) throws NoSuchAlgorithmException,
NoSuchPaddingException, InvalidKeyException,
IllegalBlockSizeException, BadPaddingException {
byte[] decryptedBytes;
byte[] byteKeyPrivate = stringToBytes(kPrivate);
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = null;
try {
privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(byteKeyPrivate));
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
String decrypted;
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
decryptedBytes = cipher.doFinal(stringToBytes(result));
decrypted = new String(decryptedBytes);
return decrypted;
}
public String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
}
try these lines:
System.out.println("Plaintext : " + new String(bplaintext.toByteArray() ) );
System.out.println("Ciphertext : " + new String(bciphertext.toByteArray() ) );
bplaintext = app.decrypt(bciphertext);
System.out.println("After Decryption Plaintext : " + new String(bplaintext.toByteArray() ) );
I edited Elton Da Costa's class a little bit adding that feature to convert Public key from String to PublicKey class. Because the user of this class might ultimately want to give out the public key to a third party for encryption of the message and keep the private key with himself for decryption.
package com.custom.util;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class RSA {
static String kPublic = "";
static String kPrivate = "";
public RSA() {
}
public class KeyPairStrings {
private String pubKey;
private String privKey;
public String getPubKey() {
return pubKey;
}
public String getPrivKey() {
return privKey;
}
#Override
public String toString() {
return "KeyPairStrings [pubKey=" + pubKey + ", privKey=" + privKey + "]";
}
}
public KeyPairStrings getKeyPair() throws NoSuchAlgorithmException{
KeyPairStrings keyPairStrings = new RSA.KeyPairStrings();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
byte[] publicKeyBytes = publicKey.getEncoded();
byte[] privateKeyBytes = privateKey.getEncoded();
keyPairStrings.pubKey = bytesToString(publicKeyBytes);
keyPairStrings.privKey = bytesToString(privateKeyBytes);
return keyPairStrings ;
}
public String encrypt(String text , String pubKey) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException{
byte[] pubKeyByte = stringToBytes(pubKey) ;
KeyFactory kf = KeyFactory.getInstance("RSA");
PublicKey publicKey = null;
try {
publicKey = kf.generatePublic(new X509EncodedKeySpec(pubKeyByte));
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, publicKey );
byte[] encryptedBytes = cipher.doFinal(text.getBytes());
String encrypted = bytesToString(encryptedBytes);
return encrypted;
}
public String decrypt(String encryptedText , String privKey) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
byte[] privKeyByte = stringToBytes(privKey) ;
KeyFactory kf = KeyFactory.getInstance("RSA");
PrivateKey privateKey = null;
try {
privateKey = kf.generatePrivate(new PKCS8EncodedKeySpec(privKeyByte));
} catch (InvalidKeySpecException e) {
e.printStackTrace();
}
String decrypted;
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptedBytes = cipher.doFinal(stringToBytes(encryptedText));
decrypted = new String(decryptedBytes);
return decrypted;
}
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException {
String text = "hello" ;
RSA rsa = new RSA();
KeyPairStrings keyPairStrings = rsa.getKeyPair() ;
System.out.println(keyPairStrings);
String encrypted = rsa.encrypt(text, keyPairStrings.getPubKey());
System.out.println("encrypted : "+encrypted);
String textResult = rsa.decrypt(encrypted, keyPairStrings.getPrivKey());
System.out.println("textResult : "+textResult);
}
public static String bytesToString(byte[] b) {
byte[] b2 = new byte[b.length + 1];
b2[0] = 1;
System.arraycopy(b, 0, b2, 1, b.length);
return new BigInteger(b2).toString(36);
}
public byte[] stringToBytes(String s) {
byte[] b2 = new BigInteger(s, 36).toByteArray();
return Arrays.copyOfRange(b2, 1, b2.length);
}
}
Instead of this (which only reads the first character):
int plaintext;
plaintext = System.in.read();
bplaintext = BigInteger.valueOf((long) plaintext);
Use this (to read the string):
byte[] plaintext;
plaintext = new Scanner(System.in).nextLine().getBytes();
bplaintext = new BigInteger(plaintext);
Then add this to the end (to convert the decrypted BigInteger back to a string)
System.out.println("Original String: " + new String(bplaintext.toByteArray()));
Related
I have this code which encrypts and decrypts text messages using Elliptic curve cryptography simultaneously. I divide split the code into two parts: encryption and decryption. But during decryption I get errors. Can someone resolve those for me.
Shared code:
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.Scanner;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.util.Enumeration;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class ENCRYPT {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
System.out.println("IV :" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Message:");
String plainText = sc.nextLine();
System.out.println("Original plaintext message: " + plainText);
// Initialize two key pairs
KeyPair keyPairA = generateECKeys();
KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
keyPairB.getPublic());
SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
String cipherText = encryptString(secretKeyA, plainText);
System.out.println("Encrypted cipher text: " + cipherText);
String encodedKeyA = Base64.getEncoder().encodeToString(secretKeyA.getEncoded());
String encodedKeyB = Base64.getEncoder().encodeToString(secretKeyB.getEncoded());
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println("Secret Key A: " + encodedKeyA);
System.out.println("Secret Key B: " + encodedKeyB);
}
public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException |
NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException |
NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
public static String encryptString(SecretKey key, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
UnsupportedEncodingException | ShortBufferException |
IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
public static String decryptString(SecretKey key, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(key.getEncoded(),
key.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength += cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
Decryption code:
//Decrypt
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.interfaces.ECPublicKey;
import java.security.spec.ECParameterSpec;
import java.security.spec.ECPoint;
import java.security.spec.ECPublicKeySpec;
import java.util.Base64;
import java.util.Scanner;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.ECNamedCurveTable;
import org.bouncycastle.jce.spec.ECNamedCurveParameterSpec;
public class Decrypt {
public static byte[] iv = new SecureRandom().generateSeed(16);
public static void main(String[] args) {
/* Scanner scc = new Scanner(System.in);
System.out.println("Enter IV:");
String ivate = scc.nextLine();
byte[] iv = ivate.getBytes();
*/
System.out.println("IV=" + iv);
Scanner sc = new Scanner(System.in); // object for scanner
System.out.println("Enter your Cipher:");
String cipherText = sc.nextLine();
Scanner scanner = new Scanner(System.in); // object for scanner
System.out.println("Enter your Secret Key B:");
String encodedKeyB = scanner.nextLine();
byte[] decodedKeyB = Base64.getDecoder().decode(encodedKeyB);
SecretKey secretKeyB = new SecretKeySpec(decodedKeyB, 0, decodedKeyB.length, "AES");
// Initialize two key pairs
// KeyPair keyPairA = generateECKeys();
// KeyPair keyPairB = generateECKeys();
// Create two AES secret keys to encrypt/decrypt the message
//SecretKey secretKeyA = generateSharedSecret(keyPairA.getPrivate(),
// keyPairB.getPublic());
//SecretKey secretKeyB = generateSharedSecret(keyPairB.getPrivate(),
// keyPairA.getPublic());
// Encrypt the message using 'secretKeyA'
// String cipherText = encryptString(secretKeyA, plainText);
// System.out.println("Encrypted cipher text: " + cipherText);
// Decrypt the message using 'secretKeyB'
String decryptedPlainText = decryptString(secretKeyB, cipherText);
System.out.println("Decrypted cipher text: " + decryptedPlainText);
System.out.println(" cipher text: " + cipherText);
System.out.println("Key: " + secretKeyB);
}
/* public static KeyPair generateECKeys() {
try {
ECNamedCurveParameterSpec parameterSpec = ECNamedCurveTable.getParameterSpec("brainpoolp256r1");
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(
"ECDH", "BC");
keyPairGenerator.initialize(parameterSpec);
KeyPair keyPair = keyPairGenerator.generateKeyPair();
return keyPair;
} catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException
| NoSuchProviderException e) {
e.printStackTrace();
return null;
}
}
*/
/* public static SecretKey generateSharedSecret(PrivateKey privateKey,
PublicKey publicKey) {
try {
KeyAgreement keyAgreement = KeyAgreement.getInstance("ECDH", "BC");
keyAgreement.init(privateKey);
keyAgreement.doPhase(publicKey, true);
SecretKey key = keyAgreement.generateSecret("AES");
return key;
} catch (InvalidKeyException | NoSuchAlgorithmException
| NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
}
*/
/* public static String encryptString(SecretKey secretkeyB, String plainText) {
try {
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] plainTextBytes = plainText.getBytes("UTF-8");
byte[] cipherText;
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
cipherText = new byte[cipher.getOutputSize(plainTextBytes.length)];
int encryptLength = cipher.update(plainTextBytes, 0,
plainTextBytes.length, cipherText, 0);
encryptLength += cipher.doFinal(cipherText, encryptLength);
return bytesToHex(cipherText);
} catch (NoSuchAlgorithmException | NoSuchProviderException
| NoSuchPaddingException | InvalidKeyException
| InvalidAlgorithmParameterException
| UnsupportedEncodingException | ShortBufferException
| IllegalBlockSizeException | BadPaddingException e) {
e.printStackTrace();
return null;
}
}
*/
public static String decryptString(SecretKey secretkeyB, String cipherText) {
try {
Key decryptionKey = new SecretKeySpec(secretkeyB.getEncoded(),
secretkeyB.getAlgorithm());
IvParameterSpec ivSpec = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
byte[] cipherTextBytes = hexToBytes(cipherText);
byte[] plainText;
cipher.init(Cipher.DECRYPT_MODE, decryptionKey, ivSpec);
plainText = new byte[cipher.getOutputSize(cipherTextBytes.length)];
int decryptLength = cipher.update(cipherTextBytes, 0,
cipherTextBytes.length, plainText, 0);
decryptLength = cipher.doFinal(plainText, decryptLength);
return new String(plainText, "UTF-8");
} catch (NoSuchAlgorithmException | NoSuchProviderException |
NoSuchPaddingException | InvalidKeyException |
InvalidAlgorithmParameterException |
IllegalBlockSizeException | BadPaddingException |
ShortBufferException | UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
}
public static String bytesToHex(byte[] data, int length) {
String digits = "0123456789ABCDEF";
StringBuffer buffer = new StringBuffer();
for (int i = 0; i != length; i++) {
int v = data[i] & 0xff;
buffer.append(digits.charAt(v >> 4));
buffer.append(digits.charAt(v & 0xf));
}
return buffer.toString();
}
public static String bytesToHex(byte[] data) {
return bytesToHex(data, data.length);
}
public static byte[] hexToBytes(String string) {
int length = string.length();
byte[] data = new byte[length / 2];
for (int i = 0; i < length; i += 2) {
data[i / 2] = (byte)((Character.digit(string.charAt(i), 16) << 4) + Character
.digit(string.charAt(i + 1), 16));
}
return data;
}
}
Artjom B is completely right with regards to noting that the key generation needs to take place for each party separately. What you need to do is to generate one class that represents either party or that just contains the shared methods such as generateKeyPair, deriveSecretKey and of course receivePublicKey. You should be able to use that for both the Sender and Receiver classes.
Just typing in the secret key completely destroys the idea of performing key agreement in the first place.
However, this is not the issue with your code.
You are using a static random IV during decryption. An IV should be random during encryption and then communicated with the party decrypting the ciphertext. This is normally accomplished by prefixing the IV to the ciphertext.
You need to generate the IV within the encryption method instead of making it static. Reusing an IV the way you do completely destroys confidentiality for GCM mode as it uses CTR mode underneath.
Note that the GCM mode IV should be 12 bytes, not 16. GCM mode IV's may just be unique (a nonce, number-used-once) rather than random.
i want to encrypt a password with a key from server and decrypt the encrypted password in serverside. this is the code i have used in my application
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package publicprivatekey;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import javax.crypto.*;
/**
*
* #author Rajorshi
*/
public class PublicPrivateKey {
public static String getEncrypted(String data, String Key) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidKeySpecException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(Key.getBytes())));
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
byte[] encryptedbytes = cipher.doFinal(data.getBytes());
return new String(Base64.getEncoder().encode(encryptedbytes));
}
public static String getDecrypted(String data, String Key) throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
PrivateKey pk = KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(Key.getBytes())));
cipher.init(Cipher.DECRYPT_MODE, pk);
byte[] encryptedbytes = cipher.doFinal(Base64.getDecoder().decode(data.getBytes()));
return new String(encryptedbytes);
}
public static void main(String[] args) throws NoSuchAlgorithmException, NoSuchProviderException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
// TODO code application logic here
KeyGenerator keyGenerator = KeyGenerator.getInstance("Blowfish");
keyGenerator.init(448);
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
keyPairGenerator.initialize(1024);
KeyPair keyPair = keyPairGenerator.genKeyPair();
String pubKey = new String(Base64.getEncoder().encode(keyPair.getPublic().getEncoded()));
String priKey = new String(Base64.getEncoder().encode(keyPair.getPrivate().getEncoded()));
System.out.println("Public Key:" + pubKey);
System.out.println("Private Key:" + priKey);
String cipherText = getEncrypted("hi this is a string", pubKey);
System.out.println("CHIPHER:" + cipherText);
String decryptedText = getDecrypted(cipherText, priKey);
System.out.println("DECRYPTED STRING:" + decryptedText);
}
}
i want to encrypt a password with a key from server and decrypt the encrypted password in serverside. this is the code i have used in my application.
If you are looking for a java program to encrypt data with public key and decrypt it with private key then here is the code (using RSA algorithm),
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
/**
* #author visruthcv
*
*/
public class CryptographyUtil {
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 void main(String[] args) throws Exception {
KeyPair generateKeyPair = generateKeyPair();
byte[] publicKey = generateKeyPair.getPublic().getEncoded();
byte[] privateKey = generateKeyPair.getPrivate().getEncoded();
byte[] encryptedData = encrypt(publicKey,
"hi this is Visruth here".getBytes());
byte[] decryptedData = decrypt(privateKey, encryptedData);
System.out.println(new String(decryptedData));
}
}
you can do with Scala or Spark + scala as:
object App {
def main(args: Array[String]): Unit = {
println("************hello*******************\n")
val generator = KeyPairGenerator.getInstance("RSA")
generator.initialize(2048)
val pair = generator.generateKeyPair
val privateKey = pair.getPrivate
val publicKey = pair.getPublic
//println("private key: ",privateKey)
println("public Key: ", publicKey)
//Convert the keys to string using encodeToString()
val publicKeyString = getEncoder.encodeToString(publicKey.getEncoded());
println("publicKeyString :", publicKeyString)
val privateKeyString = getEncoder.encodeToString(privateKey.getEncoded());
println("privateKeyString :", privateKeyString)
val spark = SparkSession.builder()
.master("local")
.appName("rsa_test")
.enableHiveSupport()
.config("spark.sql.parquet.compression.codec", "snappy")
.config("parquet.block.size", 268435456)
.config("hive.exec.dynamic.partition.mode", "nonstrict")
.getOrCreate()
def RsaEncryption(inParm: String): Array[Byte] = {
//Create a Cipher object.The Cipher will provide the functionality of a
// cryptographic cipher for encryption and decryption.
val encryptionCipher = Cipher.getInstance("RSA")
//init() method initializes the cipher with a key for encryption, decryption, key wrapping,
// or key unwrapping depending on the value of opmode
encryptionCipher.init(Cipher.ENCRYPT_MODE, privateKey)
//The doFinal() method performs the encryption operation depending on how the cipher was initialized
// and resets once it finishes allowing encrypting more data.
val encryptedMessage = encryptionCipher.doFinal(inParm.getBytes)
return encryptedMessage
//return encryption
}
def RsaDecryption(inParm: Array[Byte]): String = {
val decryptionCipher = Cipher.getInstance("RSA")
decryptionCipher.init(Cipher.DECRYPT_MODE, publicKey)
val decryptedMessage = decryptionCipher.doFinal(inParm)
val decryption = new String(decryptedMessage)
return decryption
}
val secretMessage = "Test string for encryption"
val encryptedMessage = RsaEncryption(secretMessage)
println("encryptedMessage is :"+encryptedMessage)
//The method returns an array of bites which is simply our message, and we can convert it to a string
// and log it to the console to verify our text is similar to the decrypted text.
System.out.println("Encrypted Message = " + getEncoder.encodeToString(RsaEncryption(secretMessage)))
// register udf below
val clearTxt = "It will be done through spark 2.12"
spark.udf.register("rsa_encrypt", (clearTxt: String) => getEncoder.encodeToString(RsaEncryption(clearTxt)))
val text = s"""select rsa_encrypt(\"$clearTxt\") as enc_string"""
println(text)
val df1 = spark.sql(text)
val encString = df1.select(col("enc_string")).collectAsList().get(0)(0).toString().getBytes()
//val encString1 = df1.withColumn("enc2",col("enc_string").cast(Array[Byte]()))
println("Showing string : " + encString)
println("Decoder call "+ getDecoder.decode(encString))
val decodedString = getDecoder.decode(encString)
def manOf[T: Manifest](t: T): Manifest[T] = manifest[T]
println("Data type of df value " + manOf(getEncoder.encodeToString(RsaEncryption(secretMessage))))
df1.show(truncate=false)
//Decrypt message
val decryptionCipher = Cipher.getInstance("RSA")
decryptionCipher.init(Cipher.DECRYPT_MODE, publicKey)
val decryptedMessage = decryptionCipher.doFinal(encryptedMessage)
val decryption = new String(decryptedMessage)
println("=>"+decryption)
//System.out.println("decrypted message = " + RsaDecryption(encryptedMessage))
System.out.println("decrypted message2 = " +RsaDecryption(decodedString))
}
}
I'm trying to migrate the oracle method dbms_obfuscation_toolkit.DES3Encrypt to a Java Function. My problem is that I don't get the same encrypted value in both scenes.
For this procedure in Oracle:
set serveroutput on;
declare
input raw(128);
encrypted raw(2048);
cadena varchar2(60);
begin
dbms_obfuscation_toolkit.DES3Encrypt(
input => utl_raw.cast_to_raw('TESTDATATESTDATATESTDATA'),
key => utl_raw.cast_to_raw('GD6GTT56HKY4HGF6FH3JG9J5F62FT1'),
encrypted_data => encrypted
);
dbms_output.put_line(rawtohex(encrypted));
end;
I get this output:
8A2E6792E39B0C850377F9A0E054033963F979E4A3FBA25B
However, with this Java class:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
public class TripleDes2
{
private static final String PLAIN_TEXT = "TESTDATATESTDATATESTDATA";
private static final String SHARED_KEY = "GD6GTT56HKY4HGF6FH3JG9J5F62FT1";
public static void main(String args []) throws Exception
{
String algorithm = "DESede";
String transformation = "DESede/CBC/PKCS5Padding";
byte[] keyValue = SHARED_KEY.getBytes("UTF-8");
DESedeKeySpec keySpec = new DESedeKeySpec(keyValue);
IvParameterSpec iv = new IvParameterSpec(new byte[8]);
SecretKey key = SecretKeyFactory.getInstance(algorithm).generateSecret(keySpec);
Cipher encrypter = Cipher.getInstance(transformation);
encrypter.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] input = PLAIN_TEXT.getBytes("UTF-8");
byte[] encrypted = encrypter.doFinal(input);
System.out.println(new String(Hex.encodeHex(encrypted)).toUpperCase());
}
}
I'm getting this value:
82EBC149F298DE55E4FF1540615E60ACDB7743FE79CD2CF4BB6FD232893F83D0
I'm not sure if my Java Code is right. Can you help me?
Thank you very much.
This is my final code, it works like a charm:
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
public class TripleDes3 {
private Cipher cipher = null;
private SecretKey key = null;
private byte[] bytes = null;
private IvParameterSpec iv = null;
public static void main(String[] args) throws Exception {
try {
String hexKey = "GD6GTT56HKY4HGF6FH3JG9J5";
//TripleDes3 encryptor = new TripleDes3(new String(Hex.decodeHex(hexKey.toCharArray())));
TripleDes3 encryptor = new TripleDes3(hexKey);
String original = "ABC";
System.out.println("Oringal: \"" + original + "\"");
String enc = encryptor.encrypt(original);
System.out.println("Encrypted: \"" + enc.toUpperCase() + "\"");
String dec = encryptor.decrypt(enc);
System.out.println("Decrypted: \"" + dec.toUpperCase() + "\"");
if (dec.equals(original)) {
System.out.println("Encryption ==> Decryption Successful");
}
} catch (Exception e) {
System.out.println("Error: " + e.toString());
}
}
public TripleDes3(String encryptionKey) throws GeneralSecurityException, DecoderException {
cipher = Cipher.getInstance("DESede/CBC/NoPadding");
try {
key = new SecretKeySpec(encryptionKey.getBytes("ISO8859_15"), "DESede");
iv = new IvParameterSpec(Hex.decodeHex("0123456789abcdef".toCharArray()));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public String encrypt(String input) throws GeneralSecurityException, UnsupportedEncodingException {
bytes = input.getBytes("ISO8859_15");
bytes = Arrays.copyOf(bytes, ((bytes.length+7)/8)*8);
return new String(Hex.encodeHex(encryptB(bytes)));
}
public String decrypt(String input) throws GeneralSecurityException, DecoderException, UnsupportedEncodingException {
bytes = Hex.decodeHex(input.toCharArray());
String decrypted = new String(decryptB(bytes), "ISO8859_15");
if (decrypted.indexOf((char) 0) > 0) {
decrypted = decrypted.substring(0, decrypted.indexOf((char) 0));
}
return decrypted;
}
public byte[] encryptB(byte[] bytes) throws GeneralSecurityException {
cipher.init(Cipher.ENCRYPT_MODE, (Key) key, iv);
return cipher.doFinal(bytes);
}
public byte[] decryptB(byte[] bytes) throws GeneralSecurityException {
cipher.init(Cipher.DECRYPT_MODE, (Key) key, iv);
return cipher.doFinal(bytes);
}
}
And this is the Oracle Code:
DECLARE
v_data VARCHAR2(255);
v_retval RAW(255);
p_str VARCHAR2(255);
p_key RAW(255);
BEGIN
p_str := 'ABC';
p_key := utl_raw.cast_to_raw('GD6GTT56HKY4HGF6FH3JG9J5F62FT1');
v_data := RPAD(p_str, CEIL(LENGTH(p_str)/8)*8, CHR(0));
dbms_obfuscation_toolkit.DES3Encrypt
(
input => utl_raw.cast_to_raw(v_data),
key => p_key,
which => 1,
encrypted_data => v_retval
);
dbms_output.put_line(v_retval);
END;
Something is funky with the following AES class I've written to do encryption and decryption. When I copy of the AES object and I choose to encrypt plain text, and then I immediately attempt to decrypt the text I just encrypted, it doesn't decrypt it fully (and does it differently every time).
e.g. I'm initializing it with a simple JSP like this:
<%#page import="com.myclass.util.AES"%>
<%
String hexMessage = "0xe800a86d90d2074fbf339aa70b6d0f62f047db15ef04c86b488a1dda3c6c4f2f2bbb444a8c709bbb4c29c7ff1f1e";
String keyText = "12345678abcdefgh";//*/
AES e = new AES();
//e.setKey(keyText);
String plaintext = "This should decode & encode!";
String ciphertext = e.encrypt(plaintext);
out.println(ciphertext);
out.println("<BR>");
out.println(e.decrypt(ciphertext));
%>
The output varies on each page load:
One time:
0x663D64E6A0AE455AB3D25D5AF2F77C72202627EBA068E6DEBE5F22C31
This should decoÁdìmèåV4ÉkÓ
Another:
0x5F5CF31961505F01EA9D5B7D7BFC656BD3117725D2EA041183F48
This s2??XêêÈ&ÀܧF?ÒDÒ?
etc:
0xC7178A34C59F74E5D68F7CE5ED655B670A0B4E715101B4DDC2122460E8
Tà#¼R×ËÖ?_U?xÎÚ?Ba?b4r!©F
The class I created is below:
package com.myclass.util;
import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.regex.Pattern;
import javax.crypto.*;
import javax.crypto.spec.*;
public class AES {
private static String provider = "AES/CTR/NoPadding";
private static String providerkey = "AES";
private static int size = 128;
private SecretKeySpec key;
private Cipher cipher;
private byte[] ivBytes = new byte[size/8];
private IvParameterSpec ivSpec = new IvParameterSpec(ivBytes);
public AES() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException{
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyGenerator kgen = KeyGenerator.getInstance(providerkey);
kgen.init(size); // 192 and 256 bits may not be available
SecretKey skey = kgen.generateKey();
byte[] raw = skey.getEncoded();
key = new SecretKeySpec(raw, providerkey);
cipher = Cipher.getInstance(provider);
for(int x = 0; x < (size/8); x++)
ivBytes[x] = 00;
ivSpec = new IvParameterSpec(ivBytes);
}
public void setKey(String keyText){
byte[] bText = new byte[size/8];
bText = keyText.getBytes();
key = new SecretKeySpec(bText, providerkey);
}
public void setIV(String ivText){
setIV(ivText.getBytes());
}
public void setIV(byte[] ivByte){
byte[] bText = new byte[size/8];
bText = ivByte;
ivBytes = bText;
ivSpec = new IvParameterSpec(ivBytes);
}
public String encrypt(String message) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException{
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] encrypted = cipher.doFinal(message.getBytes());
return byteArrayToHexString(encrypted);
}
public String decrypt(String hexCiphertext) throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException, UnsupportedEncodingException{
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] dec = hexStringToByteArray(hexCiphertext);
byte[] decrypted = cipher.doFinal(dec);
return new String(decrypted);
}
private static String byteArrayToHexString( byte [] raw ) {
String hex = "0x";
String s = new String(raw);
for(int x = 0; x < s.length(); x++){
char[] t = s.substring(x, x + 1).toCharArray();
hex += Integer.toHexString((int) t[0]).toUpperCase();
}
return hex;
}
private static byte[] hexStringToByteArray(String hex) {
Pattern replace = Pattern.compile("^0x");
String s = replace.matcher(hex).replaceAll("");
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++){
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte)v;
}
return b;
}
}
Based on the varied results, I'm wondering if something is getting messed up with the IV somehow, but I don't really understand why...
[EDIT] Looks like its not the IV, if I hard code that the decrypting still varies. If I hard code the key it stops varying, but still doesn't decrypt the text properly :-(.
--------------------- ===================== ---------------------
Adding the final solution I created below, based on owlstead's code and suggestions. It does the following:
1) Has a random key and iv on initialization.
2) Allows you to specify a key or iv as either a regular string, or as a hex encoded string.
3) Automatically truncates or null pads any given key or iv to make it the appropriate length.
NOTE: Item #3 could be viewed as extremely insecure since it allows you to do something stupid. For my purposes I need it, but please use with caution. If you null pad a short string for a key, your content is not going to be very secure.
--------------------- ===================== ---------------------
package com.myclass.util;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidParameterSpecException;
import java.util.regex.Pattern;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AES {
private static Charset PLAIN_TEXT_ENCODING = Charset.forName("UTF-8");
private static String CIPHER_TRANSFORMATION = "AES/CTR/NoPadding";
private static String KEY_TYPE = "AES";
private static int KEY_SIZE_BITS = 128;
private SecretKey key;
private Cipher cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
private byte[] ivBytes = new byte[KEY_SIZE_BITS/8];
public AES() throws NoSuchAlgorithmException, NoSuchPaddingException, NoSuchProviderException, InvalidParameterSpecException, InvalidKeyException, InvalidAlgorithmParameterException{
KeyGenerator kgen = KeyGenerator.getInstance(KEY_TYPE);
kgen.init(KEY_SIZE_BITS);
key = kgen.generateKey();
cipher.init(Cipher.ENCRYPT_MODE, key);
ivBytes = cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV();
}
public String getIVAsHex(){
return byteArrayToHexString(ivBytes);
}
public String getKeyAsHex(){
return byteArrayToHexString(key.getEncoded());
}
public void setStringToKey(String keyText){
setKey(keyText.getBytes());
}
public void setHexToKey(String hexKey){
setKey(hexStringToByteArray(hexKey));
}
private void setKey(byte[] bArray){
byte[] bText = new byte[KEY_SIZE_BITS/8];
int end = Math.min(KEY_SIZE_BITS/8, bArray.length);
System.arraycopy(bArray, 0, bText, 0, end);
key = new SecretKeySpec(bText, KEY_TYPE);
}
public void setStringToIV(String ivText){
setIV(ivText.getBytes());
}
public void setHexToIV(String hexIV){
setIV(hexStringToByteArray(hexIV));
}
private void setIV(byte[] bArray){
byte[] bText = new byte[KEY_SIZE_BITS/8];
int end = Math.min(KEY_SIZE_BITS/8, bArray.length);
System.arraycopy(bArray, 0, bText, 0, end);
ivBytes = bText;
}
public String encrypt(String message) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(ivBytes));
byte[] encrypted = cipher.doFinal(message.getBytes(PLAIN_TEXT_ENCODING));
return byteArrayToHexString(encrypted);
}
public String decrypt(String hexCiphertext)
throws IllegalBlockSizeException, BadPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
UnsupportedEncodingException {
cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(ivBytes));
byte[] dec = hexStringToByteArray(hexCiphertext);
byte[] decrypted = cipher.doFinal(dec);
return new String(decrypted, PLAIN_TEXT_ENCODING);
}
private static String byteArrayToHexString(byte[] raw) {
StringBuilder sb = new StringBuilder(2 + raw.length * 2);
sb.append("0x");
for (int i = 0; i < raw.length; i++) {
sb.append(String.format("%02X", Integer.valueOf(raw[i] & 0xFF)));
}
return sb.toString();
}
private static byte[] hexStringToByteArray(String hex) {
Pattern replace = Pattern.compile("^0x");
String s = replace.matcher(hex).replaceAll("");
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++){
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte)v;
}
return b;
}
}
Rewrote, with comments inline. Funny enough, the biggest mistake was generating the hexadecimals, so I rewrote that method. It's not perfect, but I kept to your original source as much as possible.
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Security;
import java.util.regex.Pattern;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/*
* Add state handling! Don't allow same key/iv for encrypting different cipher text!
*/
public class AES {
private static Charset PLAIN_TEXT_ENCODING = Charset.forName("UTF-8");
private static String CIPHER_TRANSFORMATION = "AES/CTR/NoPadding";
private static String KEY_TYPE = "AES";
// 192 and 256 bits may not be available
private static int KEY_SIZE_BITS = 128;
private Cipher cipher;
private SecretKey key;
private IvParameterSpec iv;
static {
// only needed if the platform does not contain CTR encryption by default
if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
// only needed for some platforms I presume
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
}
}
public AES() throws NoSuchAlgorithmException, NoSuchPaddingException,
NoSuchProviderException {
// not much use without a getter
// final KeyGenerator kgen = KeyGenerator.getInstance(KEY_TYPE);
// kgen.init(KEY_SIZE_BITS);
// key = kgen.generateKey();
cipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
}
public void setKeyHex(String keyText) {
byte[] bText = hexStringToByteArray(keyText);
if (bText.length * Byte.SIZE != KEY_SIZE_BITS) {
throw new IllegalArgumentException(
"Wrong key size, expecting " + KEY_SIZE_BITS / Byte.SIZE + " bytes in hex");
}
key = new SecretKeySpec(bText, KEY_TYPE);
}
public void setIVHex(String ivText) {
byte[] bText = hexStringToByteArray(ivText);
if (bText.length != cipher.getBlockSize()) {
throw new IllegalArgumentException(
"Wrong IV size, expecting " + cipher.getBlockSize() + " bytes in hex");
}
iv = new IvParameterSpec(bText);
}
public String encrypt(String message) throws InvalidKeyException,
IllegalBlockSizeException, BadPaddingException,
InvalidAlgorithmParameterException {
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] encrypted = cipher.doFinal(message.getBytes(PLAIN_TEXT_ENCODING));
return byteArrayToHexString(encrypted);
}
public String decrypt(String hexCiphertext)
throws IllegalBlockSizeException, BadPaddingException,
InvalidKeyException, InvalidAlgorithmParameterException,
UnsupportedEncodingException {
cipher.init(Cipher.DECRYPT_MODE, key, iv);
byte[] dec = hexStringToByteArray(hexCiphertext);
byte[] decrypted = cipher.doFinal(dec);
return new String(decrypted, PLAIN_TEXT_ENCODING);
}
private static String byteArrayToHexString(byte[] raw) {
StringBuilder sb = new StringBuilder(2 + raw.length * 2);
sb.append("0x");
for (int i = 0; i < raw.length; i++) {
sb.append(String.format("%02X", Integer.valueOf(raw[i] & 0xFF)));
}
return sb.toString();
}
// better add some input validation
private static byte[] hexStringToByteArray(String hex) {
Pattern replace = Pattern.compile("^0x");
String s = replace.matcher(hex).replaceAll("");
byte[] b = new byte[s.length() / 2];
for (int i = 0; i < b.length; i++) {
int index = i * 2;
int v = Integer.parseInt(s.substring(index, index + 2), 16);
b[i] = (byte) v;
}
return b;
}
public static void main(String[] args) {
try {
String key = "0x000102030405060708090A0B0C0D0E0F";
String iv = "0x000102030405060708090A0B0C0D0E0F";
String text = "Owlsteads answer";
AES aes = new AES();
aes.setKeyHex(key);
aes.setIVHex(iv);
String cipherHex = aes.encrypt(text);
System.out.println(cipherHex);
String deciphered = aes.decrypt(cipherHex);
System.out.println(deciphered);
} catch (GeneralSecurityException e) {
throw new IllegalStateException("Something is rotten in the state of Denmark", e);
} catch (UnsupportedEncodingException e) {
// not always thrown even if decryption fails, add integrity check such as MAC
throw new IllegalStateException("Decryption and/or decoding plain text message failed", e);
}
}
}
Your byteArrayToHexString method is broken. Integer.toHexString doesn't add padding zeroes but your code assumes it does. The broken conversion to hex corrupts the encrypted string, and the conversion from hex back to a raw byte string corrupts it further.
I am new to cryptography, so I have a question:
How can I create my own key (let`s say like a string "1234"). Because I need to encrypt a string with a key (defined by me), save the encrypted string in a database and when I want to use it, take it from the database and decrypt it with the key known by me.
I have this code :
import java.security.InvalidKeyException;
import java.security.*;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
public class LocalEncrypter {
private static String algorithm = "PBEWithMD5AndDES";
//private static Key key = null;
private static Cipher cipher = null;
private static SecretKey key;
private static void setUp() throws Exception {
///key = KeyGenerator.getInstance(algorithm).generateKey();
SecretKeyFactory factory = SecretKeyFactory.getInstance(algorithm);
String pass1 = "thisIsTheSecretKeyProvidedByMe";
byte[] pass = pass1.getBytes();
SecretKey key = factory.generateSecret(new DESedeKeySpec(pass));
cipher = Cipher.getInstance(algorithm);
}
public static void main(String[] args)
throws Exception {
setUp();
byte[] encryptionBytes = null;
String input = "1234";
System.out.println("Entered: " + input);
encryptionBytes = encrypt(input);
System.out.println(
"Recovered: " + decrypt(encryptionBytes));
}
private static byte[] encrypt(String input)
throws InvalidKeyException,
BadPaddingException,
IllegalBlockSizeException {
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] inputBytes = input.getBytes();
return cipher.doFinal(inputBytes);
}
private static String decrypt(byte[] encryptionBytes)
throws InvalidKeyException,
BadPaddingException,
IllegalBlockSizeException {
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] recoveredBytes =
cipher.doFinal(encryptionBytes);
String recovered =
new String(recoveredBytes);
return recovered;
}
}
Exception in thread "main" java.security.spec.InvalidKeySpecException: Invalid key spec
at com.sun.crypto.provider.PBEKeyFactory.engineGenerateSecret(PBEKeyFactory.java:114)
at javax.crypto.SecretKeyFactory.generateSecret(SecretKeyFactory.java:335)
at LocalEncrypter.setUp(LocalEncrypter.java:22)
at LocalEncrypter.main(LocalEncrypter.java:28)
A KeyGenerator generates random keys. Since you know the secret key, what you need is a SecretKeyFactory. Get an instance for your algorithm (DESede), and then call its generateSecret méthode with an instance of DESedeKeySpec as argument:
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey key = factory.generateSecret(new DESedeKeySpec(someByteArrayContainingAtLeast24Bytes));
Here is a complete example that works. As I said, DESedeKeySpec must be used with the DESede algorithm. Using a DESede key with PBEWithMD5AndDES makes no sense.
public class EncryptionTest {
public static void main(String[] args) throws Exception {
byte[] keyBytes = "1234567890azertyuiopqsdf".getBytes("ASCII");
DESedeKeySpec keySpec = new DESedeKeySpec(keyBytes);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey key = factory.generateSecret(keySpec);
byte[] text = "Hello world".getBytes("ASCII");
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(text);
cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decrypted = cipher.doFinal(encrypted);
System.out.println(new String(decrypted, "ASCII"));
}
}
Well, I found the solution after combining from here and there. The encrypted result will be formatted as Base64 String for safe saving as xml file.
package cmdCrypto;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.xml.bind.DatatypeConverter;
public class CmdCrypto {
public static void main(String[] args) {
try{
final String strPassPhrase = "123456789012345678901234"; //min 24 chars
String param = "No body can see me";
System.out.println("Text : " + param);
SecretKeyFactory factory = SecretKeyFactory.getInstance("DESede");
SecretKey key = factory.generateSecret(new DESedeKeySpec(strPassPhrase.getBytes()));
Cipher cipher = Cipher.getInstance("DESede");
cipher.init(Cipher.ENCRYPT_MODE, key);
String str = DatatypeConverter.printBase64Binary(cipher.doFinal(param.getBytes()));
System.out.println("Text Encryted : " + str);
cipher.init(Cipher.DECRYPT_MODE, key);
String str2 = new String(cipher.doFinal(DatatypeConverter.parseBase64Binary(str)));
System.out.println("Text Decryted : " + str2);
} catch(Exception e) {
e.printStackTrace();
}
}
}