I am attempting to implement HMAC using SHA-1 as the base. Using SHA-1 algorithm from bouncy castle, and implement the HMAC computation. Also to use SHA-1 to hash the input password to get the key for the HMAC algorithm. I've been trying to do this for a few hours but I really have a poor understanding of HMAC. If anyone has any tips on how to do this it would be appreciated. My code below is my implementation of SHA1, via a library function call, I'm essentially just trying to implement it with HMAC.
public class HMACSHA1 {
static byte[] password;
static byte[] fileName = null;
static byte[] input = new byte[16];
static String File;
public static void main(String[] args) {
Security.addProvider(Security.getProvider("BC"));
if(args.length != 2){
System.out.println("Invalid input");
System.exit(-1);
}
File = args[1];
try {
password = args[0].getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("Unable to read password");
System.exit(-1);
}
InputStream inputstream = null;
try {
inputstream = new FileInputStream(File);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
System.out.println("No input found\n");
System.exit(-1);
}
MessageDigest hash = null;
MessageDigest key = null;
try {
hash = MessageDigest.getInstance("SHA-1", "BC");
key = MessageDigest.getInstance("SHA-1", "BC");
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
key.update(password);
byte[] HMACKey = key.digest();
byte[] digest = null;
int reader = 0;
while (reader != -1){
try {
reader = inputstream.read(input);
} catch (IOException e2) {
e2.printStackTrace();
}
hash.update(input);
digest = hash.digest();
System.out.println(new String(Hex.encode(digest)));
}
}
}
I am not familiar with Bouncy Castle, but you can work out the HMAC-SHA1 without external libraries using only what is provided with Java SE:
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
public String getHmacSha1(byte[] key, byte[] input) throws NoSuchAlgorithmException {
SecretKeySpec signingKey = new SecretKeySpec(key, "HmacSHA1");
Mac mac = null;
mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
byte[] digest = mac.doFinal(input);
return Hex.encodeHexString(digest);
}
This is available since Java 1.4 according to the API.
Related
When I encrypt the password !QAZxdr5 by the code below:
public static String encryptPassword(String msg) {
try {
KeySpec keySpec = new DESKeySpec(msg.getBytes());
SecretKey key = SecretKeyFactory.getInstance("DES").generateSecret(keySpec);
Cipher ecipher = Cipher.getInstance(key.getAlgorithm());
ecipher.init(Cipher.ENCRYPT_MODE, key);
//Encode the string into bytes using utf-8
byte[] utf8 = msg.getBytes("UTF8");
//Encrypt
byte[] enc = ecipher.doFinal(utf8);
//Encode bytes to base64 to get a string
return new String(Base64.getEncoder().encode(enc));
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return null;
}
I got the output: QQiu2a4NT9YfDAtmHjbk1A==
Now I try to create the decryption for this:
public static String decrypt(String msg) {
try {
KeySpec keySpec = new DESKeySpec(msg.getBytes());
SecretKey key =
SecretKeyFactory.getInstance("DES").generateSecret(keySpec);
Cipher decipher = Cipher.getInstance(key.getAlgorithm());
decipher.init(Cipher.DECRYPT_MODE, key);
// Decode base64 to get bytes
byte[] dec = Base64.getDecoder().decode(msg.getBytes("UTF-8"));
//Decrypt
byte[] utf8 = decipher.doFinal(dec);
//Decode using utf-8
return new String(utf8, "UTF8");
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return null;
}
However, it doesn't work properly as it returned null :(. Can you please help to check where I'm wrong?
Normally, Base64 encoding of !QAZxdr5 is IVFBWnhkcjU=, however, your code uses a key to encode extra AFAI understand, that's why you get QQiu2a4NT9YfDAtmHjbk1A==. So, decrypt() method needs to know also the key generated already, nonetheless, yours wouldn't.
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.Base64;
class EncryptDecryptTest {
public static void main(String[] args) throws Exception {
String key = "it's our key ~~~where is my +1 karma ??~~~ - soner";
String ciphertext = encrypt(key, "!QAZxdr5");
String decrypted = decrypt(key, ciphertext.trim());
String encrypted = encrypt(key, decrypted.trim());
if (ciphertext.contentEquals(encrypted.trim())) {
System.out.println("decrypted!");
} else {
System.out.println("wrong key!");
}
}
public static String encrypt(String key, String data)
throws GeneralSecurityException {
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
return Base64.getEncoder().encodeToString(cipher.doFinal(dataBytes));
}
public static String decrypt(String key, String data)
throws GeneralSecurityException {
byte[] dataBytes = Base64.getDecoder().decode(data);
DESKeySpec desKeySpec = new DESKeySpec(key.getBytes(StandardCharsets.UTF_8));
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] dataBytesDecrypted = (cipher.doFinal(dataBytes));
return new String(dataBytesDecrypted);
}
}
As a side note,
The fact that return new String(Base64.getEncoder().encode(enc)); uses toString() method of array
should be return Base64.getEncoder().encodeToString(enc); in order to get expected encoded datum.
In DES encryption, it uses the same key to encrypt and decrypt a message.
So for both operations you need to have the same key.
In your case, you have used the same string as the key and as the password.
public static String encryptPassword(String msg) {
try {
KeySpec keySpec = new DESKeySpec(msg.getBytes());
In above code segment when creating new DESKeySpec object, you need to pass the key as well.
public static String decrypt(String msg) {
try {
KeySpec keySpec = new DESKeySpec(msg.getBytes());
Even in above decypt method you have to pass the same key you have used in encrypt method.
But in this you have given the encoded string to generate the key.
That is where you have gone wrong.
So i suggest you to change the methods parameters by adding one more parameter as key and then pass the same value for key in both methods.
public static String encryptPassword(String msg, String keySp) {
try {
KeySpec keySpec = new DESKeySpec(keySp.getBytes());
}
public static String decrypt(String msg, String keySp) {
try {
KeySpec keySpec = new DESKeySpec(keySp.getBytes());
}
I have included only the lines that needed to be changed.
You can call those methods by,
String key = "!QAZxdr5";
String password = "!QAZxdr5";
String encriptedPassword = encryptPassword(password, key);
System.out.println(decrypt(encriptedPassword, key));
i am using GPG4Win for encrypt the file and then BouncyCastle for decrypt file but code is not working
suppose i use BouncyCastle code for encrypt file and then use BouncyCastle decryption code its able to decrypt file and GPG4win also able to decrypt the file.
all code in java
suppose file is encrypted by BouncyCastle its decrypt by GPG4win and BouncyCastle
org.bouncycastle.openpgp.PGPException: Exception starting decryption
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at com.pgp.util.KeyBasedFileProcessorUtil.decryptFile(KeyBasedFileProcessorUtil.java:183)
at com.pgp.encrypt.PGPDecryption.main(PGPDecryption.java:49)
Caused by: java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.a(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
... 5 more
org.bouncycastle.openpgp.PGPException: Exception starting decryption
java.security.InvalidKeyException: Illegal key size
at javax.crypto.Cipher.a(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at javax.crypto.Cipher.init(DashoA13*..)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at org.bouncycastle.openpgp.PGPPublicKeyEncryptedData.getDataStream(Unknown Source)
at com.pgp.util.KeyBasedFileProcessorUtil.decryptFile(KeyBasedFileProcessorUtil.java:183)
at com.pgp.encrypt.PGPDecryption.main(PGPDecryption.java:49)
my code is
import org.bouncycastle.bcpg.ArmoredOutputStream;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openpgp.PGPCompressedData;
import org.bouncycastle.openpgp.PGPCompressedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedData;
import org.bouncycastle.openpgp.PGPEncryptedDataGenerator;
import org.bouncycastle.openpgp.PGPEncryptedDataList;
import org.bouncycastle.openpgp.PGPException;
import org.bouncycastle.openpgp.PGPLiteralData;
import org.bouncycastle.openpgp.PGPObjectFactory;
import org.bouncycastle.openpgp.PGPOnePassSignatureList;
import org.bouncycastle.openpgp.PGPPrivateKey;
import org.bouncycastle.openpgp.PGPPublicKey;
import org.bouncycastle.openpgp.PGPPublicKeyEncryptedData;
import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKey;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.bouncycastle.openpgp.PGPUtil;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.security.Security;
import java.util.Iterator;
import java.io.*;
/**
* A simple utility class that encrypts/decrypts public key based
* encryption files.
* <p>
* To encrypt a file: KeyBasedFileProcessor -e [-a|-ai] fileName publicKeyFile.<br>
* If -a is specified the output file will be "ascii-armored".
* If -i is specified the output file will be have integrity checking added.
* <p>
* To decrypt: KeyBasedFileProcessor -d fileName secretKeyFile passPhrase.
* <p>
* Note 1: this example will silently overwrite files, nor does it pay any attention to
* the specification of "_CONSOLE" in the filename. It also expects that a single pass phrase
* will have been used.
* <p>
* Note 2: if an empty file name has been specified in the literal data object contained in the
* encrypted packet a file with the name filename.out will be generated in the current working directory.
*/
public class KeyBasedFileProcessorUtil
{
/**
* A simple routine that opens a key ring file and loads the first available key suitable for
* encryption.
*
* #param in
* #return
* #throws IOException
* #throws PGPException
*/
public static PGPPublicKey readPublicKey(
InputStream in)
throws IOException, PGPException
{
in = PGPUtil.getDecoderStream(in);
PGPPublicKeyRingCollection pgpPub = new PGPPublicKeyRingCollection(in);
//
// we just loop through the collection till we find a key suitable for encryption, in the real
// world you would probably want to be a bit smarter about this.
//
//
// iterate through the key rings.
//
Iterator rIt = pgpPub.getKeyRings();
while (rIt.hasNext())
{
PGPPublicKeyRing kRing = (PGPPublicKeyRing)rIt.next();
Iterator kIt = kRing.getPublicKeys();
while (kIt.hasNext())
{
PGPPublicKey k = (PGPPublicKey)kIt.next();
if (k.isEncryptionKey())
{
return k;
}
}
}
throw new IllegalArgumentException("Can't find encryption key in key ring.");
}
/**
* Search a secret key ring collection for a secret key corresponding to
* keyID if it exists.
*
* #param pgpSec a secret key ring collection.
* #param keyID keyID we want.
* #param pass passphrase to decrypt secret key with.
* #return
* #throws PGPException
* #throws NoSuchProviderException
*/
public static PGPPrivateKey findSecretKey(
PGPSecretKeyRingCollection pgpSec,
long keyID,
char[] pass)
throws PGPException, NoSuchProviderException
{
PGPSecretKey pgpSecKey = pgpSec.getSecretKey(keyID);
if (pgpSecKey == null)
{
return null;
}
return pgpSecKey.extractPrivateKey(pass, "BC");
}
/**
* decrypt the passed in message stream
*/
public static void decryptFile(
InputStream in,
InputStream keyIn,
char[] passwd,
String defaultFileName)
throws Exception
{
System.out.println("File Decrypting");
System.out.println("File absulatePath :-");
in = PGPUtil.getDecoderStream(in);
try
{
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
//
// the first object might be a PGP marker packet.
//
if (o instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList)o;
}
else
{
enc = (PGPEncryptedDataList)pgpF.nextObject();
}
//
// find the secret key
//
System.out.println("find the secret key");
Iterator it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(
PGPUtil.getDecoderStream(keyIn));
while (sKey == null && it.hasNext())
{
pbe = (PGPPublicKeyEncryptedData)it.next();
sKey = findSecretKey(pgpSec, pbe.getKeyID(), passwd);
}
if (sKey == null)
{
System.out.println("--------------------");
System.out.println("secret key for message not found.");
throw new IllegalArgumentException("secret key for message not found.");
}
System.out.println("secret key for message found.");
InputStream clear = pbe.getDataStream(sKey, "BC");
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
Object message = plainFact.nextObject();
if (message instanceof PGPCompressedData)
{
PGPCompressedData cData = (PGPCompressedData)message;
PGPObjectFactory pgpFact = new PGPObjectFactory(cData.getDataStream());
message = pgpFact.nextObject();
}
if (message instanceof PGPLiteralData)
{
PGPLiteralData ld = (PGPLiteralData)message;
String outFileName = ld.getFileName();
if (ld.getFileName().length() == 0)
{
outFileName = defaultFileName;
}
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0)
{
fOut.write(ch);
}
}
else if (message instanceof PGPOnePassSignatureList)
{
System.out.println("encrypted message contains a signed message - not literal data.");
throw new PGPException("encrypted message contains a signed message - not literal data.");
}
else
{
throw new PGPException("message is not a simple encrypted file - type unknown.");
}
if (pbe.isIntegrityProtected())
{
if (!pbe.verify())
{
System.err.println("message failed integrity check");
}
else
{
System.err.println("message integrity check passed");
}
}
else
{
System.err.println("no message integrity check");
}
}
catch (PGPException e)
{
e.printStackTrace();
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
/*
private static void decryptFile(
InputStream in,
InputStream keyIn,
char[] passwd)
throws Exception
{
in = PGPUtil.getDecoderStream(in);
try
{
PGPObjectFactory pgpF = new PGPObjectFactory(in);
PGPEncryptedDataList enc;
Object o = pgpF.nextObject();
//
// the first object might be a PGP marker packet.
//
if (o instanceof PGPEncryptedDataList)
{
enc = (PGPEncryptedDataList)o;
}
else
{
enc = (PGPEncryptedDataList)pgpF.nextObject();
}
//
// find the secret key
//
Iterator it = enc.getEncryptedDataObjects();
PGPPrivateKey sKey = null;
PGPPublicKeyEncryptedData pbe = null;
while (sKey == null && it.hasNext())
{
pbe = (PGPPublicKeyEncryptedData)it.next();
sKey = findSecretKey(keyIn, pbe.getKeyID(), passwd);
}
if (sKey == null)
{
throw new IllegalArgumentException("secret key for message not found.");
}
InputStream clear = pbe.getDataStream(sKey, "BC");
PGPObjectFactory plainFact = new PGPObjectFactory(clear);
PGPCompressedData cData = (PGPCompressedData)plainFact.nextObject();
InputStream compressedStream = new BufferedInputStream(cData.getDataStream());
PGPObjectFactory pgpFact = new PGPObjectFactory(compressedStream);
Object message = pgpFact.nextObject();
if (message instanceof PGPLiteralData)
{
PGPLiteralData ld = (PGPLiteralData)message;
FileOutputStream fOut = new FileOutputStream(ld.getFileName());
BufferedOutputStream bOut = new BufferedOutputStream(fOut);
InputStream unc = ld.getInputStream();
int ch;
while ((ch = unc.read()) >= 0)
{
bOut.write(ch);
}
bOut.close();
}
else if (message instanceof PGPOnePassSignatureList)
{
throw new PGPException("encrypted message contains a signed message - not literal data.");
}
else
{
throw new PGPException("message is not a simple encrypted file - type unknown.");
}
if (pbe.isIntegrityProtected())
{
if (!pbe.verify())
{
System.err.println("message failed integrity check");
}
else
{
System.err.println("message integrity check passed");
}
}
else
{
System.err.println("no message integrity check");
}
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
*/
public static void encryptFile(
OutputStream out,
String fileName,
PGPPublicKey encKey,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
try
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(1);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
comData.close();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, withIntegrityCheck, new SecureRandom(), "BC");
cPk.addMethod(encKey);
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cOut.close();
out.close();
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
public static void encryptFile1(
OutputStream out,
String fileName,
PGPPrivateKey encKey,
boolean armor,
boolean withIntegrityCheck)
throws IOException, NoSuchProviderException
{
if (armor)
{
out = new ArmoredOutputStream(out);
}
try
{
ByteArrayOutputStream bOut = new ByteArrayOutputStream();
PGPCompressedDataGenerator comData = new PGPCompressedDataGenerator(1);
PGPUtil.writeFileToLiteralData(comData.open(bOut), PGPLiteralData.BINARY, new File(fileName));
comData.close();
PGPEncryptedDataGenerator cPk = new PGPEncryptedDataGenerator(PGPEncryptedData.CAST5, withIntegrityCheck, new SecureRandom(), "BC");
cPk.addMethod((PGPPublicKey) encKey.getKey());
byte[] bytes = bOut.toByteArray();
OutputStream cOut = cPk.open(out, bytes.length);
cOut.write(bytes);
cOut.close();
out.close();
}
catch (PGPException e)
{
System.err.println(e);
if (e.getUnderlyingException() != null)
{
e.getUnderlyingException().printStackTrace();
}
}
}
}
Decryption classs
public class PGPDecryption {
/**
*
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Properties prop=new Properties();
try {
prop.load(new FileInputStream("config.prop"));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileInputStream keyOut=null;
FileOutputStream out =null;
Security.addProvider(new BouncyCastleProvider());
try {
System.out.println(prop.getProperty(Constant.PRIVATE_KEY));
keyOut = new FileInputStream(prop.getProperty(Constant.PRIVATE_KEY));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
KeyBasedFileProcessorUtil.decryptFile(new FileInputStream(prop.getProperty(Constant.ENCRYPT_FILE_PATH)), keyOut, prop.getProperty(Constant.PRIVATE_FILE_PASS).toCharArray(), prop.getProperty(Constant.DECRYPT_FILE_OUTPUT_PATH));
System.out.println("Decrypted File created with name of "+prop.getProperty(Constant.DECRYPT_FILE_OUTPUT_PATH));
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Encryption class
public class PGPEncryption {
public static void main(String[] args) {
// TODO Auto-generated method stub
Properties prop=new Properties();
try {
File f=new File("config.prop");
System.out.println(f.getAbsolutePath());
prop.load(new FileInputStream(f));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
FileInputStream keyIn=null;
FileOutputStream out =null;
Security.addProvider(new BouncyCastleProvider());
try {
System.out.println(prop.getProperty(Constant.PUBLIC_KEY));
keyIn = new FileInputStream(prop.getProperty(Constant.PUBLIC_KEY));
System.out.println("Encrypt File Path :-"+prop.getProperty(Constant.ENCRYPT_FILE_PATH));
out= new FileOutputStream(new File(prop.getProperty(Constant.ENCRYPT_FILE_PATH)));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
boolean armor = false;
boolean integrityCheck = false;
PGPPublicKey pubKey = null;
try {
System.out.println("Reading public key.........");
pubKey = KeyBasedFileProcessorUtil.readPublicKey(keyIn);
System.out.println("Public Key found...........");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (PGPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
System.out.println("File Encrypting............");
KeyBasedFileProcessorUtil.encryptFile(out, prop.getProperty(Constant.SOURCE_FILE_PATH), pubKey, armor, integrityCheck);
System.out.println("Encrypted File created with name of "+prop.getProperty(Constant.ENCRYPT_FILE_PATH));
} catch (NoSuchProviderException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
please help me i want to decrypt the file those encrypted by GPG4win
To solve this problem now, i am using Cryptix OpenPGP.
its working properly without any error or exception.
link to download Cryptix lib
http://www.cryptix.org/
in that download two project library
Cryptix OpenPGP
Cryptix JCE
I have the following Java code which correctly decrypts a base64 encoded payload:
private static byte[] decryptPBKDF2WithBC(char[] password, byte[] data, byte[] salt, byte[] iv)
throws NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException,
InvalidAlgorithmParameterException, IllegalBlockSizeException, BadPaddingException {
PBEParametersGenerator generator = new PKCS5S2ParametersGenerator();
generator.init(PBEParametersGenerator.PKCS5PasswordToUTF8Bytes(password), salt,1024);
KeyParameter params = (KeyParameter)generator.generateDerivedParameters(256);
byte[] endcoded = params.getKey();
SecretKey key = new SecretKeySpec(endcoded, "AES");
Cipher ciph = Cipher.getInstance("AES/CBC/PKCS5Padding");
ciph.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return ciph.doFinal(data);
}
public String decrypt(String encrypted){
String salt = SALT;
String password = PASSWORD;
String[] parts = encrypted.split("--");
if (parts.length != 2) return null;
byte[] encryptedData = Base64.decode(parts[0], Base64.DEFAULT);
byte[] iv = Base64.decode(parts[1], Base64.DEFAULT);
byte[] result = null;
try {
result = decryptPBKDF2WithBC(password.toCharArray(), encryptedData, salt.getBytes(), iv);
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeySpecException e) {
e.printStackTrace();
} catch (NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
try {
return new String(result, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return null;
}
catch(Exception e){
e.printStackTrace();
return null;
}
}
The problem I'm having is that I need to port this to IOS. I've searched for several examples online, but I haven't been able to find one that uses a password, a salt and an IV. Are there any security/IOS experts who know enough about the IOS crypto libraries to at least point me in the right direction (which libraries to use or any code samples)?
Use RNCryptor if possible.
On iOS use the CommonCrypto library for the decryption along with the NSData Base64 methods.
You need to add Security.framework and you can look at the header files for the methods and more information.
Iam using TripleDes /cbc/pkcs7padding in C#.net to encrypt file.
and i need to decrypt in java.In java am using DESede/CBC/PKcs5padding
But the file is decrypted,but corrupted.
*In java is it possible to use pkcs7padding?
or any other solution to decrypt the file in java with encrypted using pkcs7 padding
C# code
namespace EncryptEpubFiles
{
public class Encryptor
{
public static bool EncryptBook(FileInfo fileToEncrypt,string outPathWithoutExtension,string keyString)
{
try
{
byte[] encryptedFileByteArray;
//Start Encryption service provider
TripleDESCryptoServiceProvider tDES = new TripleDESCryptoServiceProvider();
//Read all bytes from input file
byte[] _fileByteArray = File.ReadAllBytes(fileToEncrypt.FullName);
tDES.Key = GetBytes(keyString);
tDES.Mode = CipherMode.CBC;
//tDES.Padding = PaddingMode.PKCS7;
tDES.Padding = PaddingMode.PKCS7;
ICryptoTransform trans = tDES.CreateEncryptor();
//Create Encrypted file byte array
encryptedFileByteArray = (trans.TransformFinalBlock(_fileByteArray, 0, ((_fileByteArray).Length)));
//Write Encrypted file byte array to a filr with proper extension
System.IO.File.WriteAllBytes((outPathWithoutExtension + ".akr"), encryptedFileByteArray);
return true;
}
catch (Exception ex)
{
return false;
}
}
Java code
public class DecryptFinal {
private static Cipher dcipher;
private static byte[] iv = {
(byte)0xB2, (byte)0x12, (byte)0xD5, (byte)0xB2,
(byte)0x44, (byte)0x21, (byte)0xC3, (byte)0xC3
};
public static void main(String[] args){
try {
String s = "123456789123456789111234";
AlgorithmParameterSpec paramSpec = new IvParameterSpec(iv);
SecretKeyFactory keyfactory=SecretKeyFactory.getInstance("DESede");
byte[] encodedkey=s.getBytes();
System.out.println();
SecretKey key = keyfactory.generateSecret(new DESedeKeySpec(encodedkey));
System.out.println(new DESedeKeySpec(encodedkey));
SecretKeySpec(encodedKey,0,encodedKey.length,"DESede" );
dcipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
dcipher.init(Cipher.DECRYPT_MODE, key, paramSpec);
FileInputStream fs =new FileInputStream("E:\\Test1\\Test1\\Encrypted Files\\Wedding bells.akr");
FileOutputStream os= new FileOutputStream("E:\\Test1\\Test1\\Encrypted Files\\Encrypted Files\\E-pub Totorials");
byte[] buf = new byte[1024];// bytes read from stream will be decrypted
CipherInputStream cis = new CipherInputStream(fs, dcipher);// read in the decrypted bytes and write the clear text to out
int numRead = 0;
while ((numRead = cis.read(buf)) >= 0) {
os.write(buf, 0, numRead);
}
cis.close();// close all streams
fs.close();
os.close();
}
catch(FileNotFoundException e) {
System.out.println("File Not Found:" + e.getMessage());
return;
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
System.out.println("I/O Error:" + e.getMessage());
}
catch (InvalidKeySpecException e) {
// TODO: handle exception
e.printStackTrace();
}
I have an application consisting of three services: Client, Server and TokenService. In order to access data on the Server, Client has to obtain SecurityToken object from TokenService. The communication between parties is encrypted using shared keys (Client and TokenService share a key 'A' and TokenService and Server share a different key 'B'). When Client sends request to TokenService then the communication is encrypted with 'A'. When TokenService returns SecurityToken object, this object is encrypted with B and A like this: ((SecurityToken)B)A). This doubly encrypted object first goes back to Client, Client decrypts it with A, puts it into another object, attaches some additional information (String with request) and sends it to the Server where SecurityToken gets decrypted with B.
Everything works fine until I'am decrypting SecurityToken object on the server side. I get Exception:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:749)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:675)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:40)
at mds.hm5.tokenservice.Main2.main(Main2.java:28)
I was able to recreate this error (without remote communication between parties) like this:
public static void main(String[] args) {
SecurityToken s = new SecurityToken(false, "2");
try {
byte[] bytes = Encryptor.getBytesFromObject(s);
bytes = Encryptor.encryptData(bytes, "secretkey1");
bytes = Encryptor.encryptData(bytes, "secretkey2");
bytes = Base64.encodeBase64(bytes);
System.out.println(bytes);
bytes = Base64.decodeBase64(bytes);
bytes = Decryptor.decryptData(bytes, "secretkey2");
bytes = Decryptor.decryptData(bytes, "secretkey1");
SecurityToken s2 = (SecurityToken) Decryptor.getObjectFromBytes(bytes);
System.out.println(s2.getRole());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
I have no idea what I'am doing wrong here. Is it impossible to create two layers of encryption just like that? Am I missing something?
Additional information:
Here is my Encryptor class:
public class Encryptor {
public static byte[] encryptData(byte[] credentials, String key){
Cipher c;
SecretKeySpec k;
byte[] byteCredentials = null;
byte[] encryptedCredentials = null;
byte[] byteSharedKey = null;
try {
byteCredentials = getBytesFromObject(credentials);
byteSharedKey = getByteKey(key);
c = Cipher.getInstance("AES");
k = new SecretKeySpec(byteSharedKey, "AES");
c.init(Cipher.ENCRYPT_MODE, k);
encryptedCredentials = c.doFinal(byteCredentials);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return encryptedCredentials;
}
public static byte[] getBytesFromObject(Object credentials) throws IOException{
//Hmmm.... now I'm thinking I should make generic type for both: Token and ITU_Credentials object, that would have this getBytes and getObject methods.
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
byte[] newBytes = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(credentials);
newBytes = bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
out.close();
bos.close();
}
return newBytes;
}
private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{
//Converting key to SHA-1 and trimming to mach maximum lenght of key
byte[] bkey = key.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
bkey = sha.digest(bkey);
bkey = Arrays.copyOf(bkey, 16);
return bkey;
}
And here is my Decryptor class:
public class Decryptor {
public static byte[] decryptData(byte[] encryptedCredentials, String key){
Cipher c;
SecretKeySpec k;
byte[] byteSharedKey = null;
byte[] byteObject = null;
try {
byteSharedKey = getByteKey(key);
c = Cipher.getInstance("AES");
k = new SecretKeySpec(byteSharedKey, "AES");
c.init(Cipher.DECRYPT_MODE, k);
byteObject = c.doFinal(encryptedCredentials);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
e.printStackTrace();
} catch (BadPaddingException e) {
e.printStackTrace();
}
return byteObject;
}
public static Object getObjectFromBytes(byte[] credentials) throws IOException, ClassNotFoundException{
ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
ObjectInput in = null;
ITU_Credentials credentialsObj = null;
try {
in = new ObjectInputStream(bis);
credentialsObj = (ITU_Credentials)in.readObject();
} finally {
bis.close();
in.close();
}
return credentialsObj;
}
private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{
//Converting key to SHA-1 and trimming to mach maximum lenght of key
byte[] bkey = key.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
bkey = sha.digest(bkey);
bkey = Arrays.copyOf(bkey, 16);
return bkey;
}
public static void main(String[] args) {
new Encryptor();
}
}
EDIT:
As advised, I replaced all e.printStackTrace(); with throw new RuntimeException(e); in the Decriptor class to properly throw exceptions:
public class Decryptor {
public static byte[] decryptData(byte[] encryptedCredentials, String key){
Cipher c;
SecretKeySpec k;
byte[] byteSharedKey = null;
byte[] byteObject = null;
try {
byteSharedKey = getByteKey(key);
c = Cipher.getInstance("AES");
k = new SecretKeySpec(byteSharedKey, "AES");
c.init(Cipher.DECRYPT_MODE, k);
byteObject = c.doFinal(encryptedCredentials);
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new RuntimeException(e);
} catch (InvalidKeyException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(e);
} catch (BadPaddingException e) {
throw new RuntimeException(e);
}
return byteObject;
}
public static Object getObjectFromBytes(byte[] credentials) throws IOException, ClassNotFoundException{
ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
ObjectInput in = null;
ITU_Credentials credentialsObj = null;
try {
in = new ObjectInputStream(bis);
credentialsObj = (ITU_Credentials)in.readObject();
} finally {
bis.close();
in.close();
}
return credentialsObj;
}
private static byte[] getByteKey(String key) throws UnsupportedEncodingException, NoSuchAlgorithmException{
//Converting key to SHA-1 and trimming to mach maximum lenght of key
byte[] bkey = key.getBytes("UTF-8");
MessageDigest sha = MessageDigest.getInstance("SHA-1");
bkey = sha.digest(bkey);
bkey = Arrays.copyOf(bkey, 16);
return bkey;
}
public static void main(String[] args) {
new Encryptor();
}
}
Now the exception looks as follows:
Exception in thread "main" java.lang.RuntimeException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:51)
at mds.hm5.tokenservice.Main2.main(Main2.java:28)
Caused by: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:749)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:675)
at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:313)
at javax.crypto.Cipher.doFinal(Cipher.java:2087)
at mds.hm5.sharedclasses.Decryptor.decryptData(Decryptor.java:40)
... 1 more
I think the root of your problem is:
byte[] bytes = Encryptor.getBytesFromObject(s);
bytes = Encryptor.encryptData(bytes, "secretkey1");
which goes to:
//etc.//
byte[] encryptedCredentials = null;
byte[] byteSharedKey = null;
try {
byteCredentials = getBytesFromObject(credentials);
//Whoops! credentials is already a byte array.
//etc.//
catch (and eat) exception.....
return encryptedCredentials;
And, since you eat the exception and just return null, as home has advised against in the comments, then it keeps moving until it gets to the decryption step, where it throws an exception you hadn't anticipated (when it fails to decrypt, an IllegalBlockSizeException which is none of the eight types of Exception that you catch there), and gives you something useful.
That's what I think is going on anyway.