aboutsummaryrefslogtreecommitdiffstats
path: root/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-08-01 11:09:25 +0200
committerDominik Schürmann <dominik@dominikschuermann.de>2014-08-01 11:09:25 +0200
commite10cbc54c606563b2d06f083bca17119ca585127 (patch)
tree23c71e67b1c4a381997bdb75de476f05d7dcec5f /OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
parentbef3e621118d0e4d8fadedf0c9d67b6a9ff41883 (diff)
parentacbf2a18617eea73924dd109e09189420d9876fe (diff)
downloadopen-keychain-e10cbc54c606563b2d06f083bca17119ca585127.tar.gz
open-keychain-e10cbc54c606563b2d06f083bca17119ca585127.tar.bz2
open-keychain-e10cbc54c606563b2d06f083bca17119ca585127.zip
Merge branch 'master' into yubikey
Conflicts: .gitmodules OpenKeychain/src/main/java/org/sufficientlysecure/keychain/helper/Preferences.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/UncachedKeyRing.java
Diffstat (limited to 'OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java')
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java152
1 files changed, 152 insertions, 0 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
new file mode 100644
index 000000000..7d3e26000
--- /dev/null
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKeyRing.java
@@ -0,0 +1,152 @@
+package org.sufficientlysecure.keychain.pgp;
+
+import org.spongycastle.bcpg.S2K;
+import org.spongycastle.openpgp.PGPException;
+import org.spongycastle.openpgp.PGPKeyRing;
+import org.spongycastle.openpgp.PGPObjectFactory;
+import org.spongycastle.openpgp.PGPPrivateKey;
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.spongycastle.openpgp.PGPSecretKey;
+import org.spongycastle.openpgp.PGPSecretKeyRing;
+import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
+import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
+import org.sufficientlysecure.keychain.util.IterableIterator;
+import org.sufficientlysecure.keychain.util.Log;
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+
+public class CanonicalizedSecretKeyRing extends CanonicalizedKeyRing {
+
+ private PGPSecretKeyRing mRing;
+
+ CanonicalizedSecretKeyRing(PGPSecretKeyRing ring, int verified) {
+ super(verified);
+ mRing = ring;
+ }
+
+ public CanonicalizedSecretKeyRing(byte[] blob, boolean isRevoked, int verified)
+ {
+ super(verified);
+ PGPObjectFactory factory = new PGPObjectFactory(blob);
+ PGPKeyRing keyRing = null;
+ try {
+ if ((keyRing = (PGPKeyRing) factory.nextObject()) == null) {
+ Log.e(Constants.TAG, "No keys given!");
+ }
+ } catch (IOException e) {
+ Log.e(Constants.TAG, "Error while converting to PGPKeyRing!", e);
+ }
+
+ mRing = (PGPSecretKeyRing) keyRing;
+ }
+
+ PGPSecretKeyRing getRing() {
+ return mRing;
+ }
+
+ public CanonicalizedSecretKey getSecretKey() {
+ return new CanonicalizedSecretKey(this, mRing.getSecretKey());
+ }
+
+ public CanonicalizedSecretKey getSecretKey(long id) {
+ return new CanonicalizedSecretKey(this, mRing.getSecretKey(id));
+ }
+
+ public HashSet<Long> getAvailableSubkeys() {
+ HashSet<Long> result = new HashSet<Long>();
+ // then, mark exactly the keys we have available
+ for (PGPSecretKey sub : new IterableIterator<PGPSecretKey>(getRing().getSecretKeys())) {
+ S2K s2k = sub.getS2K();
+ // add key, except if the private key has been stripped (GNU extension)
+ if(s2k == null || (s2k.getProtectionMode() != S2K.GNU_PROTECTION_MODE_NO_PRIVATE_KEY)) {
+ result.add(sub.getKeyID());
+ }
+ }
+ return result;
+ }
+
+ /** Getter that returns the subkey that should be used for signing. */
+ CanonicalizedSecretKey getSigningSubKey() throws PgpGeneralException {
+ PGPSecretKey key = mRing.getSecretKey(getSignId());
+ if(key != null) {
+ CanonicalizedSecretKey cKey = new CanonicalizedSecretKey(this, key);
+ if(!cKey.canSign()) {
+ throw new PgpGeneralException("key error");
+ }
+ return cKey;
+ }
+ // TODO handle with proper exception
+ throw new PgpGeneralException("no signing key available");
+ }
+
+ public boolean hasPassphrase() {
+ PGPSecretKey secretKey = null;
+ boolean foundValidKey = false;
+ for (Iterator keys = mRing.getSecretKeys(); keys.hasNext(); ) {
+ secretKey = (PGPSecretKey) keys.next();
+ if (!secretKey.isPrivateKeyEmpty()) {
+ foundValidKey = true;
+ break;
+ }
+ }
+ if(!foundValidKey) {
+ return false;
+ }
+
+ try {
+ PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
+ .setProvider("SC").build("".toCharArray());
+ PGPPrivateKey testKey = secretKey.extractPrivateKey(keyDecryptor);
+ return testKey == null;
+ } catch(PGPException e) {
+ // this means the crc check failed -> passphrase required
+ return true;
+ }
+ }
+
+ public IterableIterator<CanonicalizedSecretKey> secretKeyIterator() {
+ final Iterator<PGPSecretKey> it = mRing.getSecretKeys();
+ return new IterableIterator<CanonicalizedSecretKey>(new Iterator<CanonicalizedSecretKey>() {
+ @Override
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public CanonicalizedSecretKey next() {
+ return new CanonicalizedSecretKey(CanonicalizedSecretKeyRing.this, it.next());
+ }
+
+ @Override
+ public void remove() {
+ it.remove();
+ }
+ });
+ }
+
+ public IterableIterator<CanonicalizedPublicKey> publicKeyIterator() {
+ final Iterator<PGPPublicKey> it = getRing().getPublicKeys();
+ return new IterableIterator<CanonicalizedPublicKey>(new Iterator<CanonicalizedPublicKey>() {
+ @Override
+ public boolean hasNext() {
+ return it.hasNext();
+ }
+
+ @Override
+ public CanonicalizedPublicKey next() {
+ return new CanonicalizedPublicKey(CanonicalizedSecretKeyRing.this, it.next());
+ }
+
+ @Override
+ public void remove() {
+ it.remove();
+ }
+ });
+ }
+
+}