|
|
@@ -40,7 +40,6 @@ import java.io.ByteArrayInputStream;
|
|
|
import java.io.ByteArrayOutputStream;
|
|
|
import java.io.File;
|
|
|
import java.io.FileInputStream;
|
|
|
-import java.io.FileNotFoundException;
|
|
|
import java.io.IOException;
|
|
|
import java.io.InputStream;
|
|
|
import java.io.OutputStream;
|
|
|
@@ -57,6 +56,24 @@ import info.knacki.pass.settings.SettingsManager;
|
|
|
public class GPGUtil {
|
|
|
private final static Logger log = Logger.getLogger(GPGUtil.class.getName());
|
|
|
|
|
|
+ public static class MalformedKeyException extends IOException {
|
|
|
+ public final Throwable fCause;
|
|
|
+
|
|
|
+ public MalformedKeyException(Throwable e) {
|
|
|
+ fCause = e;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public synchronized Throwable getCause() {
|
|
|
+ return fCause;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public String getMessage() {
|
|
|
+ return fCause.getMessage();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
private static class PGPPrivateKeyAndPass {
|
|
|
public final PGPPrivateKey fPrivateKey;
|
|
|
public final String fPass;
|
|
|
@@ -67,29 +84,37 @@ public class GPGUtil {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- private static boolean TryPassword(PGPSecretKey pgpSecKey, String pass, GitInterface.OnResponseListener<PGPPrivateKeyAndPass> onResponse) {
|
|
|
+ private static PGPPrivateKeyAndPass TryPassword(PGPSecretKey pgpSecKey, String pass) {
|
|
|
try {
|
|
|
PGPPrivateKey pgpPrivKey = pgpSecKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder().setProvider("BC").build()).setProvider("BC").build(pass.toCharArray()));
|
|
|
PGPPrivateKeyAndPass res = new PGPPrivateKeyAndPass(pgpPrivKey, pass);
|
|
|
- onResponse.onResponse(res);
|
|
|
+ return res;
|
|
|
} catch (PGPException e) {
|
|
|
// Wrong password
|
|
|
log.log(Level.INFO, e.getMessage() + " (wrong password ?)", e);
|
|
|
- return false;
|
|
|
+ return null;
|
|
|
}
|
|
|
- return true;
|
|
|
}
|
|
|
|
|
|
private static void FindPassword(final FileInterfaceFactory.PasswordGetter passwordGetter, final PGPSecretKey pgpSecKey, final GitInterface.OnResponseListener<PGPPrivateKeyAndPass> resp) {
|
|
|
- if (!TryPassword(pgpSecKey, "", resp)) {
|
|
|
+ PGPPrivateKeyAndPass priv = TryPassword(pgpSecKey, "");
|
|
|
+
|
|
|
+ if (priv != null) {
|
|
|
+ resp.onResponse(priv);
|
|
|
+ } else {
|
|
|
GitInterface.OnResponseListener<String> onResp = new GitInterface.OnResponseListener<String>() {
|
|
|
@Override
|
|
|
public void onResponse(String result) {
|
|
|
if (result == null) {
|
|
|
resp.onError("Invalid password", null);
|
|
|
- } else if (!TryPassword(pgpSecKey, result, resp)) {
|
|
|
- passwordGetter.WrongPassword();
|
|
|
- passwordGetter.GetPassword(this);
|
|
|
+ } else {
|
|
|
+ PGPPrivateKeyAndPass priv = TryPassword(pgpSecKey, result);
|
|
|
+ if (priv != null) {
|
|
|
+ resp.onResponse(priv);
|
|
|
+ } else {
|
|
|
+ passwordGetter.WrongPassword();
|
|
|
+ passwordGetter.GetPassword(this);
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -139,13 +164,18 @@ public class GPGUtil {
|
|
|
return null;
|
|
|
}
|
|
|
|
|
|
- private static InputStream getKeyInputStream(Context ctx) throws FileNotFoundException {
|
|
|
+ private static InputStream getKeyInputStream(Context ctx) {
|
|
|
return SettingsManager.GetGPGKeyContent(ctx);
|
|
|
}
|
|
|
|
|
|
- private static PGPSecretKey findSecretKey(InputStream in) throws IOException, PGPException {
|
|
|
+ private static PGPSecretKey findSecretKey(InputStream in) throws IOException {
|
|
|
in = PGPUtil.getDecoderStream(in);
|
|
|
- PGPSecretKeyRingCollection pgpSec = new PGPSecretKeyRingCollection(in, new JcaKeyFingerprintCalculator());
|
|
|
+ PGPSecretKeyRingCollection pgpSec;
|
|
|
+ try {
|
|
|
+ pgpSec = new PGPSecretKeyRingCollection(in, new JcaKeyFingerprintCalculator());
|
|
|
+ } catch (PGPException e) {
|
|
|
+ throw new MalformedKeyException(e);
|
|
|
+ }
|
|
|
Iterator rIt = pgpSec.getKeyRings();
|
|
|
|
|
|
while (rIt.hasNext()) {
|
|
|
@@ -182,7 +212,7 @@ public class GPGUtil {
|
|
|
resp.onResponse(output);
|
|
|
}
|
|
|
|
|
|
- public static void DecryptFile(final Context ctx, final FileInterfaceFactory.PasswordGetter passwordGetter, final File file, final GitInterface.OnResponseListener<byte[]> resp) throws IOException, PGPException {
|
|
|
+ public static void DecryptFile(final Context ctx, final FileInterfaceFactory.PasswordGetter passwordGetter, final File file, final GitInterface.OnResponseListener<byte[]> resp) throws IOException {
|
|
|
PGPObjectFactory pgpF = new PGPObjectFactory(PGPUtil.getDecoderStream(new FileInputStream(file)), new JcaKeyFingerprintCalculator());
|
|
|
Object o = pgpF.nextObject();
|
|
|
final Iterator<?> it = ((o instanceof PGPEncryptedDataList) ? (PGPEncryptedDataList) o : (PGPEncryptedDataList) pgpF.nextObject()).getEncryptedDataObjects();
|
|
|
@@ -246,7 +276,7 @@ public class GPGUtil {
|
|
|
} catch (IOException | PGPException e) {
|
|
|
resp.onError(e.getMessage(), e);
|
|
|
}
|
|
|
- } catch (IOException | PGPException e) {
|
|
|
+ } catch (IOException e) {
|
|
|
resp.onError(e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
@@ -264,45 +294,46 @@ public class GPGUtil {
|
|
|
.generateSecretKeyRing();
|
|
|
}
|
|
|
|
|
|
- public static void ChangePassword(final Context ctx, final FileInterfaceFactory.ChangePasswordGetter passwordGetter, final Runnable onDone) throws IOException {
|
|
|
- try {
|
|
|
- final PGPSecretKey secretKey = findSecretKey(getKeyInputStream(ctx));
|
|
|
- FindPassword(
|
|
|
- passwordGetter.SetStep(FileInterfaceFactory.ChangePasswordGetter.eStep.eOldPassword),
|
|
|
- secretKey,
|
|
|
- new GitInterface.OnResponseListener<PGPPrivateKeyAndPass>() {
|
|
|
- @Override
|
|
|
- public void onResponse(final PGPPrivateKeyAndPass sKey) {
|
|
|
- passwordGetter.SetStep(FileInterfaceFactory.ChangePasswordGetter.eStep.eNewPassword).GetPassword(new GitInterface.OnResponseListener<String>() {
|
|
|
- @Override
|
|
|
- public void onResponse(String result) {
|
|
|
- if (result != null) {
|
|
|
- try {
|
|
|
- ArrayList<PGPSecretKeyRing> keyringCollection = new ArrayList<>();
|
|
|
- keyringCollection.add(DoChangePassword(secretKey, sKey, result));
|
|
|
- ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
|
- new PGPSecretKeyRingCollection(keyringCollection).encode(stream);
|
|
|
- SettingsManager.SetGPGKeyContent(ctx, SettingsManager.GPG_GENERATED, new ByteArrayInputStream(stream.toByteArray()));
|
|
|
- onDone.run();
|
|
|
- } catch (PGPException | IOException e) {
|
|
|
- onError(e.getMessage(), e);
|
|
|
- }
|
|
|
+ public static void ChangePassword(final Context ctx, final FileInterfaceFactory.ChangePasswordGetter passwordGetter, final GitInterface.OnResponseListener<Void> onDone) throws IOException {
|
|
|
+ final PGPSecretKey secretKey = findSecretKey(getKeyInputStream(ctx));
|
|
|
+ FindPassword(
|
|
|
+ passwordGetter.SetStep(FileInterfaceFactory.ChangePasswordGetter.eStep.eOldPassword),
|
|
|
+ secretKey,
|
|
|
+ new GitInterface.OnResponseListener<PGPPrivateKeyAndPass>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(final PGPPrivateKeyAndPass sKey) {
|
|
|
+ passwordGetter.SetStep(FileInterfaceFactory.ChangePasswordGetter.eStep.eNewPassword).GetPassword(new GitInterface.OnResponseListener<String>() {
|
|
|
+ @Override
|
|
|
+ public void onResponse(String result) {
|
|
|
+ if (result != null) {
|
|
|
+ try {
|
|
|
+ ArrayList<PGPSecretKeyRing> keyringCollection = new ArrayList<>();
|
|
|
+ keyringCollection.add(DoChangePassword(secretKey, sKey, result));
|
|
|
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
|
|
+ new PGPSecretKeyRingCollection(keyringCollection).encode(stream);
|
|
|
+ SettingsManager.SetGPGKeyContent(ctx, SettingsManager.GPG_GENERATED, new ByteArrayInputStream(stream.toByteArray()));
|
|
|
+ onDone.onResponse(null);
|
|
|
+ } catch (PGPException | IOException e) {
|
|
|
+ onError(e.getMessage(), e);
|
|
|
}
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public void onError(String msg, Throwable e) {
|
|
|
- onDone.run();
|
|
|
- }
|
|
|
- });
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public void onError(String msg, Throwable e) {
|
|
|
+ onDone.onError(msg, e);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public void onError(String msg, Throwable e) {
|
|
|
- }
|
|
|
- });
|
|
|
- } catch (PGPException e) {
|
|
|
+ @Override
|
|
|
+ public void onError(String msg, Throwable e) {
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ public static boolean CheckIsPasswordProtected(Context ctx) throws IOException {
|
|
|
+ final PGPSecretKey secretKey = findSecretKey(getKeyInputStream(ctx));
|
|
|
+ return TryPassword(secretKey, "") == null;
|
|
|
}
|
|
|
}
|