Java digital signature with SHA1withRSA - java

I'm trying to to apply digital signature to a .txt file. The digital signature is applied successfully but whenever I try to verify it shows me Verified: false.
Here is my code for signing:
public void signData(){
Signature rsa = Signature.getInstance("SHA1withRSA");
rsa.initSign(privateKey);
File f= new File(path);
//read from file
FileInputStream fis = new FileInputStream(f);
byte[] buffer = new byte[(int) f.length()];
fis.read(buffer);
fis.close();
rsa.update(buffer);
//write to file
byte[] toWrite=rsa.sign();
String signPath;
signPath="Signed-"+f.getName();
File output=new File(signPath);
FileOutputStream fos = new FileOutputStream(output);
fos.write(toWrite);
fos.flush();
fos.close();
System.out.printf("File: %s is now signed in: %s\n\n",path,signPath);
}
Reading and verifying:
public void verify(){
Signature sig = Signature.getInstance("SHA1withRSA");
sig.initVerify(publicKey);
File f= new File(path);
FileInputStream fis = new FileInputStream(f);
byte[] buffer = new byte[(int) f.length()];
fis.read(buffer);
fis.close();
sig.update(buffer);
System.out.println("Verified: "+sig.verify(buffer));
}
No Errors are shown. KeyPair algorithm used is "RSA".
Thank you in advance.

For signing, you have the inputs private key and data to sign. The output is the signature.
For verifying, you have the inputs public key and signed data (actually it's the data to sign from the first step). You're missing the signature as an input. It should look like this:
sig.update(signedData);
System.out.println("Verified: "+sig.verify(signature));
Don't forget to read the signature from the file.

Related

Incremental Encryption with BouncyCastle PGP Utilities in Java

I'm trying to write an encrypted file that will be decrypted using gpg and will be writing lines incrementally instead of in one chunk. I've generated the keys in GnuPG and am using the public key to encrypt. Here's the method I'm using to encrypt:
public static byte[] encrypt(byte[] clearData, PGPPublicKey encKey,
String fileName,boolean withIntegrityCheck, boolean armor)
throws IOException, PGPException, NoSuchProviderException {
if (fileName == null) {
fileName = PGPLiteralData.CONSOLE;
}
ByteArrayOutputStream encOut = new ByteArrayOutputStream();
OutputStream out = encOut;
if (armor) {
out = new ArmoredOutputStream(out);
}
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(
PGPCompressedDataGenerator.ZIP);
OutputStream cos = comData.open(bOut); // open it with the final
// destination
PGPLiteralDataGenerator lData = new PGPLiteralDataGenerator();
// we want to generate compressed data. This might be a user option
// later,
// in which case we would pass in bOut.
OutputStream pOut = lData.open(cos, // the compressed output stream
PGPLiteralData.BINARY, fileName, // "filename" to store
clearData.length, // length of clear data
new Date() // current time
);
pOut.write(clearData);
lData.close();
comData.close();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(new BcPGPDataEncryptorBuilder(SymmetricKeyAlgorithmTags.AES_192).setSecureRandom(new SecureRandom()));
cPk.addMethod(new BcPublicKeyKeyEncryptionMethodGenerator(encKey));
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes); // obtain the actual bytes from the compressed stream
cOut.close();
out.close();
return encOut.toByteArray();
}
And I have a small prototype test class to use that method like this:
PGPPublicKey pubKey = PGPEncryptionTools.readPublicKeyFromCol(new FileInputStream(appProp.getKeyFileName()));
byte[] encryptbytes = PGPEncryptionTools.encrypt("\nthis is some test text".getBytes(), pubKey, null, true, false);
byte[] encryptbytes2 = PGPEncryptionTools.encrypt("\nmore test text".getBytes(), pubKey, null, true, false);
FileOutputStream fos = new FileOutputStream("C:/Users/me/workspace/workspace/spring-batch-project/resources/encryptedfile.gpg");
fos.write(encryptbytes);
fos.write(encryptbytes2);
fos.flush();
fos.close();
So this creates encryptedfile.gpg, but when I go to GnuPG to decrypt the file, it works but it only outputs the first line "this is some test text".
How can I modify this code to be able to encrypt both lines and have GnuPG decrypt them?
You're producing multiple, independent OpenPGP messages each time calling your PGPEncryptionTools.encrypt(...) method. To only output a single OpenPGP message (which GnuPG also decrypt in a single run), write all plain text to a single stream (called pOut in your code) and do not close this before finally writing the last byte into the stream.

Read different inputs from InputStream JAVA

