JAVA :- PGP Decrypting using BouncyCastle those encrypted by GPG4win Kleopatra - java

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

Related

Invalid signature with PDFBox and Bouncycastle

I'm trying sign a pdf, and my code signed the pdf but, when I open the document in Adobe I have this response: and I don't know what happens.
Certificate generator
public static BigInteger generateSerial() {
SecureRandom random = new SecureRandom();
return BigInteger.valueOf(Math.abs(random.nextLong()));
}
public static X509Certificate CeriticateGenerator(PublicKey publicKey, PrivateKey privateKey) throws OperatorCreationException, CertificateException, CertIOException {
Date startDate = new Date(System.currentTimeMillis());
Date expiryDate = new Date(System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000);
X500Name issuser=new X500Name("cn=Rubrica");
X500Name subject=new X500Name("cn=Rubrica");
X509v3CertificateBuilder certGen = new JcaX509v3CertificateBuilder(issuser,
generateSerial(),
startDate,
expiryDate,
subject,
publicKey).addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyId(publicKey))
.addExtension(Extension.authorityKeyIdentifier, false, createAuthorityKeyId(publicKey))
.addExtension(Extension.basicConstraints, true, new BasicConstraints(true));
ContentSigner sigGen = new JcaContentSignerBuilder("SHA512withRSA").setProvider("BC").build(privateKey);
return new JcaX509CertificateConverter()
.setProvider(new BouncyCastleProvider()).getCertificate(certGen.build(sigGen));
}
private static SubjectKeyIdentifier createSubjectKeyId(final PublicKey publicKey) throws OperatorCreationException {
final SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
final DigestCalculator digCalc =
new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
return new X509ExtensionUtils(digCalc).createSubjectKeyIdentifier(publicKeyInfo);
}
/**
* Creates the hash value of the authority public key.
*
* #param publicKey of the authority certificate
*
* #return AuthorityKeyIdentifier hash
*
* #throws OperatorCreationException
*/
private static AuthorityKeyIdentifier createAuthorityKeyId(final PublicKey publicKey)
throws OperatorCreationException
{
final SubjectPublicKeyInfo publicKeyInfo = SubjectPublicKeyInfo.getInstance(publicKey.getEncoded());
final DigestCalculator digCalc =
new BcDigestCalculatorProvider().get(new AlgorithmIdentifier(OIWObjectIdentifiers.idSHA1));
return new X509ExtensionUtils(digCalc).createAuthorityKeyIdentifier(publicKeyInfo);
}
this is the interface Signature
public class PDBOXsignerManager implements SignatureInterface{
private PrivateKey privateKey;
private Certificate[] certificateChain;
PDBOXsignerManager(KeyStore keyStore, String password, String appCertificateAlias) {
try {
this.certificateChain = Optional.ofNullable(keyStore.getCertificateChain(appCertificateAlias))
.orElseThrow(() -> (new IOException("Could not find a proper certificate chain")));
this.privateKey = (PrivateKey) keyStore.getKey(appCertificateAlias, password.toCharArray());
Certificate certificate = this.certificateChain[0];
if (certificate instanceof X509Certificate) {
((X509Certificate) certificate).checkValidity();
}
} catch (KeyStoreException | IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnrecoverableKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateExpiredException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (CertificateNotYetValidException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public byte[] sign(InputStream content) throws IOException {
try {
CMSSignedDataGenerator gen = new CMSSignedDataGenerator();
X509Certificate cert = (X509Certificate) this.certificateChain[0];
ContentSigner ECDSASigner = new JcaContentSignerBuilder("SHA512withRSA").build(this.privateKey);
gen.addSignerInfoGenerator(new JcaSignerInfoGeneratorBuilder(new JcaDigestCalculatorProviderBuilder().build()).build(ECDSASigner, cert));
gen.addCertificates(new JcaCertStore(Arrays.asList(this.certificateChain)));
CMSProcessableInputStream msg = new CMSProcessableInputStream(content);
CMSSignedData signedData = gen.generate(msg, false);
return signedData.getEncoded();
} catch (GeneralSecurityException | CMSException | OperatorCreationException e) {
//throw new IOException cause a SignatureInterface, but keep the stacktrace
throw new IOException(e);
}
}
}
this the class signer
public class PDBOXSigner extends PDBOXsignerManager
{
PDBOXSigner(KeyStore keyStore, String password, String appCertificateAlias) {
super(keyStore, password, appCertificateAlias);
}
public void signDetached( PDDocument document, OutputStream output, String name, String reason) {
PDSignature pdSignature = new PDSignature();
pdSignature.setFilter(PDSignature.FILTER_ADOBE_PPKLITE);
pdSignature.setSubFilter(PDSignature.SUBFILTER_ADBE_PKCS7_SHA1);
pdSignature.setName(name);
pdSignature.setReason(reason);
// Se le agrega la fecha de firma necesaria para validar la misma
pdSignature.setSignDate(Calendar.getInstance());
// Registro del diccionario de firmas y y la interfaz de firma
try {
SignatureOptions signatureOptions = new SignatureOptions();
// Size can vary, but should be enough for purpose.
signatureOptions.setPreferredSignatureSize(SignatureOptions.DEFAULT_SIGNATURE_SIZE * 2);
// register signature dictionary and sign interface
document.addSignature(pdSignature, this, signatureOptions);
// write incremental (only for signing purpose)
document.saveIncremental(output);
output.flush();
output.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
I created the certificates and key pair with java and bouncycastle, i don't now if is the problem or what am I doing wrong?
The mistake was to use SUBFILTER_ADBE_PKCS7_SHA1 instead of the SUBFILTER_ADBE_PKCS7_DETACHED that is used in the official example. SUBFILTER_ADBE_PKCS7_SHA1 shouldn't be used for signing, it is deprecated in PDF 2.0.

Android RSA decryption using private key, non-sense result

I am doing RSA decryption in my Android project, and somehow the result makes non-sense. I am showing my code here:
private static final int MAX_DECRYPT_BLOCK = 256;
private static RSAPrivateKey loadPrivateKey(InputStream in) throws Exception {
RSAPrivateKey priKey;
try {
BufferedReader br = new BufferedReader(new InputStreamReader(in));
String readLine = null;
StringBuilder sb = new StringBuilder();
while ((readLine = br.readLine()) != null) {
if (readLine.charAt(0) == '-') {
continue;
} else {
sb.append(readLine);
sb.append('\r');
}
}
byte[] priKeyData = Base64.decode(new String(sb), Base64.NO_WRAP);
PKCS8EncodedKeySpec keySpec= new PKCS8EncodedKeySpec(priKeyData);
KeyFactory keyFactory= KeyFactory.getInstance("RSA",new BouncyCastleProvider());
priKey= (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (IOException e) {
throw new Exception("error reading the key");
} catch (NullPointerException e) {
throw new Exception("inputstream is null");
}
return priKey;
}
/**
* decrypt with a private key
*
* #param privateKey
* #param cipherData
* #return
* #throws Exception
*/
private static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
if (privateKey == null) {
throw new Exception("key is null");
}
Cipher cipher = null;
try {
cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
int inputLen = cipherData.length;
ByteArrayOutputStream out = new ByteArrayOutputStream();
int offSet = 0;
byte[] cache;
int i = 0;
while (inputLen - offSet > 0) {
if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
cache = cipher.doFinal(cipherData, offSet, MAX_DECRYPT_BLOCK);
} else {
cache = cipher.doFinal(cipherData, offSet, inputLen - offSet);
}
out.write(cache, 0, cache.length);
i++;
offSet = i * MAX_DECRYPT_BLOCK;
}
byte[] decryptedData = out.toByteArray();
out.close();
return decryptedData;
} catch (NoSuchAlgorithmException e) {
throw new Exception("no such algorithm");
} catch (NoSuchPaddingException e) {
e.printStackTrace();
return null;
} catch (InvalidKeyException e) {
throw new Exception("InvalidKeyException");
} catch (IllegalBlockSizeException e) {
throw new Exception("IllegalBlockSizeException");
} catch (BadPaddingException e) {
throw new Exception("BadPaddingException");
}
}
public static String RSADecrypt(Context context, String KeyFileNameInAssetFolder, byte[] content) {
try {
InputStream inputStream = context.getResources().getAssets().open(KeyFileNameInAssetFolder);
RSAPrivateKey privateKey = loadPrivateKey(inputStream);
byte[] b = decrypt(privateKey, content);
return new String(b,"utf-8");
} catch (Exception e) {
e.printStackTrace();
}
return "error";
}
and I am calling with this statement:
String result = RSAUtils.RSADecrypt(getApplicationContext(), Constant.PRIVATE_KEY_PKCS8_FILE_NAME,Base64.decode(qrcode_result,Base64.NO_WRAP));
And this is the private key:
> -----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCsQTbkXviKG1od
wVp0t15JB4OkdDUo8O36/yzLoJmsmPf3yFzAJ3YzEAaWAKKpUx92c9yfW4vW849F
pno/GUJLwPkIG5ss1YR55P5UI76kpLM74ZXume9+WfEuQ3B/HHkcnmCVl4CV/Xqq
4X4d3Rc7zGTbGSHdVui1QJ5ubQoqHjSGaO9j2SvMsqDSU20S1DjrL/8sb0e7B63a
fJVzOZFi7E62zqYzfBOEupY+24Ac8i7s8tyX3Bd4OJ1zdQ+si5yeIkaRiD8ZeUbJ
3yS2MlUohvuwmJy7uxpP8mYXmaXM1ZtMFLaLRUc4leA7KDRlDXHJLSYAkFxCyw8J
RTK2QOcTAgMBAAECggEARRrUnsHLC/z1JkLPu0tlM/8jvPIx8X7Wun9sxTRk8m1b
7bggHaa3ML0ZJ0yR9UQ3txm8ROJBM7b6n4KuQGotwp5kSfBpTI9MWmqX7cF5ViwN
C9TwhYyUHCiRLXI4y4XswKJ5NQpWt9W9RJi6M9ji3Uaen5dxko6vRSfrZ3mvPj2/
blW5HV8j3RIzJ3942CzQw2IX/hQWhityFxTwGY3f3Rh05jpI+SowJlOTIheOHqlR
2VFTLTYIvmoZJduFzxlM4t5W3VzGZl/KmC1apNh2N3xPcmimq/YsrDqN5GgkNhuh
/WTTB7pa3qsQlFPKnwylLc2LviQafiR+yunolImCwQKBgQDS9TIth96x+McD2Gu7
1QQlalhDK1+s/O9rjQV4la9FykEFdJB7+Q9xyq9vIqqSVIFj8rI1wqziHp3czUkY
Ijqcgp0DB1Stbwp3DPh3Rq4zVHHnKplzhMwAaDBOVaHmEGaiyB/LwspCcDoON+i+
70Bzdc6EW/KqNpGlP3OPJT2pSwKBgQDRCIlyklOnKQnzbCaMwFkBZBJlHHqgIl1Z
S7jdFaTX7uUkbXF3WVtJlY1+r6h0rK075hX/61VlhfoFjBIR/7ZDaBkrH3Nd6cdU
PJIOgnQEYobRAF4ugWSPTsf0A6bjd7tsVZ7+1ediKwg1QY9Pk2hj/jRb0FD2nKZ+
yWI3RPekWQKBgBM1DfeFSmpr2zrnZo+4imMZtqWO+mwWr3ncYiYjgszY6Gilv036
VESpDqYQwvUFyq4d98nbSsBfx0HGUyRmYW3EmqUe8r/Dv3EtdiXuAohb5O8GOuiA
q85RrixDsbTvw1iI3hRATQgVjcOjpYZU5Epe7ImykXqb81DXYR8kZePXAoGBAJWk
CuFeJ0yPcHQ2hBJW0GDShuijTpW8hB8cuiZrDCsY9ijxwDy0V0mCKlz62xlLVGiA
+lbO3b9j/exirbz81jnDF+FrDme4p92Bzv1cHjnVXrXYEZQxRQ/iUfo5cwt790xC
ryO3dYEtVR7q4/EPkbejj0/6/TrOQdKZ0BnI4Y9hAoGBALlFBlvCRspXYBOXf0XM
5V0Q4t1vAxgcfNaKi4h612UZDF2GluYIwtuF+uJlxYvhRxq1gzmgP5+Z9gblMb6d
8ysWfWPl2RWGYNw0nwOYhWI1/cWRNpfH7W+OY2kHmB3G1bHnf5PxUb+1JL2PvfXS
fZ8JY1/xKqYSoSORJYQh2Z7D
-----END PRIVATE KEY-----
and this is the string I tried to decrypt:
JRhdX3DLGbMVcxN6jV3697yUkfZUBfz/ee6P8pGlgHFnOo5OWgXH0fc10Ps4li3UKkyVqo1+iz10/zzhjVTbSKC5Fai6dLnQgrFVz6lOqOeR83+x4ezyF75kORdgAyEp5MiW0LHsK13ryYEqZ1GHiZdJ6E54nbLZsZGKJJkRZ2OVQW9hovqBQXAP3M8dGk1liruiY+xAHfKkeS73m+IPYPTNGQT+y5IDACoq8dLUvV4nw76p2ZUfyYFgoYOir9KBN2SbfcndR71DZUPWdRnZoDLNFCfvMjC2Ui27j3CxcQLzJSt4K4K+kmU6n5t8Xb6YyGb2j+5pduXcnZMgc5cjsm6NBIXUv+DQzXeRo61vHrXKWeamJ+Whl0RnA9HjIl6medxfE64xHgF+aD6lqbQcwWwHWm/s3f5XkS0xP21bYuOt8mgmHC90qhJNRGKmTGgyxxls/18aV4eZEIRUg82wCIXavvQGLA3hk5UWl4YkrpaGYh+SX1t3yfi+wQ8f30lQBrKl4A0iKk4WHKNCka6nd3sc8bDwD42cvQiFSPCp7m4DRtXy1CRzNmRG7FmSK8SgkQOWSWE+6KRKat88j0Nw+Rg6U1YaMBofJOLKfIswLHgW44Bpf2c0eynJEZdLi94oOh7lkTHcaqwBiO1MWg9eiYT/j7qXCPjoi9q3PzPhxoA=
and the decryption result is like this:
result image

Using HMAC with SHA-1

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.

Pkcs7 padding in java

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();
}

Double layer encryption: "Input length must be multiple of 16 when decrypting with padded cipher..."

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.

Categories