public class MyEncrypt {
public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
oout.close();
}
}
public static void main(String[] args) throws Exception {
MyEncrypt myEncrypt = new MyEncrypt();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(128);
KeyPair kp = kpg.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
myEncrypt.saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
myEncrypt.saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());
String encString = myEncrypt.bytes2String(myEncrypt.rsaEncrypt("pritesh".getBytes()));
System.out.println("encrypted : " + encString);
String decString = myEncrypt.bytes2String(myEncrypt.rsaDecrypt(encString.getBytes()));
System.out.println("decrypted : " + decString);
}
PublicKey readKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey pubKey = fact.generatePrivate(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
public byte[] rsaEncrypt(byte[] data) throws Exception {
byte[] src = new byte[] { (byte) 0xbe, (byte) 0xef };
PublicKey pubKey = this.readKeyFromFile("public.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
public byte[] rsaDecrypt(byte[] data) throws Exception {
byte[] src = new byte[] { (byte) 0xbe, (byte) 0xef };
PrivateKey pubKey = this.readPrivateKeyFromFile("private.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
private String bytes2String(byte[] bytes) {
StringBuilder string = new StringBuilder();
for (byte b: bytes) {
String hexString = Integer.toHexString(0x00FF & b);
string.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
return string.toString();
}
}
I am getting this error:
Exception in thread "main" java.security.InvalidParameterException: RSA keys must be at least 512 bits long
at sun.security.rsa.RSAKeyPairGenerator.initialize(RSAKeyPairGenerator.java:70)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:631)
at java.security.KeyPairGenerator.initialize(KeyPairGenerator.java:340)
at MyEncrypt.main(MyEncrypt.java:42)
I have make this class from http://www.javamex.com/tutorials/cryptography/rsa_encryption_2.shtml example
public class MyEncrypt {
static final String HEXES = "0123456789ABCDEF";
byte[] buf = new byte[1024];
public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
oout.close();
}
}
public static void main(String[] args) throws Exception {
MyEncrypt myEncrypt = new MyEncrypt();
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
myEncrypt.saveToFile("public.key", pub.getModulus(), pub.getPublicExponent());
myEncrypt.saveToFile("private.key", priv.getModulus(), priv.getPrivateExponent());
String encString = myEncrypt.rsaEncrypt("pritesh");
System.out.println("encrypted : " + encString);
String decString = myEncrypt.rsaDecrypt(encString);
System.out.println("decrypted : " + decString);
String main_file_path = "resume.doc";
String main_encrypt_file_path = "encrypt.doc";
String main_decrypt_file_path = "decrypt.doc";
myEncrypt.rsaEncrypt(new FileInputStream(main_file_path),new FileOutputStream(main_encrypt_file_path));
// Decrypt
myEncrypt.rsaDecrypt(new FileInputStream(main_encrypt_file_path),new FileOutputStream(main_decrypt_file_path));
}
PublicKey readKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey pubKey = fact.generatePrivate(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
public String rsaEncrypt(String plaintext) throws Exception {
PublicKey pubKey = this.readKeyFromFile("public.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] ciphertext = cipher.doFinal(plaintext.getBytes("UTF-8"));
return this.byteToHex(ciphertext);
}
public void rsaEncrypt(InputStream in, OutputStream out) throws Exception {
try {
PublicKey pubKey = this.readKeyFromFile("public.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
// Bytes written to out will be encrypted
out = new CipherOutputStream(out, cipher);
// Read in the cleartext bytes and write to out to encrypt
int numRead = 0;
while ((numRead = in.read(buf)) >= 0){
out.write(buf, 0, numRead);
}
out.close();
}
catch (java.io.IOException e){
e.printStackTrace();
}
}
public void rsaDecrypt(InputStream in, OutputStream out) throws Exception {
try {
PrivateKey pubKey = this.readPrivateKeyFromFile("private.key");
Cipher dcipher = Cipher.getInstance("RSA");
dcipher.init(Cipher.DECRYPT_MODE, pubKey);
// Bytes read from in will be decrypted
in = new CipherInputStream(in, dcipher);
// Read in the decrypted bytes and write the cleartext to out
int numRead = 0;
while ((numRead = in.read(buf)) >= 0) {
out.write(buf, 0, numRead);
}
out.close();
} catch (java.io.IOException e) {
e.printStackTrace();
}
}
public String rsaDecrypt(String hexCipherText) throws Exception {
PrivateKey pubKey = this.readPrivateKeyFromFile("private.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, pubKey);
String plaintext = new String(cipher.doFinal(this.hexToByte(hexCipherText)), "UTF-8");
return plaintext;
}
public static String byteToHex( byte [] raw ) {
if ( raw == null ) {
return null;
}
final StringBuilder hex = new StringBuilder( 2 * raw.length );
for ( final byte b : raw ) {
hex.append(HEXES.charAt((b & 0xF0) >> 4))
.append(HEXES.charAt((b & 0x0F)));
}
return hex.toString();
}
public static byte[] hexToByte( String hexString){
int len = hexString.length();
byte[] ba = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
ba[i/2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
}
return ba;
}
}
It works well with text file but giving issue on files like docx and video any idea?
The error says it all: you're initializing with a keyset of 128 and RSA expects at least 512.
You have more than one problem:
Java does not support RSA keys of size less than 512. 2048 bit is a better choice. So change the key length:
kpg.initialize(2048);
String.getBytes() is not the inverse operation to your bytes2String(). After encrypting you convert the bytes to a hexadecimal string. But then you convert this hexadecimal string to its ASCII representation before decrypting, which yields a byte-array that is too long. Instead, use something like this to convert the hexadecimal string back:
private byte[] string2bytes(String s) {
int len = s.length();
byte[] res = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
res[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return res;
}
and then call that instead of String.getBytes():
// Note, this line is not completely fixed yet
String decString =
myEncrypt.bytes2String(
myEncrypt.rsaDecrypt(
myEncrypt.string2bytes(encString)
)
);
Finally you have the opposite problem. Your bytes2String() method does not reverse the String.getBytes() operation. You encrypted the output of "pritesh".getBytes(), so that is what you got out of the decrypt operation. Now you have to convert that back to a String. The String(byte[])-constructor will do that for you:
String decString =
new String(
myEncrypt.rsaDecrypt(
myEncrypt.string2bytes(encString)
)
);
Final ans
public class MyEncrypt {
public static final int AES_Key_Size = 128;
Cipher pkCipher, aesCipher;
byte[] aesKey;
SecretKeySpec aeskeySpec;
public static void main(String[] args) throws Exception {
//MyEncrypt.createRSAKeys(); //call to generated RSA keys
MyEncrypt secure = new MyEncrypt();
// to encrypt a file
secure.makeKey();
secure.saveKey(new File("keys/ase.key"), "keys/public.key");
secure.encrypt(new File("test/sample.pdf"), new File("test/encrypt_sample.pdf"));
// to decrypt it again
secure.loadKey(new File("keys/ase.key"), "keys/private.key");
secure.decrypt(new File("test/encrypt_sample.pdf"), new File("test/decrypted_sample.pdf"));
}
/**
* Constructor: creates ciphers
*/
public MyEncrypt() throws GeneralSecurityException {
// create RSA public key cipher
pkCipher = Cipher.getInstance("RSA");
// create AES shared key cipher
aesCipher = Cipher.getInstance("AES");
}
public static void createRSAKeys() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(512);
KeyPair kp = kpg.genKeyPair();
RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
saveToFile("keys/public.key", pub.getModulus(), pub.getPublicExponent());
saveToFile("keys/private.key", priv.getModulus(), priv.getPrivateExponent());
System.out.println("RSA public & private keys are generated");
}
private static void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
ObjectOutputStream oout = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
try {
oout.writeObject(mod);
oout.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error", e);
} finally {
oout.close();
}
}
/**
* Creates a new AES key
*/
public void makeKey() throws NoSuchAlgorithmException {
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(AES_Key_Size);
SecretKey key = kgen.generateKey();
aesKey = key.getEncoded();
aeskeySpec = new SecretKeySpec(aesKey, "AES");
}
/**
* Encrypts the AES key to a file using an RSA public key
*/
public void saveKey(File out, String publicKeyFile) throws IOException, GeneralSecurityException {
try {
// read public key to be used to encrypt the AES key
byte[] encodedKey = new byte[(int)publicKeyFile.length()];
new FileInputStream(publicKeyFile).read(encodedKey);
// create public key
//X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(encodedKey);
//KeyFactory kf = KeyFactory.getInstance("RSA");
//PublicKey pk = kf.generatePublic(publicKeySpec);
PublicKey pk = this.readPublicKeyFromFile(publicKeyFile);
// write AES key
pkCipher.init(Cipher.ENCRYPT_MODE, pk);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), pkCipher);
os.write(aesKey);
os.close();
} catch (Exception e) {
//throw new Exception("Saving key exception", e);
}
}
private PublicKey readPublicKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
private PrivateKey readPrivateKeyFromFile(String keyFileName) throws Exception {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PrivateKey pubKey = fact.generatePrivate(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
/**
* Decrypts an AES key from a file using an RSA private key
*/
public void loadKey(File in, String privateKeyFile) throws GeneralSecurityException, IOException {
try {
// read private key to be used to decrypt the AES key
byte[] encodedKey = new byte[(int)privateKeyFile.length()];
new FileInputStream(privateKeyFile).read(encodedKey);
// create private key
//PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(encodedKey);
//KeyFactory kf = KeyFactory.getInstance("RSA");
//PrivateKey pk = kf.generatePrivate(privateKeySpec);
PrivateKey pk = this.readPrivateKeyFromFile(privateKeyFile);
// read AES key
pkCipher.init(Cipher.DECRYPT_MODE, pk);
aesKey = new byte[AES_Key_Size/8];
CipherInputStream is = new CipherInputStream(new FileInputStream(in), pkCipher);
is.read(aesKey);
aeskeySpec = new SecretKeySpec(aesKey, "AES");
} catch (Exception e) {
}
}
/**
* Encrypts and then copies the contents of a given file.
*/
public void encrypt(File in, File out) throws IOException, InvalidKeyException {
aesCipher.init(Cipher.ENCRYPT_MODE, aeskeySpec);
FileInputStream is = new FileInputStream(in);
CipherOutputStream os = new CipherOutputStream(new FileOutputStream(out), aesCipher);
copy(is, os);
os.close();
}
/**
* Decrypts and then copies the contents of a given file.
*/
public void decrypt(File in, File out) throws IOException, InvalidKeyException {
aesCipher.init(Cipher.DECRYPT_MODE, aeskeySpec);
CipherInputStream is = new CipherInputStream(new FileInputStream(in), aesCipher);
FileOutputStream os = new FileOutputStream(out);
copy(is, os);
is.close();
os.close();
}
/**
* Copies a stream.
*/
private void copy(InputStream is, OutputStream os) throws IOException {
int i;
byte[] b = new byte[1024];
while((i=is.read(b))!=-1) {
os.write(b, 0, i);
}
}
}
Related
I referred to the below link
AES Encryption .net to swift,
But, applying the same for ANDROID, I am not able to get the correct AES encryption with version(PBKDF2) conversion for my code. NEED HELP.
public static String Encrypt(String PlainText) throws Exception {
try {
byte[] salt = new byte[] { 0x49, 0x76, 0x61, 0x6E, 0x20, 0x4D,
0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 };
System.out.println("Exception setting up cipher: "+pbkdf2("<keyname>",salt.toString(),1024,128));
Cipher _aesCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
byte[] keyBytes =pbkdf2("<keyname>",salt.toString(),1024,128).getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
byte[] iv ="OFRna73m*aze01xY".getBytes();//pbkdf2("<keyname>",salt.toString(),2,64).getBytes();
IvParameterSpec ivSpec = new IvParameterSpec(iv);
_aesCipher.init(1, keySpec, ivSpec);
byte[] plainText = PlainText.getBytes();
byte[] result = _aesCipher.doFinal(plainText);
return Base64.encodeToString(result, Base64.DEFAULT);//Base64.encode(result,1));
} catch (Exception ex1) {
System.out.println("Exception setting up cipher: "
+ ex1.getMessage() + "\r\n");
ex1.printStackTrace();
return "";
}
}
public static String pbkdf2(String password, String salt, int iterations, int keyLength) throws NoSuchAlgorithmException, InvalidKeySpecException {
char[] chars = password.toCharArray();
PBEKeySpec spec = new PBEKeySpec(chars, salt.getBytes(), iterations, keyLength);
SecretKeyFactory skf = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] hash = skf.generateSecret(spec).getEncoded();
return toHex(hash);
}
// Converts byte array to a hexadecimal string
private static String toHex(byte[] array) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < array.length; i++) {
sb.append(Integer.toString((array[i] & 0xff) + 0x100, 16).substring(1));
}
return sb.toString();
}
Please check below code .
I have created Singletone class for the same so that i can access it anywhere in app.
Below Points Should be same like .net or swift
Important Points are IV , SALT and PASSWORD
Please check this too PBKDF2WithHmacSHA1
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
to generate key we used this
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
Importnant points are (password, salt,iterantion,bytes) this must be same like other platform which you are using with like .net or swift
public class AesBase64Wrapper {
private static String IV = "it should be same like server or other platform";
private static String PASSWORD = "it should be same like server or other platform";
private static String SALT = "it should be same like server or other platform";
private static volatile AesBase64Wrapper sSoleInstance = new AesBase64Wrapper();
//private constructor.
private AesBase64Wrapper() {
}
public static AesBase64Wrapper getInstance() {
return sSoleInstance;
}
// For Encryption
public String encryptAndEncode(String raw) {
try {
Cipher c = getCipher(Cipher.ENCRYPT_MODE);
byte[] encryptedVal = c.doFinal(getBytes(raw));
//String retVal = Base64.encodeToString(encryptedVal, Base64.DEFAULT);
String retVal = Base64.encodeToString(encryptedVal, Base64.NO_WRAP);
return retVal;
}catch (Throwable t) {
throw new RuntimeException(t);
}
}
public String decodeAndDecrypt(String encrypted) throws Exception {
// byte[] decodedValue = Base64.decode(getBytes(encrypted),Base64.DEFAULT);
byte[] decodedValue = Base64.decode(getBytes(encrypted), Base64.NO_WRAP);
Cipher c = getCipher(Cipher.DECRYPT_MODE);
byte[] decValue = c.doFinal(decodedValue);
return new String(decValue);
}
private String getString(byte[] bytes) throws UnsupportedEncodingException {
return new String(bytes, "UTF-8");
}
private byte[] getBytes(String str) throws UnsupportedEncodingException {
return str.getBytes("UTF-8");
}
private Cipher getCipher(int mode) throws Exception {
Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = getBytes(IV);
String xyz = String.valueOf(generateKey());
Log.i("generateKey", xyz);
c.init(mode, generateKey(), new IvParameterSpec(iv));
return c;
}
private Key generateKey() throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
char[] password = PASSWORD.toCharArray();
byte[] salt = getBytes(SALT);
KeySpec spec = new PBEKeySpec(password, salt, 2, 256);
SecretKey tmp = factory.generateSecret(spec);
byte[] encoded = tmp.getEncoded();
byte b = encoded[1];
Log.e("Secrete Key", String.valueOf(encoded));
return new SecretKeySpec(encoded, "CBC");
}
}
In Activity you can use it like
String EncryptString = AesBase64Wrapper.getInstance().encryptAndEncode("hello");
String DecryptString = AesBase64Wrapper.getInstance().encryptAndEncode(EncryptString);
// You will Get Output in Decrypted String
I would like to encrypt and decrypt files. While decrypting I wish to skip first few bytes of the file and decrypt only the rest.
Here contains three files
input_file.txt - input text file for encryption
output_file.txt - encrypted input_file.txt file
decrypted_file.txt - decrypted output_file.txt file
Sample code:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class FileReadWrite {
public static byte[] getAESKey() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return bytes;
}
/**
* Method used to generate a random new iv
*
* #return Randomly generated iv
*/
public static byte[] getAESIV() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);
return bytes;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
FileInputStream fin = new FileInputStream("/Users/emp/Research/Streams/input_file.txt");
FileOutputStream fout = new FileOutputStream("/Users/emp/Research/Streams/output_file.txt");
SecretKeySpec keySpec = null;
IvParameterSpec ivSpec = null;
Cipher ecipher = null;
Cipher dcipher = null;
byte[] keyBytes = getAESKey();
byte[] ivBytes = getAESIV();
// Creating keyspec and ivspec for generating cipher
keySpec = new SecretKeySpec(keyBytes,"AES");
ivSpec = new IvParameterSpec(ivBytes);
try {
ecipher = Cipher.getInstance("AES/CTR/NoPadding");
ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
CipherOutputStream cout = new CipherOutputStream(fout, ecipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
while((count = fin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
cout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
fout.close();
cout.close();
}
fin = new FileInputStream("/Users/emp/Research/Streams/output_file.txt");
fout = new FileOutputStream("/Users/emp/Research/Streams/decrypted_file.txt");
try {
dcipher = Cipher.getInstance("AES/CTR/NoPadding");
dcipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
//fin.skip(1024);
CipherInputStream cin = new CipherInputStream(fin, dcipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
**//cin.read(bytearray, 0, 30);**
while((count = cin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
fout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
cin.close();
fout.close();
}
System.out.println("File read write completed successfully !!! ");
}
}
Tried:
Cipher input stream skip - cin.skip(no_of_bytes) - this doesn't work - this decrypts the entire file
File input stream skip
fin.skip(no_of_bytes); CipherInputStream cin = new
CipherInputStream(fin, cipher);
This does not decrypt the file. The output file looks like encrypted.
Dummy read - Reading and ignoring from cipher input stream - this works
//cin.read(bytearray, 0, 30);
Please clarify me the following:
What skip and seek input stream does internally?
Why my cipher input stream seek doesn't work?
Why cipher input stream requires all the bytes to be read from the stream (I assume so) for decrypting? How does it work?
With reference to the article,
Random access InputStream using AES CTR mode in android
After updating the iv with offset value the decryption works fine.
Here is the updated code
package Streams;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.SecureRandom;
import java.util.Arrays;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.ShortBufferException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class FileReadWrite {
private static final int AES_BLOCK_SIZE = 16;
public static final void jumpToOffset(final Cipher c, final SecretKeySpec aesKey, final IvParameterSpec iv, final long offset) {
if (!c.getAlgorithm().toUpperCase().startsWith("AES/CTR")) {
throw new IllegalArgumentException("Invalid algorithm, only AES/CTR mode supported");
}
if (offset < 0) {
throw new IllegalArgumentException("Invalid offset");
}
final int skip = (int) (offset % AES_BLOCK_SIZE);
final IvParameterSpec calculatedIVForOffset = calculateIVForOffset(iv, offset - skip);
try {
c.init(Cipher.ENCRYPT_MODE, aesKey, calculatedIVForOffset);
final byte[] skipBuffer = new byte[skip];
c.update(skipBuffer, 0, skip, skipBuffer);
Arrays.fill(skipBuffer, (byte) 0);
} catch (ShortBufferException | InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalStateException(e);
}
}
private static IvParameterSpec calculateIVForOffset(final IvParameterSpec iv, final long blockOffset) {
final BigInteger ivBI = new BigInteger(1, iv.getIV());
final BigInteger ivForOffsetBI = ivBI.add(BigInteger.valueOf(blockOffset / AES_BLOCK_SIZE));
final byte[] ivForOffsetBA = ivForOffsetBI.toByteArray();
final IvParameterSpec ivForOffset;
if (ivForOffsetBA.length >= AES_BLOCK_SIZE) {
ivForOffset = new IvParameterSpec(ivForOffsetBA, ivForOffsetBA.length - AES_BLOCK_SIZE, AES_BLOCK_SIZE);
} else {
final byte[] ivForOffsetBASized = new byte[AES_BLOCK_SIZE];
System.arraycopy(ivForOffsetBA, 0, ivForOffsetBASized, AES_BLOCK_SIZE - ivForOffsetBA.length, ivForOffsetBA.length);
ivForOffset = new IvParameterSpec(ivForOffsetBASized);
}
return ivForOffset;
}
public static byte[] getAESKey() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[32];
secureRandom.nextBytes(bytes);
return bytes;
}
/**
* Method used to generate a random new iv
*
* #return Randomly generated iv
*/
public static byte[] getAESIV() {
SecureRandom secureRandom = new SecureRandom();
byte[] bytes = new byte[16];
secureRandom.nextBytes(bytes);
return bytes;
}
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
FileInputStream fin = new FileInputStream("/Users/emp/Research/Streams/input_file.txt");
FileOutputStream fout = new FileOutputStream("/Users/emp/Research/Streams/output_file.txt");
SecretKeySpec keySpec = null;
IvParameterSpec ivSpec = null;
Cipher ecipher = null;
Cipher dcipher = null;
byte[] keyBytes = getAESKey();
byte[] ivBytes = getAESIV();
// Creating keyspec and ivspec for generating cipher
keySpec = new SecretKeySpec(keyBytes,"AES");
ivSpec = new IvParameterSpec(ivBytes);
try {
ecipher = Cipher.getInstance("AES/CTR/NoPadding");
ecipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
CipherOutputStream cout = new CipherOutputStream(fout, ecipher);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
while((count = fin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
cout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
fout.close();
cout.close();
}
fin = new FileInputStream("/Users/emp/Research/Streams/output_file.txt");
fout = new FileOutputStream("/Users/emp/Research/Streams/decrypted_file.txt");
try {
dcipher = Cipher.getInstance("AES/CTR/NoPadding");
dcipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
} catch (Exception e) {
System.out.println("Thus the exception occured during cipher generation is ::: "+e);
}
fin.skip(1024);
jumpToOffset(dcipher, keySpec, ivSpec, 1024);
CipherInputStream cin = new CipherInputStream(fin, dcipher);
//cin.skip(1024);
try {
int count = 0;
int BUFFER_SIZE = 1024;
byte[] bytearray = new byte[BUFFER_SIZE];
//cin.read(bytearray, 0, 30);
while((count = cin.read(bytearray, 0, BUFFER_SIZE)) != -1) {
//fout.write(bytearray, 0, count);
fout.write(bytearray, 0, count);
}
} catch(Exception ex) {
System.out.println("Thus the exception occured is ::: "+ex);
} finally {
fin.close();
cin.close();
fout.close();
}
System.out.println("File read write completed successfully !!! ");
}
}
I encrypt a word in java and I have trouble decrypting it in php.
here is how I create the keys in android:
public void GenerateAndSaveToFile(){
try {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
KeyPair kp = kpg.genKeyPair();
Key publicKey = kp.getPublic();
Key privateKey = kp.getPrivate();
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class);
//////////////////////////
String root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).toString();
File myDir = new File(root + "/keys");
myDir.mkdirs();
File file = new File (myDir, "private.key");
FileOutputStream fileout1 = new FileOutputStream(file);
ObjectOutputStream oout1 = new ObjectOutputStream(fileout1);
oout1.writeObject(priv.getModulus());
oout1.writeObject( priv.getPrivateExponent());
oout1.close();
///////////////////////
File file2 = new File (myDir, "public.key");
FileOutputStream fileout2 = new FileOutputStream(file2);
ObjectOutputStream oout2 = new ObjectOutputStream(new BufferedOutputStream(fileout2));
oout2.writeObject(pub.getModulus());
oout2.writeObject( pub.getPublicExponent());
oout2.close();
}
catch (Exception ex){
Exception e = ex;
}
}
here is how I encrypt the word with generated public key in android:
byte[] u1Encrypted = RSAEncrypt(String.valueOf(inputEmail.getText()).getBytes());
public byte[] RSAEncrypt(byte[] data) {
try {
PublicKey pubKey = ReadPublicKey();
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
byte[] cipherData = cipher.doFinal(data);
return cipherData;
}
catch (Exception ex)
{
Exception e = ex;
return null;
}
}
private PublicKey ReadPublicKey() throws IOException {
try {
AssetManager assetManager = getAssets();
InputStream in = assetManager.open("public.key");
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
PublicKey pubKey = fact.generatePublic(keySpec);
return pubKey;
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
}
}
catch (Exception ex)
{
Exception e = ex;
return null;
}
}
then I convert the encrypted string to base64 in android:
String u1EncryptedBase64 = Base64.encodeToString(u1Encrypted, Base64.DEFAULT);
and in php I decode the base64 string:
$encryptedString = base64_decode(u1EncryptedBase64);
get the private key:
$keytmp = fopen("../../../private.key", "r") or die("Unable to open file!");
$key = fread($keytmp,filesize("../../../private.key"));
$res = openssl_get_privatekey($key);
and finally I try to decrypt the string in php:
if (openssl_private_decrypt($encryptedString, $decrypted, $res)) {
echo $decrypted;
}
else
{
echo "problem";
}
and error I get is:
Warning: openssl_private_decrypt(): key parameter is not a valid private key ...
please guide me how to accompolish this task.
thanks
I can show you how i have done encryption in my android and decryption in php. It worked wonderfully fine.May be you can get some help from this. In android the code is like:
final private static String RSA_public_key="MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEApeRuOhn71+wcRtlN6JoW\n" +
"JLrVE5HKLPukFgpMdguNskBwDOPrrdYKP1e3rZMHN9oVB/QTTpkQM4CrGYlstUmT\n" +
"u5nEfdsH4lHRxe3qhi9+zOknWKJCnW4Cq70oITCAK08BIJ/4ZcGM1SUyv1+0u1aB\n" +
"cx6g1aKhthttRjNpck2LBaHVolt7Z4FTb5SdZMwJKRyEv8fuP6yyR0CJGEbQKZKA\n" +
"ODNKyqJ42sVzUQ2AMQIWdhkFdAFahKCL4MChGvKU6F20cHdvokyxXJjU3sZobjNf\n" +
"i+8FzH9hd7y8kmi4o3AKP69p5asgflXoXHpo135i3NzZqlNJ+Bs9pY+90u9iLScp\n" +
"JwIBAw==";
static String enccriptData(String txt)
{
String encoded = "";
byte[] encrypted = null;
try {
byte[] publicBytes = Base64.decode(RSA_public_key, Base64.DEFAULT);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1PADDING"); //or try with "RSA"
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
encrypted = cipher.doFinal(txt.getBytes());
encoded = Base64.encodeToString(encrypted, Base64.DEFAULT);
}
catch (Exception e) {
e.printStackTrace();
}
return encoded;
}
I have paste that encoded string that is returned in the above function in below $string. This is the code for php:
<?php
$string="W39VlV1Q96QzDIR/jINzaEL7rh2Z+Z90uxJ1DtaSfkVKzIgt2TIkxsuRY+A2icwPtTdq6+9j1Xb009KT+ck2KD+dot3wPL5UaHqApbZSi6UZan/nDbFCNJdffTlTWsPS2ThEefeMMSs8HE2ORSt42D8cxYlogOvkvlLr60cHYKwfC1itLSqPuYR+C/gPAf6yCteLbj//EkJp8TemlmPi0eSsH492FgrmBqiTOS4LzpzsPFpSI4KJbuM2dvqp5jkt7MnpR1laILmyC37fA5XPUQmEQChoG5eSbMxqO7SPboYC1BH9ATy6uTS1MGXGDzJ2FSJ41MMRV1Ul/4UNFVA8Ng==";
$encryptedString = base64_decode($string);
$key="-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCl5G46GfvX7BxG
2U3omhYkutUTkcos+6QWCkx2C42yQHAM4+ut1go/V7etkwc32hUH9BNOmRAzgKsZ
iWy1SZO7mcR92wfiUdHF7eqGL37M6SdYokKdbgKrvSghMIArTwEgn/hlwYzVJTK/
X7S7VoFzHqDVoqG2G21GM2lyTYsFodWiW3tngVNvlJ1kzAkpHIS/x+4/rLJHQIkY
RtApkoA4M0rKonjaxXNRDYAxAhZ2GQV0AVqEoIvgwKEa8pToXbRwd2+iTLFcmNTe
xmhuM1+L7wXMf2F3vLySaLijcAo/r2nlqyB+VehcemjXfmLc3NmqU0n4Gz2lj73S
72ItJyknAgEDAoIBAG6YSXwRUo/yvYSQ3psRZBh8jg0L3B39GA6xiE6yXnbVoAiX
8nPkBtTlJR5iBM/muK/4DN8QtXerHLuw8yOGYn0RLak8r+w2i9lJRwQfqd3wxOXB
gb5JVx0oxWt1qseKAMBqpZkrszjDdyo/zdI5q6IUazkXFnlnni7M8PbeXK5q0PE6
0XclC1W79jX71D8d24SITAfXDqaXOwObSn9dadw1gsxx8fPd6Fr7ZTS0AddxJZN2
jNK14xkv2rkxdP1W529gnCVQUhju5SPJS5QwphI7KyfH7wTHnBOhbhp3FpaVKPz0
biLwZ6D0xgR6reZofz+t1cvDOha54wC4ZZYJyTsCgYEA0blJn8zxAHDSj8z/01zz
dc1qdYfdlf9gEWgr+APS9XSowGg+CdQN2W0XwySlpPoMZyCKM/aH0DNcl11yynpL
Mkm5MU2V2T+VKWXwUNHrGXSVRJkgLu+iD1Pt0oGPfS9qRYydG5TBjQEVrBrh4Jtk
KdsMBA82mgxEdFqtERbTpi0CgYEAyn85oWfYwf4oHEbSd218RauRBqwMhk39nyqx
6Gaza/k6Ri+5hBjqvVt8pT1Obrji5fZFU1IH5wecQae1mvIQJv+tVBy+XPedU8Mo
Jj3/TPwBAHezTADvQyEIwPot6y5lZt2fX7Urv+n1k7XkfWfb8O/ChTc/zHc0dPct
uLVE1SMCgYEAi9Dbv932AEs3CoiqjOiiTojxo6/pDqpAC5rH+q03Tk3F1ZrUBo1e
kPNlLMMZGKay72sGzU8FNXeTD5Oh3FGHdtvQy4kOkNUOG5lK4IvyEPhjgxDAH0ps
Cjfz4au0/h+cLl2+EmMrs1YOcryWlbztcTyyrV95vAgtouceC2SNGXMCgYEAhv97
wO/l1qlwEtnhpPOoLnJgrx1drt6pFMchRZnM8qYm2XUmWBCcfjz9w340SdCXQ/mD
jOFamgUS1m/OZ0wKxKpzjWh+6KUTjSzFbtP/iKgAqvp3iACfghYF1fwenMmY7z5q
P84dKpv5DSPtqO/n9fUsWM9/3aTNo09z0HjYjhcCgYEAoN+1/ZzonPWDIY/u+7bW
e8BkcuBVpMZe7qBYHeVix89yvyuVE+erKqurnG7fN7YIDX8V1OcVP+qHw8fJNQKL
wd03nNIIJyTPXodgty3HYjBUe8fVn/8P+JOv2U7bJCkUGlFeyZIMZWEsYd8t5794
3fotiYXOUug9bFtnGHRyY7I=
-----END PRIVATE KEY-----";
openssl_private_decrypt($encryptedString, $decrypted, $key);
$string1=$decrypted;
echo $string1;
?>
The private and public keys are made for each other.
i am trying to verify a file with my java program. I have no idea what i am doing wrong, all the solutions i found does not work.
Here is my code:
public boolean pruefeSignatur(File file, File signatur, File publicKey) {
boolean verifies = false;
try {
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
// encode public key bytes
FileInputStream keyfis = new FileInputStream(publicKey);
byte [] encKey = new byte[keyfis.available()];
keyfis.read(encKey);
keyfis.close();
// key specification
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
// conversion
KeyFactory keyFactory = KeyFactory.getInstance(pubKeySpec.getFormat());
// generate publicKey
PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
// input signature bytes
FileInputStream sigfis = new FileInputStream(signatur);
byte[] sigToVerify = new byte[sigfis.available()];
sigfis.read(sigToVerify);
sigfis.close();
// initialize the signature
Signature sig = Signature.getInstance("RSA");
sig.initVerify(pubKey);
// supply signature object with the data to be verified
FileInputStream datafis = new FileInputStream(file);
BufferedInputStream bufin = new BufferedInputStream(datafis);
byte[] buffer = new byte[1024];
int len;
while(bufin.available() != 0) {
len = bufin.read(buffer);
sig.update(buffer, 0, len);
}
bufin.close();
//verify signature
verifies = sig.verify(sigToVerify);
} catch (Exception e) {
e.printStackTrace();
}
return verifies;
}
With this code i get the exception:
java.security.spec.InvalidKeySpecException: java.lang.ClassCastException: org.bouncycastle.asn1.DERUnknownTag cannot be cast to org.bouncycastle.asn1.ASN1Object
When i use Base64, for example:
Base64 decoder = new Base64();
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(decoder.decode(encKey));
I get the exception:
java.security.spec.InvalidKeySpecException: java.io.IOException: unexpected end-of-contents marker
Another solution i found was changing it to:
X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);
// conversion
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
But then i get the exception:
java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: invalid key format
I made my keys with Gpg4win and Kleopatra.
Edit:
Now I do not get an error, but the function always returns false. So I am not sure if everything is right.
public boolean pruefeSignatur(File file, File signaturFile, File publicKeyFile) throws IOException {
boolean verifies = false;
FileInputStream keyfis = null;
DataInputStream keydis = null;
FileInputStream sigfis = null;
DataInputStream sigdis = null;
FileInputStream datafis = null;
DataInputStream datadis = null;
try {
// add provider
Security.addProvider(new BouncyCastleProvider());
// encode public key bytes
keyfis = new FileInputStream(publicKeyFile);
keydis = new DataInputStream(keyfis);
byte[] keyBytes = new byte[(int) publicKeyFile.length()];
keydis.readFully(keyBytes);
keyfis.close();
keydis.close();
// key specification
String modulusBase64 = new String(keyBytes);
Base64 b64 = new Base64();
String exponentBase64 = "65337"; //festgelegte Zahl http://crypto.stackexchange.com/questions/3110/impacts-of-not-using-rsa-exponent-of-65537
RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(1, b64.decode(modulusBase64)), new BigInteger(1, b64.decode(exponentBase64)));
// conversion
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
// generate publicKey
PublicKey publicKey = keyFactory.generatePublic(pubKeySpec);
// read signature
sigfis = new FileInputStream(signaturFile);
sigdis = new DataInputStream(sigfis);
byte[] sigBytes = new byte[(int) signaturFile.length()];
sigdis.readFully(sigBytes);
sigfis.close();
sigdis.close();
// initialize the signature
Signature sig = Signature.getInstance("RSA");
sig.initVerify(publicKey);
// supply signature object with the data to be verified
datafis = new FileInputStream(file);
datadis = new DataInputStream(datafis);
byte[] dataBytes = new byte[(int) file.length()];
datadis.readFully(dataBytes);
/*
int len;
while(datadis.available() != 0) {
len = datadis.read(dataBytes);
sig.update(dataBytes, 0, len);
}
*/
datadis.close();
datafis.close();
sig.update(dataBytes);
//verify signature
verifies = sig.verify(sigBytes);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (keyfis != null) {
keyfis.close();
}
if (keydis != null) {
keydis.close();
}
if (sigfis != null) {
sigfis.close();
}
if (sigdis != null) {
sigdis.close();
}
if (datafis != null) {
datafis.close();
}
if (datadis != null) {
datadis.close();
}
}
return verifies;
}
Finally i have a solution:
InputStream inSig = PGPUtil.getDecoderStream(new FileInputStream(signaturFile));
//ArmoredInputStream inSig = new ArmoredInputStream(new FileInputStream(signaturFile));
JcaPGPObjectFactory objFactory = new JcaPGPObjectFactory(inSig);
PGPSignatureList signatureList = (PGPSignatureList) objFactory.nextObject();
PGPSignature signature = signatureList.get(0);
InputStream keyIn = PGPUtil.getDecoderStream(new FileInputStream(publicKeyFile));
//ArmoredInputStream keyIn = new ArmoredInputStream(new FileInputStream(publicKeyFile));
JcaPGPPublicKeyRingCollection pgpRing = new JcaPGPPublicKeyRingCollection(keyIn);
PGPPublicKey publicKey = pgpRing.getPublicKey(signature.getKeyID());
byte[] bytePublicKeyFingerprint = publicKey.getFingerprint();
char[] publicKeyFingerprintHexArray = org.apache.commons.codec.binary.Hex.encodeHex(bytePublicKeyFingerprint);
String publicKeyFingerprintHex = new String(publicKeyFingerprintHexArray);
signature.init(new JcaPGPContentVerifierBuilderProvider().setProvider("BC"), publicKey);
FileInputStream in = new FileInputStream(file);
byte[] byteData = new byte[(int) file.length()];
in.read(byteData);
in.close();
signature.update(byteData);
if (signature.verify() && publicKeyFingerprintHex.equals(fingerprint)) {
return true;
} else {
return false;
}
Is it possible to encrypt a file with 2 RSA key (private key from pair A and public key from pair B), so that user B can open the file with his private key and A's public key?
I have code build in java and I still try encrypt it manually so I know my program work or not but when I try encrypt my data in second time's my data broken and didn't encrypt at all.
it's my code :
public static void main(String[] args) throws Exception {
generateKeys();
RSA.rsaEncrypt("AES.key","RSA(AES).key");
RSA.rsaDecrypt("RSA(AES).key","AES(RSA).key");
}
public static void generateKeys() throws Exception {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair kp = kpg.genKeyPair();
PublicKey publicKey = kp.getPublic();
PrivateKey privateKey = kp.getPrivate();
System.out.println("keys created");
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = fact.getKeySpec(publicKey,
RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = fact.getKeySpec(privateKey,
RSAPrivateKeySpec.class);
saveToFile("publicA.key", pub.getModulus(), pub.getPublicExponent());
saveToFile("privateA.key", priv.getModulus(), priv.getPrivateExponent());
System.out.println("keys saved");
}
public static void saveToFile(String fileName, BigInteger mod,
BigInteger exp) throws IOException {
ObjectOutputStream fileOut = new ObjectOutputStream(
new BufferedOutputStream(new FileOutputStream(fileName)));
try {
fileOut.writeObject(mod);
fileOut.writeObject(exp);
} catch (Exception e) {
throw new IOException("Unexpected error");
} finally {
fileOut.close();
System.out.println("Closed writing file.");
}
}
// Return the saved key
static Key readKeyFromFile(String keyFileName) throws IOException {
InputStream in = new FileInputStream(keyFileName);
ObjectInputStream oin = new ObjectInputStream(new BufferedInputStream(
in));
try {
BigInteger m = (BigInteger) oin.readObject();
BigInteger e = (BigInteger) oin.readObject();
KeyFactory fact = KeyFactory.getInstance("RSA");
if (keyFileName.startsWith("publicB")) {
return fact.generatePublic(new RSAPublicKeySpec(m, e));
} else {
return fact.generatePrivate(new RSAPrivateKeySpec(m, e));
}
} catch (Exception e) {
throw new RuntimeException("Spurious serialisation error", e);
} finally {
oin.close();
System.out.println("Closed reading file.");
}
}
// Use this PublicKey object to initialize a Cipher and encrypt some data
public static void rsaEncrypt(String file_loc, String file_des)
throws Exception {
byte[] data = new byte[32];
int i;
System.out.println("start encyption");
Key pubKey = readKeyFromFile("publicB.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
FileInputStream fileIn = new FileInputStream(file_loc);
FileOutputStream fileOut = new FileOutputStream(file_des);
CipherOutputStream cipherOut = new CipherOutputStream(fileOut, cipher);
// Read in the data from the file and encrypt it
while ((i = fileIn.read(data)) != -1) {
cipherOut.write(data, 0, i);
}
// Close the encrypted file
cipherOut.close();
fileIn.close();
System.out.println("encrypted file created");
}
// Use this PublicKey object to initialize a Cipher and decrypt some data
public static void rsaDecrypt(String file_loc, String file_des)
throws Exception {
byte[] data = new byte[32];
int i;
System.out.println("start decyption");
Key priKey = readKeyFromFile("privateB.key");
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, priKey);
FileInputStream fileIn = new FileInputStream(file_loc);
CipherInputStream cipherIn = new CipherInputStream(fileIn, cipher);
FileOutputStream fileOut = new FileOutputStream(file_des);
// Write data to new file
while ((i = cipherIn.read()) != -1) {
fileOut.write(i);
}
// Close the file
fileIn.close();
cipherIn.close();
fileOut.close();
System.out.println("decrypted file created");
}
If you want to ensure that the information really came from A, you should sign with A key pair, not encrypt it twice. In a nutshell:
Data -> Encrypt with B public Key -> Encrypted data -> Sign with A private key
Then send it to B who will verify A sign with A public key then open the encrypted data with his own private key.
With this method, you ll have:
- Privacy: encrypted with B public key, only B can open it.
- Non repudiation: Using A private key to sign, only A could have done it.
- Data integrity: When sign it and using a good hash function, you can check the received data for alteration.
Cheers.