I'm writing a code that send encrypted file from client to server
but first the client send the encrypted message digest of the file to the server and then send the name of the file and at the end it will send the bytes of encrypted file,
but in the server side it read all these variables as one variable which is the digest ,
and when the server trying to decrypt the digest it throws Illegal Block Size Exception
My question here is how can the server read and save them in different variables ??
Client
// set mode to encrypt
AesCipher.init(Cipher.ENCRYPT_MODE, key);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
// get the digest of the file
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(bytes);
// encrypt digest and write it to file
byte [] encryptedHash = AesCipher.doFinal(hash);
toServer.write(encryptedHash);
// write file name to server
toServer.writeUTF(fileName);
//encrypt file
byte[] encryptedByte = AesCipher.doFinal(bytes);
// write file to server
toServer.write(encryptedByte);
toServer.flush();
socket.close();
Server
// read digest of the file
byte [] digest =IOUtils.toByteArray(fromClient);
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
byte[] fileBytes = IOUtils.toByteArray(fromClient);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
also I tried this code but it didn't works too
// read digest of the file
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[1024];
while ((nRead = fromClient.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();
byte[] digest = buffer.toByteArray();
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
file.createNewFile();
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
byte[] fileBytes = IOUtils.toByteArray(fromClient);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
IOUtils.toByteArray(InputStream) reads the entire stream. So instead of just getting the hash bytes, you got the whole stream, and there was nothing left for the filename or the ciphertext, and the hash didn't check.
You don't need external libraries for this. You can do it all with DataInputStream and DataOutputStream. But you do need to send the length of the hash ahead of the hash.
Client:
// set mode to encrypt
AesCipher.init(Cipher.ENCRYPT_MODE, key);
DataOutputStream toServer = new DataOutputStream(socket.getOutputStream());
// get the digest of the file
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] hash = md.digest(bytes);
// encrypt digest and write it to file
byte [] encryptedHash = AesCipher.doFinal(hash);
toServer.writeInt(encryptedHash.length);
toServer.write(encryptedHash);
// write file name to server
toServer.writeUTF(fileName);
//encrypt file
byte[] encryptedByte = AesCipher.doFinal(bytes);
// write file to server
toServer.writeInt(encryptedByte.length);
toServer.write(encryptedByte);
socket.close();
Server:
// read digest of the file
int digestLength = fromClient.readInt();
byte[] digest = new byte[digestLength];
fromClient.readFully(digest);
// decrypt it
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedDigest = AesCipher.doFinal(digest);
// read file name to be received
String fileName = fromClient.readUTF();
File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName);
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
// read file bytes from client
int fileLength = fromClient.readInt();
byte[] fileBytes = new byte[fileLength];
fromClient.readFully(fileBytes);
AesCipher.init(Cipher.DECRYPT_MODE, key);
byte[] decryptedByte = AesCipher.doFinal(fileBytes);
bos.write(decryptedByte, 0, decryptedByte.length);
bos.close();
However the encryption and decryption parts of this would be much better done with CipherInputStream and CipherOutputStream. You shouldn't load entire files into memory.
Note that the file.createNewFile() call was redundant before new FileOutputStream(...).
Why you're encrypting a message digest is another mystery. You should be using it as a final step to compare with a locally-generated digest after decryption.

How to put a notification tell me that file is encrypted after using AES ? & How to check it is the file i encrypt or not ?

I am using AES symmetric encryption algorithm in java and after i encrypt file i want to put something on it to tell me it is encrypted so i can check for it is exist or not before decrypt it ?
Here is a sample of the code
` cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
jTextField3.setText(""+secretKeySpec);
String cleartextFile = "E:\\"+dir;
FileInputStream fis = new FileInputStream(cleartextFile);
CipherInputStream cis = new CipherInputStream(fis, cipher);
FileOutputStream fos = new FileOutputStream("E:\\d"+dir);
FileChannel out = fos.getChannel();
out.transferFrom(Channels.newChannel(cis), 0, Long.MAX_VALUE); `

error in decoding an encrypted text file in java

