|
|
@@ -1,161 +0,0 @@
|
|
|
-package info.knacki.pass.io.pgp;
|
|
|
-
|
|
|
-import android.content.Context;
|
|
|
-import android.support.annotation.NonNull;
|
|
|
-
|
|
|
-import org.bouncycastle.openpgp.PGPException;
|
|
|
-import org.bouncycastle.openpgp.PGPSecretKey;
|
|
|
-import org.bouncycastle.openpgp.PGPSecretKeyRing;
|
|
|
-import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
|
|
|
-import org.bouncycastle.openpgp.PGPUtil;
|
|
|
-import org.bouncycastle.openpgp.operator.jcajce.JcaKeyFingerprintCalculator;
|
|
|
-
|
|
|
-import java.io.ByteArrayInputStream;
|
|
|
-import java.io.File;
|
|
|
-import java.io.FileInputStream;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
-import java.io.FileOutputStream;
|
|
|
-import java.io.IOException;
|
|
|
-import java.io.InputStream;
|
|
|
-import java.io.OutputStream;
|
|
|
-import java.security.KeyStore;
|
|
|
-import java.security.KeyStoreException;
|
|
|
-import java.security.NoSuchAlgorithmException;
|
|
|
-import java.security.NoSuchProviderException;
|
|
|
-import java.security.UnrecoverableKeyException;
|
|
|
-import java.security.cert.CertificateException;
|
|
|
-import java.util.Iterator;
|
|
|
-import java.util.NoSuchElementException;
|
|
|
-import java.util.logging.Level;
|
|
|
-import java.util.logging.Logger;
|
|
|
-
|
|
|
-import javax.crypto.SecretKey;
|
|
|
-import javax.crypto.spec.SecretKeySpec;
|
|
|
-
|
|
|
-import info.knacki.pass.io.FileUtils;
|
|
|
-import info.knacki.pass.io.PathUtils;
|
|
|
-
|
|
|
-public class GPGStorage {
|
|
|
- private static final Logger log = Logger.getLogger(GPGStorage.class.getName());
|
|
|
- private GPGStorage(){}
|
|
|
-
|
|
|
- private final static String KEY_NAME = GPGStorage.class.getName()+"_PGP_PRIVATE";
|
|
|
- private final static String KEY_PASS = GPGStorage.class.getName()+"___PASSWORD";
|
|
|
-
|
|
|
- static SecretKey FindSecretKey(@NonNull byte[] in) throws IOException {
|
|
|
- final PGPSecretKeyRingCollection pgpSec;
|
|
|
-
|
|
|
- try {
|
|
|
- pgpSec = new PGPSecretKeyRingCollection(in, new JcaKeyFingerprintCalculator());
|
|
|
- } catch (PGPException e) {
|
|
|
- throw new GPGUtil.MalformedKeyException(e);
|
|
|
- }
|
|
|
- Iterator<PGPSecretKeyRing> rIt = pgpSec.getKeyRings();
|
|
|
- if (rIt.hasNext()) {
|
|
|
- PGPSecretKey bcSecKey = rIt.next().getSecretKey();
|
|
|
- return new SecretKeySpec(bcSecKey.getEncoded(), "AES");
|
|
|
- }
|
|
|
- throw new NoSuchElementException("GPG key not found");
|
|
|
- }
|
|
|
-
|
|
|
- private static KeyStore GetKeystore(Context ctx, boolean read) {
|
|
|
- KeyStore ks;
|
|
|
-
|
|
|
- try {
|
|
|
- ks = KeyStore.getInstance("UBER", "BC");
|
|
|
- if (read) {
|
|
|
- File gpgKeyFile = new File(PathUtils.GetGPGKeyFile(ctx));
|
|
|
- if (!gpgKeyFile.exists())
|
|
|
- throw new FileNotFoundException(gpgKeyFile.getName());
|
|
|
- ks.load(new FileInputStream(gpgKeyFile), KEY_PASS.toCharArray());
|
|
|
- } else {
|
|
|
- ks.load(null, null);
|
|
|
- }
|
|
|
- } catch (KeyStoreException | NoSuchProviderException | IOException | CertificateException | NoSuchAlgorithmException e) {
|
|
|
- log.log(Level.SEVERE, "Cannot retreive KeyStore", e);
|
|
|
- ks = null;
|
|
|
- }
|
|
|
- return ks;
|
|
|
- }
|
|
|
-
|
|
|
- private static void SaveKeystore(Context ctx, KeyStore ks) {
|
|
|
- try {
|
|
|
- File f = new File(PathUtils.GetGPGKeyFile(ctx));
|
|
|
- if (!f.exists() && !f.createNewFile())
|
|
|
- throw new FileNotFoundException(f.getName());
|
|
|
- ks.store(new FileOutputStream(f), KEY_PASS.toCharArray());
|
|
|
- }
|
|
|
- catch (IOException | CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
|
|
|
- log.log(Level.SEVERE, "Cannot save keystore", e);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static boolean HasGPGKey(Context ctx) {
|
|
|
- try {
|
|
|
- KeyStore ks = GetKeystore(ctx, true);
|
|
|
- return ks != null && ks.containsAlias(KEY_NAME);
|
|
|
- } catch (KeyStoreException e) {
|
|
|
- log.log(Level.SEVERE, "KeyStore Exception: " +e.getMessage(), e);
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static boolean SetGPGKeyContent(Context ctx, InputStream content) {
|
|
|
- KeyStore ks = GetKeystore(ctx, false);
|
|
|
- if (ks == null)
|
|
|
- return false;
|
|
|
- try {
|
|
|
- SecretKey secret = FindSecretKey(FileUtils.ReadAllStream(content));
|
|
|
- KeyStore.Entry e = new KeyStore.SecretKeyEntry(secret);
|
|
|
- ks.setEntry(KEY_NAME, e, new KeyStore.PasswordProtection(null));
|
|
|
- SaveKeystore(ctx, ks);
|
|
|
- } catch (KeyStoreException | IOException e) {
|
|
|
- log.log(Level.SEVERE, "Cannot set GPG key content", e);
|
|
|
- return false;
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- private static @NonNull InputStream GetGPGKeyContent(Context ctx) throws FileNotFoundException {
|
|
|
- if (!HasGPGKey(ctx))
|
|
|
- throw new FileNotFoundException("GPG key");
|
|
|
- KeyStore ks = GetKeystore(ctx, true);
|
|
|
- if (ks == null)
|
|
|
- throw new FileNotFoundException("GPG key store");
|
|
|
- try {
|
|
|
- return new ByteArrayInputStream(ks.getKey(KEY_NAME, null).getEncoded());
|
|
|
- } catch (KeyStoreException | NoSuchAlgorithmException | UnrecoverableKeyException e) {
|
|
|
- log.log(Level.SEVERE, "KeyStore Exception: " +e.getMessage(), e);
|
|
|
- throw new FileNotFoundException("GPG key store");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public static void ExportGPGKeyContent(Context ctx, OutputStream out) throws IOException {
|
|
|
- FileUtils.pipe(GetGPGKeyContent(ctx), out);
|
|
|
- }
|
|
|
-
|
|
|
- public static @NonNull PGPSecretKeyRing GetGPGKeyRing(Context ctx) throws IOException {
|
|
|
- final PGPSecretKeyRingCollection pgpSec;
|
|
|
-
|
|
|
- try {
|
|
|
- pgpSec = new PGPSecretKeyRingCollection(PGPUtil.getDecoderStream(GetGPGKeyContent(ctx)), new JcaKeyFingerprintCalculator());
|
|
|
- } catch (PGPException e) {
|
|
|
- throw new GPGUtil.MalformedKeyException(e);
|
|
|
- }
|
|
|
- Iterator<PGPSecretKeyRing> rIt = pgpSec.getKeyRings();
|
|
|
- if (rIt.hasNext())
|
|
|
- return rIt.next();
|
|
|
- throw new NoSuchElementException("GPG key not found");
|
|
|
- }
|
|
|
-
|
|
|
- public static @NonNull PGPSecretKey GetGPGSecretKey(Context ctx) throws IOException {
|
|
|
- return GetGPGKeyRing(ctx).getSecretKey();
|
|
|
- }
|
|
|
-
|
|
|
- public static void RemoveGpgKey(Context ctx) {
|
|
|
- File f = new File(PathUtils.GetGPGKeyFile(ctx));
|
|
|
- if (f.exists() && !f.delete()) {
|
|
|
- log.severe("Cannot remove GPG file");
|
|
|
- }
|
|
|
- }
|
|
|
-}
|