package org.witness.informacam.crypto;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
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.Date;
import java.util.Iterator;
import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.jce.provider.BouncyCastleProvider;
import org.spongycastle.openpgp.PGPCompressedData;
import org.spongycastle.openpgp.PGPCompressedDataGenerator;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.spongycastle.openpgp.PGPEncryptedDataGenerator;
import org.spongycastle.openpgp.PGPEncryptedDataList;
import org.spongycastle.openpgp.PGPException;
import org.spongycastle.openpgp.PGPLiteralData;
import org.spongycastle.openpgp.PGPLiteralDataGenerator;
import org.spongycastle.openpgp.PGPObjectFactory;
import org.spongycastle.openpgp.PGPPrivateKey;
import org.spongycastle.openpgp.PGPPublicKeyEncryptedData;
import org.spongycastle.openpgp.PGPSecretKey;
import org.spongycastle.openpgp.PGPUtil;
import org.witness.informacam.models.credentials.ISecretKey;
import org.witness.informacam.utils.Constants.App.Crypto;
import android.util.Base64;
import android.util.Log;
public class EncryptionUtility {
@SuppressWarnings("unused")
private final static String LOG = Crypto.LOG;
@SuppressWarnings("deprecation")
public final static byte[] encrypt(byte[] data, byte[] publicKey) {
try {
BouncyCastleProvider bc = new BouncyCastleProvider();
int bufferSize = 1 << 16;
Security.addProvider(bc);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
OutputStream aos = new ArmoredOutputStream(baos);
PGPEncryptedDataGenerator edg = new PGPEncryptedDataGenerator(PGPEncryptedData.AES_256, true, new SecureRandom(), bc);
edg.addMethod(KeyUtility.extractPublicKeyFromBytes(publicKey));
OutputStream encOs = edg.open(aos, new byte[bufferSize]);
PGPCompressedDataGenerator cdg = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
OutputStream compOs = cdg.open(encOs);
PGPLiteralDataGenerator ldg = new PGPLiteralDataGenerator();
OutputStream litOs = ldg.open(compOs, PGPLiteralData.BINARY, PGPLiteralData.CONSOLE, new Date(System.currentTimeMillis()), new byte[bufferSize]);
InputStream is = new ByteArrayInputStream(data);
byte[] buf = new byte[bufferSize];
int len;
while((len = is.read(buf)) > 0)
litOs.write(buf, 0, len);
litOs.flush();
litOs.close();
ldg.close();
compOs.flush();
compOs.close();
cdg.close();
encOs.flush();
encOs.close();
edg.close();
baos.flush();
aos.close();
baos.close();
is.close();
return baos.toByteArray();
} catch (NoSuchProviderException e) {
e.printStackTrace();
return null;
} catch (PGPException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@SuppressWarnings("deprecation")
public final static void encrypt(InputStream is, OutputStream os, byte[] publicKey) throws NoSuchProviderException, PGPException, IOException {
BouncyCastleProvider bc = new BouncyCastleProvider();
int bufferSize = 1 << 16;
Security.addProvider(bc);
OutputStream aos = new ArmoredOutputStream(os);
PGPEncryptedDataGenerator edg = new PGPEncryptedDataGenerator(PGPEncryptedData.AES_256, true, new SecureRandom(), bc);
edg.addMethod(KeyUtility.extractPublicKeyFromBytes(publicKey));
OutputStream encOs = edg.open(aos, new byte[bufferSize]);
PGPCompressedDataGenerator cdg = new PGPCompressedDataGenerator(PGPCompressedData.ZIP);
OutputStream compOs = cdg.open(encOs);
PGPLiteralDataGenerator ldg = new PGPLiteralDataGenerator();
OutputStream litOs = ldg.open(compOs, PGPLiteralData.BINARY, PGPLiteralData.CONSOLE, new Date(System.currentTimeMillis()), new byte[bufferSize]);
byte[] buf = new byte[bufferSize];
int len;
while((len = is.read(buf)) > 0)
litOs.write(buf, 0, len);
litOs.flush();
litOs.close();
ldg.close();
compOs.flush();
compOs.close();
cdg.close();
encOs.flush();
encOs.close();
edg.close();
aos.close();
is.close();
}
public static info.guardianproject.iocipher.File decrypt(info.guardianproject.iocipher.File file, info.guardianproject.iocipher.File newFile, ISecretKey secretKey) {
try {
info.guardianproject.iocipher.FileInputStream fis = new info.guardianproject.iocipher.FileInputStream(file);
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
fis.close();
info.guardianproject.iocipher.FileOutputStream fos = new info.guardianproject.iocipher.FileOutputStream(newFile);
fos.write(decrypt(bytes, secretKey));
fos.flush();
fos.close();
return newFile;
} catch (FileNotFoundException e) {
Log.e(Crypto.LOG, e.toString());
e.printStackTrace();
} catch (IOException e) {
Log.e(Crypto.LOG, e.toString());
e.printStackTrace();
} catch (NullPointerException e) {
Log.e(Crypto.LOG, e.toString());
e.printStackTrace();
}
return null;
}
public static byte[] decrypt(byte[] bytes, ISecretKey secretKey) {
return decrypt(bytes, false, secretKey);
}
@SuppressWarnings({ "deprecation", "rawtypes" })
public static byte[] decrypt(byte[] bytes, boolean isBase64Encoded, ISecretKey secretKey) {
if(isBase64Encoded) {
bytes = Base64.decode(bytes, Base64.DEFAULT);
}
byte[] decryptedBytes = null;
PGPSecretKey sk = null;
PGPPrivateKey pk = null;
try {
BouncyCastleProvider bc = new BouncyCastleProvider();
sk = KeyUtility.extractSecretKey(secretKey.secretKey.getBytes());
pk = sk.extractPrivateKey(secretKey.secretAuthToken.toCharArray(), bc);
if(sk == null || pk == null) {
Log.e(Crypto.LOG, "secret key or private key is null");
return null;
}
InputStream is = PGPUtil.getDecoderStream(new ByteArrayInputStream(bytes));
PGPObjectFactory pgpF = new PGPObjectFactory(is);
PGPEncryptedDataList edl;
Object o = pgpF.nextObject();
if(o instanceof PGPEncryptedDataList)
edl = (PGPEncryptedDataList) o;
else
edl = (PGPEncryptedDataList) pgpF.nextObject();
Iterator it = edl.getEncryptedDataObjects();
PGPPublicKeyEncryptedData ed = null;
ed = (PGPPublicKeyEncryptedData) it.next();
if(ed == null) {
Log.e(Crypto.LOG, "No PGPPublicKeyEncryptedData found.");
return null;
}
InputStream clearStream = ed.getDataStream(pk, bc);
pgpF = new PGPObjectFactory(clearStream);
PGPLiteralData ld = null;
o = pgpF.nextObject();
try {
PGPCompressedData cd = (PGPCompressedData) o;
InputStream compressedStream = new BufferedInputStream(cd.getDataStream());
pgpF = new PGPObjectFactory(compressedStream);
Object message = pgpF.nextObject();
if(message instanceof PGPLiteralData) {
ld = (PGPLiteralData) message;
}
} catch(ClassCastException e) {
ld = (PGPLiteralData) o;
}
if(ld == null)
return null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(baos);
InputStream ldis = ld.getInputStream();
int ch;
while((ch = ldis.read()) >= 0)
bos.write(ch);
bos.flush();
bos.close();
decryptedBytes = baos.toByteArray();
baos.close();
} catch (IOException e) {
Log.e(Crypto.LOG, e.toString());
e.printStackTrace();
} catch (PGPException e) {
Log.e(Crypto.LOG, e.toString());
e.printStackTrace();
}
return decryptedBytes;
}
}