I encrypted a text file in AES algorithm. I am not able to decrypt it. I used the same key and the whole process is running in the same method body.
At first, the input.txt file is being encrypted into encrypted.txt file. Then the decoder, decrypt the encrypted.txt into decrypted.txt
Here is the code. Thank you for your help.
public static void main(String[] args) throws IOException,
NoSuchAlgorithmException, NoSuchPaddingException,
InvalidKeyException {
Scanner sc = new Scanner(System.in);
String filename = sc.nextLine();
sc.close();
System.out.println("The file requested is " + filename);
File file = new File(filename);
if (file.exists())
System.out.println("File found");
File to_b_encf = new File("encrypted.txt");
if (!to_b_encf.exists())
to_b_encf.createNewFile();
System.out.println("encrypting");
Cipher encipher = Cipher.getInstance("AES");
KeyGenerator keygen = KeyGenerator.getInstance("AES");
SecretKey key = keygen.generateKey();
encipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream output = new FileOutputStream(to_b_encf);
FileInputStream input = new FileInputStream(filename);
CipherInputStream cis = new CipherInputStream(input, encipher);
int read;
while ((read = cis.read()) != -1) {
output.write(read);
output.flush();
}
input.close();
output.close();
System.out.println("done");
System.out.println("decrypting");
Cipher decipher = Cipher.getInstance("AES");//initiate a cipher for decryption
decipher.init(Cipher.DECRYPT_MODE, key);//decrypt the file
File sourcefile = new File("encrypted.txt");
File destfile = new File("decrypted.txt");
if (!destfile.exists())
destfile.createNewFile();
FileInputStream decf = new FileInputStream(sourcefile);
CipherInputStream c_decf = new CipherInputStream(decf,decipher);
FileOutputStream destf = new FileOutputStream(destfile);
cout = new CipherOutputStream(destf,decipher);
while ((read = c_decf.read()) != -1) {
cout.write(read);
cout.flush();
}
c_decf.close();
destf.close();
cout.close();
decf.close();
System.out.println("done");
}
You messed with InputStream, OutputStream and whatnot. I made a simplfied version of your code (no files, all in-memory I/O) that illustrates the main concepts:
public class EncDec {
public static void main(String[] args) throws IOException
, InvalidKeyException, NoSuchAlgorithmException
, NoSuchPaddingException {
final String MESSAGE = "I'm a secret message";
final Charset CHARSET = Charset.defaultCharset();
Cipher cipher = Cipher.getInstance("AES");
SecretKey key = KeyGenerator.getInstance("AES").generateKey();
cipher.init(Cipher.ENCRYPT_MODE, key);
// Encrypt the message
InputStream plainIn = new ByteArrayInputStream(
MESSAGE.getBytes(CHARSET));
ByteArrayOutputStream encryptedOut = new ByteArrayOutputStream();
copy(plainIn, new CipherOutputStream(encryptedOut, cipher));
// Decrypt the message
cipher.init(Cipher.DECRYPT_MODE, key);
InputStream encryptedIn = new CipherInputStream(
new ByteArrayInputStream(encryptedOut.toByteArray()), cipher);
ByteArrayOutputStream plainOut = new ByteArrayOutputStream();
copy(encryptedIn, plainOut);
System.out.println(new String(plainOut.toByteArray(), CHARSET));
}
private static void copy(InputStream in, OutputStream out)
throws IOException {
byte[] buffer = new byte[4096];
while ( in.read(buffer) > -1) {
out.write(buffer);
}
out.flush();
}
}
The Java I/O API is inspired by the decorator pattern. Encryption/decription libraries provide a decorator CipherInputStream for reading encrypted content and a decorator CipherOutputStream to encrypt a plain source and write it to the decorated output destination.
CipherInputStream c_decf = new CipherInputStream(decf,decipher);
FileOutputStream destf = new FileOutputStream(destfile);
cout = new CipherOutputStream(destf,decipher);
while ((read = c_decf.read()) != -1) {
cout.write(read);
cout.flush();
}
It looks like you're deciphering it twice.

Decrypt the encrypted file content?

I am having a problem decrypting a file using RSA public key decryption. My process is to receive the xml file, encrypt the content, and write it back to the same file. Another function decrypts the content. My source code is:
public void decryptFile(String fileName,PrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
FileInputStream fis = new FileInputStream(fileName);
File file=new File("decryptedfile.xml");
if(file.exists()) {
file.delete();
}
FileOutputStream fos = new FileOutputStream("decryptedfile.xml");
CipherInputStream cis = new CipherInputStream(fis, cipher);
int i;
byte[] block = new byte[32];
//System.out.println("Read : "+cis.read(block));
while ((i = cis.read(block)) != -1) {
System.out.println(String.valueOf(i));
fos.write(block, 0, i);
}
fos.close();
}
I just pass in the name of the encrypted file, and the corresponding private key value, into the function. However the cis.read(block) returns -1 on the first attempt. Can anyone suggest how I can decrypt the encrypted file?
Your file is almost certainly not RSA encrypted. Its probably encrypted with AES under a random symmetric key and the key is then encrypted with RSA.
You are assuming someone actually encrypted the entire file using just RSA. Assuming the implementation even lets you do this (i've seen ones that throw exceptions when one tries this), it would be way way way too slow to do anything useful.

Categories

Resources