I'm using RSA (With Java) to cipher a text. I need to send that text via email.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.nio.Buffer;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import javax.crypto.Cipher;
public class importarLlaves {
/**
* #param args
*/
public static void main(String[] args) {
File archivo = new File("C:/llaves/Publica 2.txt");
File archivo2 = new File("C:/llaves/Privada 2.txt");
try {
BufferedReader lector = new BufferedReader(new FileReader(archivo));
String[] linea = lector.readLine().split(":");
String moduloPublico = linea[1];
linea = lector.readLine().split(":");
String exponentePublico = linea[1];
lector.close();
lector = new BufferedReader(new FileReader(archivo2));
lector.readLine();
linea = lector.readLine().split(":");
String exponentePrivado = linea[1];
lector.close();
String algorithm = "RSA";
KeyFactory factory = KeyFactory.getInstance(algorithm);
RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(new BigInteger(moduloPublico), new BigInteger(exponentePublico));
PublicKey llavePublica = factory.generatePublic(publicKeySpec);
RSAPrivateKeySpec privateKeySpec = new RSAPrivateKeySpec(new BigInteger(moduloPublico), new BigInteger(exponentePrivado));
PrivateKey llavePrivada = factory.generatePrivate(privateKeySpec);
System.out.println(llavePublica.toString());
System.out.println(llavePrivada.toString());
// Iniciar un objeto para la encr / desencr
Cipher desCipher = Cipher.getInstance("RSA");
// Leer, escribir y encriptar un dato
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String pwd = stdIn.readLine();
byte [ ] cleartext = pwd.getBytes();
String s1 = new String (cleartext);
System.out.println ("password original:" + s1 );desCipher.init (Cipher.ENCRYPT_MODE, llavePublica);
byte [ ] ciphertext = desCipher.doFinal(cleartext);
String s2 = new String (ciphertext);
System.out.println ("password encriptado:" + s2 );
// Ahora desencriptar
desCipher.init(Cipher.DECRYPT_MODE, llavePrivada);
byte [ ] cleartext1 = desCipher.doFinal(ciphertext);
String s3 = new String (cleartext1);
System.out.println("password desencriptado:"+ s3 );
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This code works great but when I try to decrypt it only works if I pass the original ciphertext byte.
byte [ ] cleartext1 = desCipher.doFinal(ciphertext);
I need to safely convert that encrypt from byte[] to an string (to send it vía email). But if I try like:
s2.getBytes();
It returns the bytes from the s2 string (where the encrypted text is stored). But if I try to use that string to pass to the desCipher (desencrypt) it fails and says that: DATA MUST NOT START WITH 0.
It's my understanding that not all bytes can clearly be encoded into characters (in a String). Encode it to base64 before sending, and then decode the base64 string before decryption.
The Apache Commons Codec project can encode/decode base64.
http://commons.apache.org/codec/
Related
I am trying to decrypt a file that was encrypted in Java using AES/CBC/PKCS5Padding. However, I'm having some trouble completely decrypting the file. I think I'm missing something simple. I am pretty new to encryption, so this is highly probable:
import base64
import re
from Crypto import Random
from Crypto.Cipher import AES
# generate the key
passphrase = "my_secret_passphrase"
key = passphrase[0:16].encode()
# load in the encrypted file as bytes
file_name = "tbd/enc.csv"
with open(file_name, "rb") as in_file:
encrypted_bytes = in_file.read()
# initialize the cipher
iv = Random.new().read(AES.block_size)
cipher = AES.new(key, AES.MODE_CBC, iv)
# use the cipher to decrypt the bytes
decrypted_bytes = cipher.decrypt(encrypted_bytes)
# write to an out_file
file = re.sub("\.csv", "_decoded.csv", file)
with open(file, "wb") as binary_file:
binary_file.write(decrypted_bytes)
Here's a the first line of text from what I get:
M¢p†‘GW§'tÄ%èéired Date,Employees - Id,First,Employees - Middle,Last,Employees - Preferred Name,Job Title,Employees - Marital Status,Employees - Trade Code,...
I noticed that the first 16 chars are complete gibberish, so I know I'm close. What could I be missing that is causing the first 16 chars to not be decoded properly? The weird thing is that we are able to decrypt the entire file in java, so we know its something wrong with the python implementation.
Bonus Round: the java code used to encrypt the file (I did not code it nor do I know java):
package rpa.ipaengine.bots.cmic.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class TestFile {
private static Logger LOGGER = LoggerFactory.getLogger(TestFile.class);
public static void main(String[] args) {
LOGGER.info("running");
try {
Security.setProperty("crypto.policy", "unlimited");
encryptedFile("my_secret_passphrase", "/tbd/enc.csv", "tbd/dec.csv");
decryptedFile("my_secret_passphrase", "/tbd/enc.csv", "tbd/dec.csv");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void encryptedFile(String secretKey, String fileInputPath, String fileOutPath)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException,
BadPaddingException {
try {
byte[] raw1 = "my_secret_passphrase"
.getBytes();
byte[] raw = new String(raw1, 0, 16).getBytes();
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, ivParams);
var fileInput = new File(fileInputPath);
var inputStream = new FileInputStream(fileInput);
var inputBytes = new byte[(int) fileInput.length()];
inputStream.read(inputBytes);
var outputBytes = cipher.doFinal(inputBytes);
var fileEncryptOut = new File(fileOutPath);
var outputStream = new FileOutputStream(fileEncryptOut);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
System.out.println("File successfully encrypted!");
System.out.println("New File: " + fileOutPath);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void decryptedFile(String secretKey, String fileInputPath, String fileOutPath)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException, IllegalBlockSizeException,
BadPaddingException, InvalidAlgorithmParameterException {
try {
byte[] raw1 = "my_secret_passphrase"
.getBytes();
byte[] raw = new String(raw1, 0, 16).getBytes();
Key skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] iv = new byte[cipher.getBlockSize()];
IvParameterSpec ivParams = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParams);
var fileInput = new File(fileInputPath);
var inputStream = new FileInputStream(fileInput);
var inputBytes = new byte[(int) fileInput.length()];
inputStream.read(inputBytes);
byte[] outputBytes = cipher.doFinal(inputBytes);
var fileEncryptOut = new File(fileOutPath);
var outputStream = new FileOutputStream(fileEncryptOut);
outputStream.write(outputBytes);
inputStream.close();
outputStream.close();
System.out.println("File successfully decrypted!");
System.out.println("New File: " + fileOutPath);
} catch (Exception e) {
e.printStackTrace();
}
}
}
Using bytes(16) as matt suggested, I was able to decipher the text completely:
import base64
import re
from Crypto import Random
from Crypto.Cipher import AES
# generate the key
passphrase = "my_secret_passphrase"
key = passphrase[0:16].encode()
# load in the encrypted file as bytes
file_name = "tbd/enc.csv"
with open(file_name, "rb") as in_file:
encrypted_bytes = in_file.read()
# initialize the cipher
iv = bytes(16)
cipher = AES.new(key, AES.MODE_CBC, iv)
# use the cipher to decrypt the bytes
decrypted_bytes = cipher.decrypt(encrypted_bytes)
# write to an out_file
file = re.sub("\.csv", "_decoded.csv", file)
with open(file, "wb") as binary_file:
binary_file.write(decrypted_bytes)
First line of file:
Employees - Hired Date,Employees - Id,First,Employees - Middle...
However Michael provides some valid comments about the Java code used to encrypt the file. I will work with my team to make sure its more secure.
I am trying to calculate the performance of ECDSA signature verification in Java for secp521r1 curve.
I am getting around 3000 signature verification per second.
Adding my other work also, I tested with openssl speed command for secp521r1 curve, there I got around 9000 verification on my machine (40 cores). I tested with Golang also but the performance with secp521r1 is not good, though the performance with secp256r1 is great(28000 verification per second). I reached out to Golang community and found 256 is hand optimized but other curves are not.
I also tested with nodeJs to verify signature, there I got 9000 verification per second which is similar to Openssl. By checking the source code of nodeJs crypto module implementation, I found they are using openssl like implementation.
But I have to work on Java only, so reaching out to the community. Is this the usual result in Java or do we have any openssl like implementation in Java as well?
Dummy Code==========================
package dummy;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Security;
import java.security.Signature;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.bouncycastle.asn1.DERInteger;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemReader;
import org.json.JSONObject;
public class DSA {
static JSONObject ob = new JSONObject();
static byte[] strByte = null;
static byte[] realSig;
static String str = "a";//"{\"type\":\"issueTx\",\"userId\":1,\"transaction\":{\"amount\":1000}}"; /a
static byte[] sigdata;
static String sigEdata;
static X509Certificate c;
static String sigTestSigneddata;
public static void main(String[] args)
throws InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException {
try {
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("EC");
keyGen.initialize(new ECGenParameterSpec("secp521r1"), new SecureRandom());
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();
FileWriter fw = new FileWriter("MyKeys/n.pem");
PemWriter writer = new PemWriter(fw);
writer.writeObject(new PemObject("PUBLIC KEY", pub.getEncoded()));
writer.close();
FileWriter fw2 = new FileWriter("MyKeys/n_sk");
PemWriter writer2 = new PemWriter(fw2);
writer2.writeObject(new PemObject("PRIVATE KEY ", priv.getEncoded()));
writer2.close();
Security.addProvider(new BouncyCastleProvider());
Signature ecdsa;
ecdsa = Signature.getInstance("SHA256withECDSA"); // SHA512WITHECDSA SHA512withECDSA
ecdsa.initSign(getPrivate("MyKeys/n_sk"));
strByte = str.getBytes("UTF-8");
ecdsa.update(strByte);
realSig = ecdsa.sign();
sigEdata = Base64.getEncoder().encodeToString(realSig);
Thread.sleep(1000);
verify();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void verify() throws Exception {
verifySignature();
}
private static void verifySignature() throws Exception {
Signature sig = Signature.getInstance("SHA256withECDSA", "BC"); // SHA256withECDSA // SHA512withECDSA
// sig.initVerify(c.getPublicKey()); to verify using digi cert
sig.initVerify(getPublic("MyKeys/n.pem"));
sig.update(str.getBytes());
System.out.println(sig.verify(Base64.getDecoder().decode(sigEdata)));
// sig.verify(sigEdata.getBytes(Charset.defaultCharset()));
System.out.println(str);
}
private static PrivateKey getPrivate(String filename) throws Exception {
PemReader reader = new PemReader(new FileReader(filename));
PemObject pemObject = reader.readPemObject();
byte[] content = pemObject.getContent();
reader.close();
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(content);
KeyFactory kf = KeyFactory.getInstance("EC");
return kf.generatePrivate(spec);
}
private static PublicKey getPublic(String filename) throws Exception {
PemReader reader = new PemReader(new FileReader(filename));
PemObject pemObject = reader.readPemObject();
byte[] content = pemObject.getContent();
reader.close();
X509EncodedKeySpec spec = new X509EncodedKeySpec(content);
KeyFactory kf = KeyFactory.getInstance("EC");
return kf.generatePublic(spec);
}
}
I'm writing a program which takes as input from the console - the name of a zip file, name of a zip file to be made containig the encrypted files generate from the first zip and a file containing the public key. I get an exception every time the stream closes:
Exception in thread "main" java.util.zip.ZipException: invalid entry size (expected 11 but got 128 bytes)
at java.util.zip.ZipOutputStream.closeEntry(ZipOutputStream.java:288)
at java.util.zip.ZipOutputStream.finish(ZipOutputStream.java:361)
at java.util.zip.DeflaterOutputStream.close(DeflaterOutputStream.java:238)
at java.util.zip.ZipOutputStream.close(ZipOutputStream.java:378)
at javax.crypto.CipherOutputStream.close(CipherOutputStream.java:217)
at com.Main.main(Main.java:107)
How can I fix this? The code is bellow:
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherOutputStream;
public class Main {
public final static int BUFFER_SIZE = 1024;
public static String getPublicKeyString(String fileName){
String key = new String();
try {
BufferedReader buf = new BufferedReader(new FileReader(fileName));
key = buf.readLine();
} catch ( IOException e) {
e.printStackTrace();
}
return key.trim();
}
public static PublicKey makePublicKey(String stored) throws GeneralSecurityException {
byte[] data = Base64.getDecoder().decode(stored);//Base64.decode(keyBytes, Base64.DEFAULT);
X509EncodedKeySpec spec = new X509EncodedKeySpec(data);
KeyFactory fact = KeyFactory.getInstance("RSA");
return fact.generatePublic(spec);
}
public static void main(String[] args) throws Exception {
Scanner scan = new Scanner(System.in);
System.out.println("Enter type of operation:");
String line = scan.nextLine();
if(line.equals("encrypt")){
// Reading from console
System.out.println("Enter name of original ZIP file:");
String originalZipFileName = scan.nextLine();
System.out.println("Enter name of new ZIP file:");
String newZipFileName = scan.nextLine();
System.out.println("Enter name of file containg public key:");
String publicKeyFileName = scan.nextLine();
String publicKey = getPublicKeyString(publicKeyFileName);
// Declaration
ZipFile originalZipFile = new ZipFile(originalZipFileName);
byte[] buffer = new byte[BUFFER_SIZE];
ZipOutputStream newZipFile = new ZipOutputStream(new FileOutputStream(newZipFileName));
Enumeration<? extends ZipEntry> zipEntries = originalZipFile.entries();
//
PublicKey key = makePublicKey(publicKey);
//System.out.println(key.toString());
//
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, key);
while(zipEntries.hasMoreElements()){
ZipEntry entry = zipEntries.nextElement();
ZipEntry copy = new ZipEntry(entry);
newZipFile.putNextEntry(copy);
int read;
InputStream input = originalZipFile.getInputStream(entry);
CipherOutputStream cos = new CipherOutputStream(newZipFile, cipher);
while((read = input.read(buffer)) != -1){
cos.write(buffer, 0, read);
}
input.close();
cos.close();
newZipFile.closeEntry();
}
}
}
}
RSA can only be used to encrypt relatively tiny amounts of data, less the size in bytes of the RSA modulus. When you execute cos.close(), the wrapped cipher object has its doFinal() method called which generates an IllegalBlockSizeException which is silently swallowed by CipherOutputStream. However, since no data made it through the cipher object the ZipOutputStream is messed up, so it throws an exception upon closure.
You can't use RSA the way you are trying to.
I'm writing a program that decrypt a file that was encrypted.
i recive the folowing output:
==============================
== Receiver\Decryptor side ==
==============================
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
Base64 cannot be resolved
Base64 cannot be resolved
Base64 cannot be resolved
at Decryptor.DecryptFileAndValidateSignature(Decryptor.java:97)
at Decryptor.main(Decryptor.java:65)
the error happens somwhere at these 3 lines -
ks.load(ksStream, receiverConfigurations.get("keyStorePass").toCharArray());
/* Loads private key from keyStore, needed to decrypt the symmetric key from configuration file */
PrivateKey receiverPrivateKey = (PrivateKey) ks.getKey(receiverConfigurations.get("receiverAlias"), receiverConfigurations.get("receiverKeyPass").toCharArray()); //private key of receiver
i guess something is wring with my imports..
as you can see i tried a lot. any help will be aprricated tnx
here is my code -
import java.io.File;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.Key;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.util.HashMap;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.security.KeyStore;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.codec.binary.Base64InputStream;
public class Decryptor {
public static void main(String args[]) throws Exception
{
if (args.length!=2)
{
System.out.println("Wrong number of parameters, please insert the path of encryptedTextFile.txt, cipherConfigurations.xml and the path for keystore file.\n" +
"Make sure that path is ended with '\\\\'. Example: c:\\\\test\\\\crypto\\\\keyStore.jks c:\\\\test\\\\crypto\\\\"
+ "\nAborting...\n");
return;
}
if (!Files.exists(Paths.get(args[0])))
{
System.out.println("Path "+args[0]+" doesn't exist.\nAborting...\n");
return;
}
String basePath = args[0];
String keyStore = args[1];
basePath = "c:\\test\\crypto\\";
System.out.println("-------------------------------------------------------------");
System.out.println("==============================");
System.out.println("== Receiver\\Decryptor side ==");
System.out.println("==============================");
/* Configurations that are known to the receiver */
HashMap<String,String> receiverConfigurations = new HashMap<>();
receiverConfigurations.put("encryptedTextFile" ,basePath+"encryptedTextFile.txt");
receiverConfigurations.put("configurationFile",basePath+"cipherConfigurations.xml");
receiverConfigurations.put("keyStorePass","gilperryB");
receiverConfigurations.put("receiverAlias","b_side");
receiverConfigurations.put("receiverKeyPass","gilperryB");
receiverConfigurations.put("decryptedTextFile",basePath+"decryptedText.txt");
receiverConfigurations.put("keyStorePath",keyStore);
receiverConfigurations.put("senderAlias","a_side");
DecryptFileAndValidateSignature(receiverConfigurations);
System.out.println("-------------------------------------------------------------");
}
/*
* Decrypts and validates a signature of an encrypted file that was sent between a sender and a receiver, in the following way:
* 1. Uses private key to encrypt a symmetric key from a configuration file.
* 2. Uses the symmetric key to decrypt the message sent in a different file
* 3. Calculates digital signature over the file, and compares it with the one received in the configuration file.
* 4. If the signatures match - returns true, else - returns false
* */
static public boolean DecryptFileAndValidateSignature(HashMap<String,String> receiverConfigurations) throws Exception
{
/* Load data from keyStore .jks file */
KeyStore ks = KeyStore.getInstance("jks"); // Load public key from keyStore
FileInputStream ksStream = new FileInputStream(receiverConfigurations.get("keyStorePath"));
ks.load(ksStream, receiverConfigurations.get("keyStorePass").toCharArray());
/* Loads private key from keyStore, needed to decrypt the symmetric key from configuration file */
PrivateKey receiverPrivateKey = (PrivateKey) ks.getKey(receiverConfigurations.get("receiverAlias"), receiverConfigurations.get("receiverKeyPass").toCharArray()); //private key of receiver
/* Load data received by the cipher configurations XML sent by sender */
HashMap<String,String> cipherConfigurations = ReadConfigurationXML(receiverConfigurations.get("configurationFile"));
if (cipherConfigurations == null)
{
System.out.println("Error reading cipher configurations XML.\nAborting...");
}
System.out.println("Read data Cipher configurations XML.");
/* Initialize the encryptor */
Cipher encryptor = Cipher.getInstance(cipherConfigurations.get("encryptionAlgoForSymmetricKey"), cipherConfigurations.get("encryptionAlgoForSymmetricKeyProvider"));
/* Get data from cipher configurations XML*/
byte[] symetricKeyEncrypted = Base64.decodeBase64(cipherConfigurations.get("symetricKeyEncrypted"));
/* Initialize the symmetric key encryptor */
Cipher rsaEncryptor = Cipher.getInstance(cipherConfigurations.get("encryptionAlgoForSendingSharedKey"), cipherConfigurations.get("encryptionAlgoForSendingSharedKeyProvider")); // encryptor for the secret key
byte[] symetricKeyDecrypted = DecryptText(symetricKeyEncrypted,rsaEncryptor,receiverPrivateKey, null);
byte[] ivConfig =Base64.decodeBase64(cipherConfigurations.get("ivspec"));
byte[] iv = DecryptText(ivConfig, rsaEncryptor, receiverPrivateKey, null);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
byte[] digitalSignature = Base64.decodeBase64(cipherConfigurations.get("digitalSignature"));
Key symmetricKeyAfterDecription = new SecretKeySpec(symetricKeyDecrypted, cipherConfigurations.get("encryptionAlgoForKeyGeneration")); //build a new secret key from text
System.out.println("Decrypted symmetric key using his own private key");
/* Decrypt file into decryptedFile */
DecryptFile(receiverConfigurations.get("encryptedTextFile"), receiverConfigurations.get("decryptedTextFile"), encryptor, symmetricKeyAfterDecription,ivSpec);
System.out.println("Decrypted text file "+receiverConfigurations.get("encryptedTextFile")+" into "+receiverConfigurations.get("decryptedTextFile"));
/* Verify digital signature */
PublicKey senderPublicKey = ks.getCertificate(receiverConfigurations.get("senderAlias")).getPublicKey(); //publicKey holds the public key for sender
boolean signatureValidated = ValidateDigitalSignature(receiverConfigurations.get("decryptedTextFile"),cipherConfigurations.get("digitalSignatureAlgorithm"),senderPublicKey,digitalSignature);
if (!signatureValidated)
{
System.out.println("Error decrypting text or validating digital signature.\nAborting...");
return false;
}
else
{
System.out.println("File was successfully decrypted, digital signature was successfully validated.\n");
return true;
}
}
/*
* Simulates the process where the receiver is calculating the signature of a message he received
* and compares it to the signature sent to him by sender.
* Calculates the digital signature over the decrypted file, using the digital signature algorithm in digitalSignatureAlgorithm,
* and public key in senderPublicKey.
* returns true iff the signatures match.
* */
private static boolean ValidateDigitalSignature(String decryptedFile,
String digitalSignatureAlgorithm, PublicKey senderPublicKey, byte[] signatureToVerify) throws Exception {
Signature dsa = Signature.getInstance(digitalSignatureAlgorithm); /* Initializing the object with the digital signature algorithm */
dsa.initVerify(senderPublicKey);
/* Update and sign the data */
FileInputStream fis = new FileInputStream(decryptedFile);
byte[] block = new byte[8];
int i;
while ((i = fis.read(block)) != -1) { //read all blocks in file
dsa.update(block); // update digital signature after each block
}
fis.close();
return dsa.verify(signatureToVerify);
}
/*
* Reads an encrypted text file and decrypts it using a Cipher object (encryptor).
* The decrypted file will be the returned value.
* Decryption process contains also Base64 encoding of the text.
*/
private static void DecryptFile(String inputFile,String outputFile, Cipher encryptor, Key key, IvParameterSpec ivspec) throws Exception
{
assert (CreateFileIfNecessery(outputFile) == true); //creates output file if necessery
FileInputStream fis = new FileInputStream(inputFile);
Base64InputStream b64os = new Base64InputStream(fis);
CipherInputStream cis = new CipherInputStream(b64os, encryptor);
FileOutputStream fos = new FileOutputStream(outputFile);
encryptor.init(Cipher.DECRYPT_MODE, key, ivspec); //initilize cipher in decryption mode with IV
byte[] block = new byte[8];
int i;
while ((i = cis.read(block)) != -1) { //read all blocks in file
{
fos.write(block,0,i); // write each block encrypted to the output file
}
}
b64os.close();
fos.close(); // close output file
cis.close(); // close input file
}
/*
* Reads the configuration XML from file in 'path'.
* Retuns a HashMap containing the entries and their value.
* if not possible - returns null.
*/
public static HashMap<String,String> ReadConfigurationXML(String path) throws Exception
{
HashMap<String,String> cipherConfigurations = new HashMap<>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc;
try{
doc = builder.parse(path);
}catch (Exception e)
{
System.out.println("Error reading configurations file "+path+"\nAborting...");
return null;
}
NodeList mainNode = null;
try
{
mainNode = doc.getElementsByTagName("CipherConfigurations");
}
catch (Exception e)
{
System.out.println("Could not find element EncryptionConfigurations in the configurations file.\nAborting...");
return null;
}
if (mainNode.getLength()!=1)
{
System.out.println("Wrong structure of cipher configutarion element.\nAborting...");
return null;
}
NodeList cipherConfigurationsRoot = (NodeList) mainNode.item(0); // get the root element of the configurations
for (int i = 0; i < cipherConfigurationsRoot.getLength(); ++i)
{
Element elem = (Element) cipherConfigurationsRoot.item(i);
String paramName = elem.getNodeName();
String innerText = elem.getTextContent();
cipherConfigurations.put(paramName, innerText);
}
return cipherConfigurations;
}
/*
* Reads an encrypted text and decrypts it using a Cipher object (encryptor).
* The decrypted text will be the returned value.
* Decryption process contains also Base64 encoding of the text.
*/
public static byte[] DecryptText(byte[] text, Cipher encryptor, Key key, IvParameterSpec ivspec) throws Exception
{
OutputStream os = new ByteArrayOutputStream();
InputStream is = new ByteArrayInputStream(text);
Base64InputStream b64is = new Base64InputStream(is);
CipherInputStream cis = new CipherInputStream(b64is, encryptor);
encryptor.init(Cipher.DECRYPT_MODE, key, ivspec); //initilize cipher in decryption mode with IV
byte[] block = new byte[8];
int i;
while ((i = cis.read(block)) != -1) { //read all blocks in file
{
os.write(block,0, i); // write each block encrypted to the output file
}
}
b64is.close();
os.close(); // close output file
is.close(); // close input file
cis.close();
return ((ByteArrayOutputStream) os).toByteArray();
}
/*
* Creates file and its paths if not exist.
* Example: path = c:\\test\\test1\\foo.txt
* Method will check if this path and file exists, if not - will create full hierarchy.
*/
private static boolean CreateFileIfNecessery(String path) throws Exception
{
File f = new File(path);
if (!f.mkdirs()) return false; //creates the directories for the file
if (!f.createNewFile()) return false; // creates the output file
return true;
}
}
You're missing Apache's commons-codec-1.10.jar
or
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>
if you're using Maven
I do RSA encryption and having a problem. I want to encrypt a string.To convert the string, I already have the rsHex array to convert it.. I run the source code but it give me error say "the system cannot find the file specified" Here is my source code. How do I solve his? Thanks for helping me :)
import de.flexiprovider.api.keys.PrivateKey;
import de.flexiprovider.api.keys.PublicKey;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.math.BigInteger;
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.spec.InvalidKeySpecException;
import java.security.spec.RSAPrivateKeySpec;
import java.security.spec.RSAPublicKeySpec;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
public class RSA {
private String str, s;
private String chipertext;
private byte[] cipherData;
public RSA(String string) throws Exception {
try {
String input = string;
FileReader read = new FileReader(input);
BufferedReader reader = new BufferedReader(read);
while ((s = reader.readLine()) != null) {
byte[] theByteArray = s.getBytes();
setUserinput(string);
rsHex(theByteArray);
}
} catch (Exception ex) {
Logger.getLogger(RSA.class.getName()).log(Level.SEVERE, null, ex);
}
//Creating an RSA key pair in Java
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); //instance of KeyPairGenerator
kpg.initialize(1024);//bit length of the modulus that required
KeyPair kp = kpg.genKeyPair();//returns a KeyPair object
Key publicKey = kp.getPublic(); //pull out the public and private keys
Key privateKey = kp.getPrivate();
//Saving the public and private key
//private key will be placed on our server, and the public key distributed to clients.
KeyFactory fact = KeyFactory.getInstance("RSA");
RSAPublicKeySpec pub = (RSAPublicKeySpec) fact.getKeySpec(publicKey, RSAPublicKeySpec.class);
RSAPrivateKeySpec priv = (RSAPrivateKeySpec) fact.getKeySpec(privateKey, RSAPrivateKeySpec.class);
// Save the file to local drive
saveToFile("c:\\public.key", pub.getModulus(), pub.getPublicExponent());
saveToFile("c:\\private.key", priv.getModulus(),priv.getPrivateExponent());
}
private void rsHex(byte[] bytes) throws Exception {
StringBuilder hex = new StringBuilder();
for (byte b : bytes) {
String hexString = Integer.toHexString(0x00FF & b);
hex.append(hexString.length() == 1 ? "0" + hexString : hexString);
}
setChipertext(hex.toString());
}
//save the moduli and exponents to file, we can just use boring old serialisation
public void saveToFile(String fileName, BigInteger mod, BigInteger exp) throws IOException {
FileOutputStream f = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(f);
oos.writeObject(mod);
oos.writeObject(exp);
oos.close();
}
////Encryption
//initialise the cipher with the public key that we previously saved to file.
PublicKey readKeyFromFile(String keyFileName) throws IOException {
PublicKey key = null;
try {
FileInputStream fin = new FileInputStream(keyFileName);
ObjectInputStream ois = new ObjectInputStream(fin);
BigInteger m = (BigInteger) ois.readObject();
BigInteger e = (BigInteger) ois.readObject();
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(m, e);
KeyFactory fact = KeyFactory.getInstance("RSA");
java.security.PublicKey pubKey = fact.generatePublic(keySpec);
ois.close();
}
catch (Exception e) {
e.printStackTrace();
}
return key;
}
public void rsaEncrypt(String str)throws Exception {
PublicKey pubKey = readKeyFromFile(str);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);//initialise the cipher
cipherData = cipher.doFinal(str.getBytes());//passing in the data to be encrypted
rsHex(cipherData);
}
public String getUserinput() {
return str;
}
public String getChipertext() {
return chipertext;
}
public void setUserinput(String input) {
this.str = input;
}
public void setChipertext(String chipertext) throws Exception {
this.chipertext = chipertext;
}
}
----main Program------
import java.util.Scanner;
public class TWO{
public static void main(String[] args) throws Exception{
Scanner scan = new Scanner(System.in);
System.out.println("Insert your string");
String str = scan.nextLine();
RSA two = new RSA(str);
System.out.println("Encrypted: "+ two.getChipertext());
}
}
The problem is that you're taking an input string from the user, but then your code is treating this as though it was a filename by constructing a FileReader with that string.
Instead of all that nonsense with the FileReader and BufferedReader, is there any reason why you don't just use string.getBytes()?
You also seem to be making life awfully complicated for yourself: you're taking a string, converting into a byte array, then converting that into a string again (with hex representation), then converting that into a byte array again. That's an awful lot of messing about when you could really just take the byte representation of the original string (as given to you by getBytes()) and pass that directly to the RSA encryption.