mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-25 08:28:50 -05:00
wrapped-key-ring: more refactoring - no more pgp imports in KeychainIntentService!
This commit is contained in:
parent
32baf42515
commit
f524fa692c
@ -1,44 +1,26 @@
|
|||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
import org.spongycastle.openpgp.PGPSignature;
|
|
||||||
|
|
||||||
public abstract class CachedKeyRing {
|
public abstract class CachedKeyRing {
|
||||||
|
|
||||||
private final long mMasterKeyId;
|
private final long mMasterKeyId;
|
||||||
private final int mKeySize;
|
|
||||||
private final boolean mIsRevoked;
|
|
||||||
private final boolean mCanCertify;
|
private final boolean mCanCertify;
|
||||||
private final long mCreation;
|
|
||||||
private final long mExpiry;
|
|
||||||
private final int mAlgorithm;
|
|
||||||
private final byte[] mFingerprint;
|
private final byte[] mFingerprint;
|
||||||
private final String mUserId;
|
private final String mUserId;
|
||||||
private final int mVerified;
|
private final int mVerified;
|
||||||
private final boolean mHasSecret;
|
private final boolean mHasSecret;
|
||||||
|
|
||||||
protected CachedKeyRing(long masterKeyId, int keySize, boolean isRevoked,
|
protected CachedKeyRing(long masterKeyId, boolean canCertify,
|
||||||
boolean canCertify, long creation, long expiry, int algorithm,
|
|
||||||
byte[] fingerprint, String userId, int verified, boolean hasSecret)
|
byte[] fingerprint, String userId, int verified, boolean hasSecret)
|
||||||
{
|
{
|
||||||
mMasterKeyId = masterKeyId;
|
mMasterKeyId = masterKeyId;
|
||||||
mKeySize = keySize;
|
|
||||||
mIsRevoked = isRevoked;
|
|
||||||
mCanCertify = canCertify;
|
mCanCertify = canCertify;
|
||||||
mCreation = creation;
|
|
||||||
mExpiry = expiry;
|
|
||||||
mAlgorithm = algorithm;
|
|
||||||
mFingerprint = fingerprint;
|
mFingerprint = fingerprint;
|
||||||
mUserId = userId;
|
mUserId = userId;
|
||||||
mVerified = verified;
|
mVerified = verified;
|
||||||
mHasSecret = hasSecret;
|
mHasSecret = hasSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isRevoked() {
|
|
||||||
return mIsRevoked;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getFingerprint() {
|
public byte[] getFingerprint() {
|
||||||
|
|
||||||
return mFingerprint;
|
return mFingerprint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,4 +36,12 @@ public abstract class CachedKeyRing {
|
|||||||
return mVerified;
|
return mVerified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canCertify() {
|
||||||
|
return mCanCertify;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasSecret() {
|
||||||
|
return mHasSecret;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,10 @@ public class CachedPublicKey {
|
|||||||
return mKey.getKeyID();
|
return mKey.getKeyID();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isRevoked() {
|
||||||
|
return mKey.isRevoked();
|
||||||
|
}
|
||||||
|
|
||||||
public Date getCreationTime() {
|
public Date getCreationTime() {
|
||||||
return mKey.getCreationTime();
|
return mKey.getCreationTime();
|
||||||
}
|
}
|
||||||
@ -48,6 +52,15 @@ public class CachedPublicKey {
|
|||||||
return calendar.getTime();
|
return calendar.getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isExpired() {
|
||||||
|
Date creationDate = mKey.getCreationTime();
|
||||||
|
Date expiryDate = mKey.getValidSeconds() > 0
|
||||||
|
? new Date(creationDate.getTime() + mKey.getValidSeconds() * 1000) : null;
|
||||||
|
|
||||||
|
Date now = new Date();
|
||||||
|
return creationDate.after(now) || (expiryDate != null && expiryDate.before(now));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMasterKey() {
|
public boolean isMasterKey() {
|
||||||
return mKey.isMasterKey();
|
return mKey.isMasterKey();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package org.sufficientlysecure.keychain.pgp;
|
|||||||
|
|
||||||
import org.spongycastle.bcpg.ArmoredOutputStream;
|
import org.spongycastle.bcpg.ArmoredOutputStream;
|
||||||
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
import org.spongycastle.bcpg.SignatureSubpacketTags;
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
|
||||||
import org.spongycastle.openpgp.PGPException;
|
import org.spongycastle.openpgp.PGPException;
|
||||||
import org.spongycastle.openpgp.PGPPublicKey;
|
import org.spongycastle.openpgp.PGPPublicKey;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
@ -17,7 +16,6 @@ import org.sufficientlysecure.keychain.util.IterableIterator;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.SignatureException;
|
import java.security.SignatureException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class CachedPublicKeyRing extends CachedKeyRing {
|
public class CachedPublicKeyRing extends CachedKeyRing {
|
||||||
@ -30,8 +28,7 @@ public class CachedPublicKeyRing extends CachedKeyRing {
|
|||||||
byte[] fingerprint, String userId, int verified, boolean hasSecret,
|
byte[] fingerprint, String userId, int verified, boolean hasSecret,
|
||||||
byte[] pubkey)
|
byte[] pubkey)
|
||||||
{
|
{
|
||||||
super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry,
|
super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret);
|
||||||
algorithm, fingerprint, userId, verified, hasSecret);
|
|
||||||
|
|
||||||
mPubKey = pubkey;
|
mPubKey = pubkey;
|
||||||
}
|
}
|
||||||
@ -55,24 +52,46 @@ public class CachedPublicKeyRing extends CachedKeyRing {
|
|||||||
return new CachedPublicKey(this, getRing().getPublicKey(id));
|
return new CachedPublicKey(this, getRing().getPublicKey(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachedPublicKey getFirstEncryptSubkey() throws PgpGeneralException {
|
public CachedPublicKey getFirstSignSubkey() throws PgpGeneralException {
|
||||||
// only return master key if no other encryption key is available
|
// only return master key if no other signing key is available
|
||||||
PGPPublicKey masterKey = null;
|
CachedPublicKey masterKey = null;
|
||||||
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) {
|
for (PGPPublicKey k : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) {
|
||||||
if (key.isRevoked() || !isEncryptionKey(key) || isExpired(key)) {
|
CachedPublicKey key = new CachedPublicKey(this, k);
|
||||||
|
if (key.isRevoked() || key.canSign() || key.isExpired()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (key.isMasterKey()) {
|
if (key.isMasterKey()) {
|
||||||
masterKey = key;
|
masterKey = key;
|
||||||
} else {
|
} else {
|
||||||
return new CachedPublicKey(this, key);
|
return key;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(masterKey == null) {
|
if(masterKey == null) {
|
||||||
// TODO proper exception
|
// TODO proper exception
|
||||||
throw new PgpGeneralException("key not found");
|
throw new PgpGeneralException("key not found");
|
||||||
}
|
}
|
||||||
return new CachedPublicKey(this, masterKey);
|
return masterKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CachedPublicKey getFirstEncryptSubkey() throws PgpGeneralException {
|
||||||
|
// only return master key if no other encryption key is available
|
||||||
|
CachedPublicKey masterKey = null;
|
||||||
|
for (PGPPublicKey k : new IterableIterator<PGPPublicKey>(getRing().getPublicKeys())) {
|
||||||
|
CachedPublicKey key = new CachedPublicKey(this, k);
|
||||||
|
if (key.isRevoked() || key.canEncrypt() || key.isExpired()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (key.isMasterKey()) {
|
||||||
|
masterKey = key;
|
||||||
|
} else {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(masterKey == null) {
|
||||||
|
// TODO proper exception
|
||||||
|
throw new PgpGeneralException("key not found");
|
||||||
|
}
|
||||||
|
return masterKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) {
|
public boolean verifySubkeyBinding(CachedPublicKey cachedSubkey) {
|
||||||
@ -132,55 +151,6 @@ public class CachedPublicKeyRing extends CachedKeyRing {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean isEncryptionKey(PGPPublicKey key) {
|
|
||||||
if (!key.isEncryptionKey()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.getVersion() <= 3) {
|
|
||||||
// this must be true now
|
|
||||||
return key.isEncryptionKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
// special cases
|
|
||||||
if (key.getAlgorithm() == PGPPublicKey.ELGAMAL_ENCRYPT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key.getAlgorithm() == PGPPublicKey.RSA_ENCRYPT) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PGPSignature sig : new IterableIterator<PGPSignature>(key.getSignatures())) {
|
|
||||||
if (key.isMasterKey() && sig.getKeyID() != key.getKeyID()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
PGPSignatureSubpacketVector hashed = sig.getHashedSubPackets();
|
|
||||||
|
|
||||||
if (hashed != null
|
|
||||||
&& (hashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSignatureSubpacketVector unhashed = sig.getUnhashedSubPackets();
|
|
||||||
|
|
||||||
if (unhashed != null
|
|
||||||
&& (unhashed.getKeyFlags() & (KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE)) != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean isExpired(PGPPublicKey key) {
|
|
||||||
Date creationDate = key.getCreationTime();
|
|
||||||
Date expiryDate = key.getValidSeconds() > 0
|
|
||||||
? new Date(creationDate.getTime() + key.getValidSeconds() * 1000) : null;
|
|
||||||
|
|
||||||
Date now = new Date();
|
|
||||||
return creationDate.after(now) || (expiryDate != null && expiryDate.before(now));
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
|
static boolean verifyPrimaryKeyBinding(PGPSignatureSubpacketVector pkts,
|
||||||
PGPPublicKey masterPublicKey,
|
PGPPublicKey masterPublicKey,
|
||||||
PGPPublicKey signingPublicKey) {
|
PGPPublicKey signingPublicKey) {
|
||||||
|
@ -9,9 +9,14 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
|
import org.spongycastle.openpgp.operator.jcajce.JcaPGPDigestCalculatorProviderBuilder;
|
||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
||||||
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||||
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.NoSuchProviderException;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class CachedSecretKeyRing extends CachedKeyRing {
|
public class CachedSecretKeyRing extends CachedKeyRing {
|
||||||
@ -23,12 +28,15 @@ public class CachedSecretKeyRing extends CachedKeyRing {
|
|||||||
byte[] fingerprint, String userId, int verified, boolean hasSecret,
|
byte[] fingerprint, String userId, int verified, boolean hasSecret,
|
||||||
byte[] blob)
|
byte[] blob)
|
||||||
{
|
{
|
||||||
super(masterKeyId, keySize, isRevoked, canCertify, creation, expiry,
|
super(masterKeyId, canCertify, fingerprint, userId, verified, hasSecret);
|
||||||
algorithm, fingerprint, userId, verified, hasSecret);
|
|
||||||
|
|
||||||
mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob);
|
mRing = (PGPSecretKeyRing) PgpConversionHelper.BytesToPGPKeyRing(blob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PGPSecretKeyRing getRing() {
|
||||||
|
return mRing;
|
||||||
|
}
|
||||||
|
|
||||||
public CachedSecretKey getSubKey() {
|
public CachedSecretKey getSubKey() {
|
||||||
return new CachedSecretKey(this, mRing.getSecretKey());
|
return new CachedSecretKey(this, mRing.getSecretKey());
|
||||||
}
|
}
|
||||||
@ -110,4 +118,27 @@ public class CachedSecretKeyRing extends CachedKeyRing {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UncachedSecretKeyRing changeSecretKeyPassphrase(String oldPassphrase,
|
||||||
|
String newPassphrase)
|
||||||
|
throws IOException, PGPException, NoSuchProviderException {
|
||||||
|
|
||||||
|
if (oldPassphrase == null) {
|
||||||
|
oldPassphrase = "";
|
||||||
|
}
|
||||||
|
if (newPassphrase == null) {
|
||||||
|
newPassphrase = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
|
||||||
|
mRing,
|
||||||
|
new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
|
||||||
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
|
||||||
|
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()),
|
||||||
|
new JcePBESecretKeyEncryptorBuilder(mRing.getSecretKey()
|
||||||
|
.getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray()));
|
||||||
|
|
||||||
|
return new UncachedSecretKeyRing(newKeyRing);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -165,36 +165,4 @@ public class PgpConversionHelper {
|
|||||||
return os.toByteArray();
|
return os.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert from PGPSecretKey to byte[]
|
|
||||||
*
|
|
||||||
* @param key
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] PGPSecretKeyToBytes(PGPSecretKey key) {
|
|
||||||
try {
|
|
||||||
return key.getEncoded();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(Constants.TAG, "Encoding failed", e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert from PGPSecretKeyRing to byte[]
|
|
||||||
*
|
|
||||||
* @param keyRing
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static byte[] PGPSecretKeyRingToBytes(PGPSecretKeyRing keyRing) {
|
|
||||||
try {
|
|
||||||
return keyRing.getEncoded();
|
|
||||||
} catch (IOException e) {
|
|
||||||
Log.e(Constants.TAG, "Encoding failed", e);
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -277,7 +277,7 @@ public class PgpImportExport {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public int storeKeyRingInCache(UncachedKeyRing keyring) {
|
public int storeKeyRingInCache(UncachedKeyRing keyring) {
|
||||||
int status = RETURN_ERROR;
|
int status;
|
||||||
try {
|
try {
|
||||||
PGPSecretKeyRing secretKeyRing = keyring.getSecretRing();
|
PGPSecretKeyRing secretKeyRing = keyring.getSecretRing();
|
||||||
PGPPublicKeyRing publicKeyRing = keyring.getPublicRing();
|
PGPPublicKeyRing publicKeyRing = keyring.getPublicRing();
|
||||||
|
@ -81,18 +81,6 @@ public class PgpKeyHelper {
|
|||||||
return getExpiryDate(key.getPublicKey());
|
return getExpiryDate(key.getPublicKey());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static boolean isExpired(PGPPublicKey key) {
|
|
||||||
Date creationDate = getCreationDate(key);
|
|
||||||
Date expiryDate = getExpiryDate(key);
|
|
||||||
Date now = new Date();
|
|
||||||
if (now.compareTo(creationDate) >= 0
|
|
||||||
&& (expiryDate == null || now.compareTo(expiryDate) <= 0)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
|
public static PGPSecretKey getKeyNum(PGPSecretKeyRing keyRing, long num) {
|
||||||
@ -110,48 +98,6 @@ public class PgpKeyHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Deprecated
|
|
||||||
private static Vector<PGPSecretKey> getSigningKeys(PGPSecretKeyRing keyRing) {
|
|
||||||
Vector<PGPSecretKey> signingKeys = new Vector<PGPSecretKey>();
|
|
||||||
|
|
||||||
for (PGPSecretKey key : new IterableIterator<PGPSecretKey>(keyRing.getSecretKeys())) {
|
|
||||||
if (isSigningKey(key)) {
|
|
||||||
signingKeys.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return signingKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
private static Vector<PGPSecretKey> getUsableSigningKeys(PGPSecretKeyRing keyRing) {
|
|
||||||
Vector<PGPSecretKey> usableKeys = new Vector<PGPSecretKey>();
|
|
||||||
Vector<PGPSecretKey> signingKeys = getSigningKeys(keyRing);
|
|
||||||
PGPSecretKey masterKey = null;
|
|
||||||
for (int i = 0; i < signingKeys.size(); ++i) {
|
|
||||||
PGPSecretKey key = signingKeys.get(i);
|
|
||||||
if (key.isMasterKey()) {
|
|
||||||
masterKey = key;
|
|
||||||
} else {
|
|
||||||
usableKeys.add(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (masterKey != null) {
|
|
||||||
usableKeys.add(masterKey);
|
|
||||||
}
|
|
||||||
return usableKeys;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static PGPSecretKey getFirstSigningSubkey(PGPSecretKeyRing keyRing) {
|
|
||||||
Vector<PGPSecretKey> signingKeys = getUsableSigningKeys(keyRing);
|
|
||||||
if (signingKeys.size() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return signingKeys.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getKeyUsage(PGPSecretKey key) {
|
public static int getKeyUsage(PGPSecretKey key) {
|
||||||
return getKeyUsage(key.getPublicKey());
|
return getKeyUsage(key.getPublicKey());
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,6 @@ import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|||||||
import org.spongycastle.openpgp.PGPSignature;
|
import org.spongycastle.openpgp.PGPSignature;
|
||||||
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
import org.spongycastle.openpgp.PGPSignatureGenerator;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
|
||||||
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
|
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyDecryptor;
|
||||||
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
import org.spongycastle.openpgp.operator.PBESecretKeyEncryptor;
|
||||||
@ -48,10 +47,8 @@ import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder;
|
|||||||
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
import org.spongycastle.openpgp.operator.jcajce.JcePBESecretKeyEncryptorBuilder;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
||||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
|
||||||
import org.sufficientlysecure.keychain.util.Primes;
|
import org.sufficientlysecure.keychain.util.Primes;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -66,7 +63,6 @@ import java.util.ArrayList;
|
|||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -124,7 +120,7 @@ public class PgpKeyOperation {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// TODO: key flags?
|
// TODO: key flags?
|
||||||
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase,
|
public byte[] createKey(int algorithmChoice, int keySize, String passphrase,
|
||||||
boolean isMasterKey)
|
boolean isMasterKey)
|
||||||
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||||
PgpGeneralMsgIdException, InvalidAlgorithmParameterException {
|
PgpGeneralMsgIdException, InvalidAlgorithmParameterException {
|
||||||
@ -188,35 +184,15 @@ public class PgpKeyOperation {
|
|||||||
PGPEncryptedData.CAST5, sha1Calc)
|
PGPEncryptedData.CAST5, sha1Calc)
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||||
|
|
||||||
return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
try {
|
||||||
sha1Calc, isMasterKey, keyEncryptor);
|
return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
||||||
|
sha1Calc, isMasterKey, keyEncryptor).getEncoded();
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new PgpGeneralMsgIdException(R.string.error_encoding);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public PGPSecretKeyRing changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassphrase,
|
public UncachedKeyRing buildNewSecretKey(
|
||||||
String newPassphrase)
|
|
||||||
throws IOException, PGPException, NoSuchProviderException {
|
|
||||||
|
|
||||||
updateProgress(R.string.progress_building_key, 0, 100);
|
|
||||||
if (oldPassphrase == null) {
|
|
||||||
oldPassphrase = "";
|
|
||||||
}
|
|
||||||
if (newPassphrase == null) {
|
|
||||||
newPassphrase = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
PGPSecretKeyRing newKeyRing = PGPSecretKeyRing.copyWithNewPassword(
|
|
||||||
keyRing,
|
|
||||||
new JcePBESecretKeyDecryptorBuilder(new JcaPGPDigestCalculatorProviderBuilder()
|
|
||||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build()).setProvider(
|
|
||||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassphrase.toCharArray()),
|
|
||||||
new JcePBESecretKeyEncryptorBuilder(keyRing.getSecretKey()
|
|
||||||
.getKeyEncryptionAlgorithm()).build(newPassphrase.toCharArray()));
|
|
||||||
|
|
||||||
return newKeyRing;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildNewSecretKey(
|
|
||||||
SaveKeyringParcel saveParcel)
|
SaveKeyringParcel saveParcel)
|
||||||
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
|
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
|
||||||
|
|
||||||
@ -357,17 +333,19 @@ public class PgpKeyOperation {
|
|||||||
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
|
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
|
||||||
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
|
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
|
||||||
|
|
||||||
return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(secretKeyRing, publicKeyRing);
|
return new UncachedKeyRing(publicKeyRing, secretKeyRing);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pair<PGPSecretKeyRing, PGPPublicKeyRing> buildSecretKey(PGPSecretKeyRing mKR,
|
public UncachedKeyRing buildSecretKey(CachedSecretKeyRing wmKR,
|
||||||
PGPPublicKeyRing pKR,
|
CachedPublicKeyRing wpKR,
|
||||||
SaveKeyringParcel saveParcel)
|
SaveKeyringParcel saveParcel)
|
||||||
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
|
throws PgpGeneralMsgIdException, PGPException, SignatureException, IOException {
|
||||||
|
|
||||||
|
PGPSecretKeyRing mKR = wmKR.getRing();
|
||||||
|
PGPPublicKeyRing pKR = wpKR.getRing();
|
||||||
|
|
||||||
updateProgress(R.string.progress_building_key, 0, 100);
|
updateProgress(R.string.progress_building_key, 0, 100);
|
||||||
PGPSecretKey masterKey = saveParcel.keys.get(0);
|
|
||||||
|
|
||||||
if (saveParcel.oldPassphrase == null) {
|
if (saveParcel.oldPassphrase == null) {
|
||||||
saveParcel.oldPassphrase = "";
|
saveParcel.oldPassphrase = "";
|
||||||
@ -404,7 +382,7 @@ public class PgpKeyOperation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
masterKey = mKR.getSecretKey();
|
PGPSecretKey masterKey = mKR.getSecretKey();
|
||||||
PGPPublicKey masterPublicKey = masterKey.getPublicKey();
|
PGPPublicKey masterPublicKey = masterKey.getPublicKey();
|
||||||
|
|
||||||
int usageId = saveParcel.keysUsages.get(0);
|
int usageId = saveParcel.keysUsages.get(0);
|
||||||
@ -686,7 +664,7 @@ public class PgpKeyOperation {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return new Pair<PGPSecretKeyRing, PGPPublicKeyRing>(mKR, pKR);
|
return new UncachedKeyRing(pKR, mKR);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,15 @@
|
|||||||
package org.sufficientlysecure.keychain.pgp;
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
import org.spongycastle.openpgp.PGPObjectFactory;
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
import org.spongycastle.openpgp.PGPUtil;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
public class UncachedKeyRing {
|
public class UncachedKeyRing {
|
||||||
|
|
||||||
@ -9,8 +17,6 @@ public class UncachedKeyRing {
|
|||||||
final PGPSecretKeyRing mSecretRing;
|
final PGPSecretKeyRing mSecretRing;
|
||||||
|
|
||||||
UncachedKeyRing(PGPPublicKeyRing publicRing, PGPSecretKeyRing secretRing) {
|
UncachedKeyRing(PGPPublicKeyRing publicRing, PGPSecretKeyRing secretRing) {
|
||||||
// this one must not be false!
|
|
||||||
assert(publicRing != null);
|
|
||||||
mPublicRing = publicRing;
|
mPublicRing = publicRing;
|
||||||
mSecretRing = secretRing;
|
mSecretRing = secretRing;
|
||||||
}
|
}
|
||||||
@ -26,4 +32,29 @@ public class UncachedKeyRing {
|
|||||||
public PGPSecretKeyRing getSecretRing() {
|
public PGPSecretKeyRing getSecretRing() {
|
||||||
return mSecretRing;
|
return mSecretRing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public byte[] getFingerprint() {
|
||||||
|
return mPublicRing.getPublicKey().getFingerprint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UncachedKeyRing decodePubkeyFromData(byte[] data)
|
||||||
|
throws PgpGeneralException, IOException {
|
||||||
|
BufferedInputStream bufferedInput =
|
||||||
|
new BufferedInputStream(new ByteArrayInputStream(data));
|
||||||
|
if (bufferedInput.available() > 0) {
|
||||||
|
InputStream in = PGPUtil.getDecoderStream(bufferedInput);
|
||||||
|
PGPObjectFactory objectFactory = new PGPObjectFactory(in);
|
||||||
|
|
||||||
|
// get first object in block
|
||||||
|
Object obj;
|
||||||
|
if ((obj = objectFactory.nextObject()) != null && obj instanceof PGPPublicKeyRing) {
|
||||||
|
return new UncachedKeyRing((PGPPublicKeyRing) obj);
|
||||||
|
} else {
|
||||||
|
throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new PgpGeneralException("Object not recognized as PGPPublicKeyRing!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
package org.sufficientlysecure.keychain.pgp;
|
||||||
|
|
||||||
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
|
|
||||||
|
public class UncachedSecretKeyRing {
|
||||||
|
|
||||||
|
final PGPSecretKeyRing mSecretRing;
|
||||||
|
|
||||||
|
UncachedSecretKeyRing(PGPSecretKeyRing secretRing) {
|
||||||
|
mSecretRing = secretRing;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Breaking the pattern here, for key import!
|
||||||
|
// TODO reduce this from public to default visibility!
|
||||||
|
public PGPSecretKeyRing getSecretKeyRing() {
|
||||||
|
return mSecretRing;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -43,6 +43,8 @@ import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing;
|
|||||||
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.UncachedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.ApiApps;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.Certs;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRingData;
|
||||||
@ -484,12 +486,22 @@ public class ProviderHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
|
||||||
|
* is already in the database!
|
||||||
|
*/
|
||||||
|
public void saveKeyRing(UncachedSecretKeyRing wrappedRing) throws IOException {
|
||||||
|
// TODO split up getters
|
||||||
|
PGPSecretKeyRing keyRing = wrappedRing.getSecretKeyRing();
|
||||||
|
saveKeyRing(keyRing);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
|
* Saves a PGPSecretKeyRing in the DB. This will only work if a corresponding public keyring
|
||||||
* is already in the database!
|
* is already in the database!
|
||||||
*/
|
*/
|
||||||
public void saveKeyRing(PGPSecretKeyRing keyRing) throws IOException {
|
public void saveKeyRing(PGPSecretKeyRing keyRing) throws IOException {
|
||||||
long masterKeyId = keyRing.getPublicKey().getKeyID();
|
long masterKeyId = keyRing.getSecretKey().getKeyID();
|
||||||
|
|
||||||
{
|
{
|
||||||
Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId));
|
Uri uri = Keys.buildKeysUri(Long.toString(masterKeyId));
|
||||||
@ -526,6 +538,12 @@ public class ProviderHelper {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void saveKeyRing(UncachedKeyRing wrappedRing) throws IOException {
|
||||||
|
PGPPublicKeyRing pubRing = wrappedRing.getPublicRing();
|
||||||
|
PGPSecretKeyRing secRing = wrappedRing.getSecretRing();
|
||||||
|
saveKeyRing(pubRing, secRing);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Saves (or updates) a pair of public and secret KeyRings in the database
|
* Saves (or updates) a pair of public and secret KeyRings in the database
|
||||||
*/
|
*/
|
||||||
|
@ -27,12 +27,6 @@ import android.os.Messenger;
|
|||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
|
|
||||||
import org.spongycastle.bcpg.sig.KeyFlags;
|
import org.spongycastle.bcpg.sig.KeyFlags;
|
||||||
import org.spongycastle.openpgp.PGPKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPObjectFactory;
|
|
||||||
import org.spongycastle.openpgp.PGPPublicKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKey;
|
|
||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
|
||||||
import org.spongycastle.openpgp.PGPUtil;
|
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.helper.FileHelper;
|
import org.sufficientlysecure.keychain.helper.FileHelper;
|
||||||
@ -41,7 +35,6 @@ import org.sufficientlysecure.keychain.helper.Preferences;
|
|||||||
import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.CachedSecretKey;
|
import org.sufficientlysecure.keychain.pgp.CachedSecretKey;
|
||||||
import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing;
|
import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
|
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerify;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
|
import org.sufficientlysecure.keychain.pgp.PgpDecryptVerifyResult;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpHelper;
|
||||||
@ -51,6 +44,7 @@ import org.sufficientlysecure.keychain.pgp.PgpKeyOperation;
|
|||||||
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
|
import org.sufficientlysecure.keychain.pgp.PgpSignEncrypt;
|
||||||
import org.sufficientlysecure.keychain.pgp.Progressable;
|
import org.sufficientlysecure.keychain.pgp.Progressable;
|
||||||
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
import org.sufficientlysecure.keychain.pgp.UncachedKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.UncachedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralMsgIdException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
@ -63,7 +57,6 @@ import org.sufficientlysecure.keychain.util.KeychainServiceListener;
|
|||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
import org.sufficientlysecure.keychain.util.ProgressScaler;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -516,19 +509,19 @@ public class KeychainIntentService extends IntentService
|
|||||||
/* Operation */
|
/* Operation */
|
||||||
ProviderHelper providerHelper = new ProviderHelper(this);
|
ProviderHelper providerHelper = new ProviderHelper(this);
|
||||||
if (!canSign) {
|
if (!canSign) {
|
||||||
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 50, 100));
|
setProgress(R.string.progress_building_key, 0, 100);
|
||||||
PGPSecretKeyRing keyRing = providerHelper.getPGPSecretKeyRing(masterKeyId);
|
CachedSecretKeyRing keyRing = providerHelper.getCachedSecretKeyRing(masterKeyId);
|
||||||
keyRing = keyOperations.changeSecretKeyPassphrase(keyRing,
|
UncachedSecretKeyRing newKeyRing =
|
||||||
oldPassphrase, newPassphrase);
|
keyRing.changeSecretKeyPassphrase(oldPassphrase, newPassphrase);
|
||||||
setProgress(R.string.progress_saving_key_ring, 50, 100);
|
setProgress(R.string.progress_saving_key_ring, 50, 100);
|
||||||
providerHelper.saveKeyRing(keyRing);
|
providerHelper.saveKeyRing(newKeyRing);
|
||||||
setProgress(R.string.progress_done, 100, 100);
|
setProgress(R.string.progress_done, 100, 100);
|
||||||
} else {
|
} else {
|
||||||
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100));
|
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 90, 100));
|
||||||
PgpKeyOperation.Pair<PGPSecretKeyRing, PGPPublicKeyRing> pair;
|
UncachedKeyRing pair;
|
||||||
try {
|
try {
|
||||||
PGPSecretKeyRing privkey = providerHelper.getPGPSecretKeyRing(masterKeyId);
|
CachedSecretKeyRing privkey = providerHelper.getCachedSecretKeyRing(masterKeyId);
|
||||||
PGPPublicKeyRing pubkey = providerHelper.getPGPPublicKeyRing(masterKeyId);
|
CachedPublicKeyRing pubkey = providerHelper.getCachedPublicKeyRing(masterKeyId);
|
||||||
|
|
||||||
pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing
|
pair = keyOperations.buildSecretKey(privkey, pubkey, saveParcel); // edit existing
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
@ -537,7 +530,7 @@ public class KeychainIntentService extends IntentService
|
|||||||
|
|
||||||
setProgress(R.string.progress_saving_key_ring, 90, 100);
|
setProgress(R.string.progress_saving_key_ring, 90, 100);
|
||||||
// save the pair
|
// save the pair
|
||||||
providerHelper.saveKeyRing(pair.second, pair.first);
|
providerHelper.saveKeyRing(pair);
|
||||||
setProgress(R.string.progress_done, 100, 100);
|
setProgress(R.string.progress_done, 100, 100);
|
||||||
}
|
}
|
||||||
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
|
PassphraseCacheService.addCachedPassphrase(this, masterKeyId, newPassphrase);
|
||||||
@ -557,13 +550,11 @@ public class KeychainIntentService extends IntentService
|
|||||||
|
|
||||||
/* Operation */
|
/* Operation */
|
||||||
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
|
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
|
||||||
PGPSecretKey newKey = keyOperations.createKey(algorithm, keysize,
|
byte[] newKey = keyOperations.createKey(algorithm, keysize, passphrase, masterKey);
|
||||||
passphrase, masterKey);
|
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
Bundle resultData = new Bundle();
|
Bundle resultData = new Bundle();
|
||||||
resultData.putByteArray(RESULT_NEW_KEY,
|
resultData.putByteArray(RESULT_NEW_KEY, newKey);
|
||||||
PgpConversionHelper.PGPSecretKeyToBytes(newKey));
|
|
||||||
|
|
||||||
OtherHelper.logDebugBundle(resultData, "resultData");
|
OtherHelper.logDebugBundle(resultData, "resultData");
|
||||||
|
|
||||||
@ -576,7 +567,6 @@ public class KeychainIntentService extends IntentService
|
|||||||
try {
|
try {
|
||||||
/* Input */
|
/* Input */
|
||||||
String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
|
String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
|
||||||
ArrayList<PGPSecretKey> newKeys = new ArrayList<PGPSecretKey>();
|
|
||||||
ArrayList<Integer> keyUsageList = new ArrayList<Integer>();
|
ArrayList<Integer> keyUsageList = new ArrayList<Integer>();
|
||||||
|
|
||||||
/* Operation */
|
/* Operation */
|
||||||
@ -589,23 +579,27 @@ public class KeychainIntentService extends IntentService
|
|||||||
keysTotal);
|
keysTotal);
|
||||||
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
|
PgpKeyOperation keyOperations = new PgpKeyOperation(new ProgressScaler(this, 0, 100, 100));
|
||||||
|
|
||||||
PGPSecretKey masterKey = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
byte[] buf;
|
||||||
|
|
||||||
|
buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
||||||
4096, passphrase, true);
|
4096, passphrase, true);
|
||||||
newKeys.add(masterKey);
|
os.write(buf);
|
||||||
keyUsageList.add(KeyFlags.CERTIFY_OTHER);
|
keyUsageList.add(KeyFlags.CERTIFY_OTHER);
|
||||||
keysCreated++;
|
keysCreated++;
|
||||||
setProgress(keysCreated, keysTotal);
|
setProgress(keysCreated, keysTotal);
|
||||||
|
|
||||||
PGPSecretKey subKey = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
||||||
4096, passphrase, false);
|
4096, passphrase, false);
|
||||||
newKeys.add(subKey);
|
os.write(buf);
|
||||||
keyUsageList.add(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
|
keyUsageList.add(KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE);
|
||||||
keysCreated++;
|
keysCreated++;
|
||||||
setProgress(keysCreated, keysTotal);
|
setProgress(keysCreated, keysTotal);
|
||||||
|
|
||||||
subKey = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
buf = keyOperations.createKey(Constants.choice.algorithm.rsa,
|
||||||
4096, passphrase, false);
|
4096, passphrase, false);
|
||||||
newKeys.add(subKey);
|
os.write(buf);
|
||||||
keyUsageList.add(KeyFlags.SIGN_DATA);
|
keyUsageList.add(KeyFlags.SIGN_DATA);
|
||||||
keysCreated++;
|
keysCreated++;
|
||||||
setProgress(keysCreated, keysTotal);
|
setProgress(keysCreated, keysTotal);
|
||||||
@ -614,10 +608,8 @@ public class KeychainIntentService extends IntentService
|
|||||||
// for sign
|
// for sign
|
||||||
|
|
||||||
/* Output */
|
/* Output */
|
||||||
|
|
||||||
Bundle resultData = new Bundle();
|
Bundle resultData = new Bundle();
|
||||||
resultData.putByteArray(RESULT_NEW_KEY,
|
resultData.putByteArray(RESULT_NEW_KEY, os.toByteArray());
|
||||||
PgpConversionHelper.PGPSecretKeyArrayListToBytes(newKeys));
|
|
||||||
resultData.putIntegerArrayList(RESULT_KEY_USAGES, keyUsageList);
|
resultData.putIntegerArrayList(RESULT_KEY_USAGES, keyUsageList);
|
||||||
|
|
||||||
OtherHelper.logDebugBundle(resultData, "resultData");
|
OtherHelper.logDebugBundle(resultData, "resultData");
|
||||||
@ -755,30 +747,13 @@ public class KeychainIntentService extends IntentService
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create PGPKeyRing object based on downloaded armored key
|
// create PGPKeyRing object based on downloaded armored key
|
||||||
PGPKeyRing downloadedKey = null;
|
UncachedKeyRing downloadedKey =
|
||||||
BufferedInputStream bufferedInput =
|
UncachedKeyRing.decodePubkeyFromData(downloadedKeyBytes);
|
||||||
new BufferedInputStream(new ByteArrayInputStream(downloadedKeyBytes));
|
|
||||||
if (bufferedInput.available() > 0) {
|
|
||||||
InputStream in = PGPUtil.getDecoderStream(bufferedInput);
|
|
||||||
PGPObjectFactory objectFactory = new PGPObjectFactory(in);
|
|
||||||
|
|
||||||
// get first object in block
|
|
||||||
Object obj;
|
|
||||||
if ((obj = objectFactory.nextObject()) != null) {
|
|
||||||
Log.d(Constants.TAG, "Found class: " + obj.getClass());
|
|
||||||
|
|
||||||
if (obj instanceof PGPKeyRing) {
|
|
||||||
downloadedKey = (PGPKeyRing) obj;
|
|
||||||
} else {
|
|
||||||
throw new PgpGeneralException("Object not recognized as PGPKeyRing!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// verify downloaded key by comparing fingerprints
|
// verify downloaded key by comparing fingerprints
|
||||||
if (entry.getFingerPrintHex() != null) {
|
if (entry.getFingerPrintHex() != null) {
|
||||||
String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex(
|
String downloadedKeyFp = PgpKeyHelper.convertFingerprintToHex(
|
||||||
downloadedKey.getPublicKey().getFingerprint());
|
downloadedKey.getFingerprint());
|
||||||
if (downloadedKeyFp.equals(entry.getFingerPrintHex())) {
|
if (downloadedKeyFp.equals(entry.getFingerPrintHex())) {
|
||||||
Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " +
|
Log.d(Constants.TAG, "fingerprint of downloaded key is the same as " +
|
||||||
"the requested fingerprint!");
|
"the requested fingerprint!");
|
||||||
@ -790,7 +765,7 @@ public class KeychainIntentService extends IntentService
|
|||||||
|
|
||||||
// save key bytes in entry object for doing the
|
// save key bytes in entry object for doing the
|
||||||
// actual import afterwards
|
// actual import afterwards
|
||||||
entry.setBytes(downloadedKey.getEncoded());
|
entry.setBytes(downloadedKeyBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
Intent importIntent = new Intent(this, KeychainIntentService.class);
|
Intent importIntent = new Intent(this, KeychainIntentService.class);
|
||||||
|
@ -34,7 +34,12 @@ import org.spongycastle.openpgp.PGPSecretKey;
|
|||||||
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
import org.spongycastle.openpgp.PGPSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.CachedPublicKey;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.CachedPublicKeyRing;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.CachedSecretKey;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.CachedSecretKeyRing;
|
||||||
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
|
||||||
|
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@ -144,18 +149,14 @@ public class EncryptAsymmetricFragment extends Fragment {
|
|||||||
*/
|
*/
|
||||||
private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds,
|
private void preselectKeys(long preselectedSignatureKeyId, long[] preselectedEncryptionKeyIds,
|
||||||
ProviderHelper providerHelper) {
|
ProviderHelper providerHelper) {
|
||||||
|
// TODO all of this works under the assumption that the first suitable subkey is always used!
|
||||||
|
// not sure if we need to distinguish between different subkeys here?
|
||||||
if (preselectedSignatureKeyId != 0) {
|
if (preselectedSignatureKeyId != 0) {
|
||||||
// TODO: don't use bouncy castle objects!
|
|
||||||
try {
|
try {
|
||||||
PGPSecretKeyRing keyRing = providerHelper.getPGPSecretKeyRingWithKeyId(
|
CachedPublicKeyRing keyring =
|
||||||
preselectedSignatureKeyId);
|
providerHelper.getCachedPublicKeyRing(preselectedSignatureKeyId);
|
||||||
|
if(keyring.hasSecret()) {
|
||||||
PGPSecretKey masterKey = keyRing.getSecretKey();
|
setSignatureKeyId(keyring.getMasterKeyId());
|
||||||
if (masterKey != null) {
|
|
||||||
PGPSecretKey signKey = PgpKeyHelper.getFirstSigningSubkey(keyRing);
|
|
||||||
if (signKey != null) {
|
|
||||||
setSignatureKeyId(masterKey.getKeyID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (ProviderHelper.NotFoundException e) {
|
} catch (ProviderHelper.NotFoundException e) {
|
||||||
Log.e(Constants.TAG, "key not found!", e);
|
Log.e(Constants.TAG, "key not found!", e);
|
||||||
@ -165,7 +166,6 @@ public class EncryptAsymmetricFragment extends Fragment {
|
|||||||
if (preselectedEncryptionKeyIds != null) {
|
if (preselectedEncryptionKeyIds != null) {
|
||||||
Vector<Long> goodIds = new Vector<Long>();
|
Vector<Long> goodIds = new Vector<Long>();
|
||||||
for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
|
for (int i = 0; i < preselectedEncryptionKeyIds.length; ++i) {
|
||||||
// TODO One query per selected key?! wtf
|
|
||||||
try {
|
try {
|
||||||
long id = providerHelper.getMasterKeyId(
|
long id = providerHelper.getMasterKeyId(
|
||||||
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
|
KeyRings.buildUnifiedKeyRingsFindBySubkeyUri(
|
||||||
|
@ -500,5 +500,6 @@
|
|||||||
<string name="title_view_cert">View Certificate Details</string>
|
<string name="title_view_cert">View Certificate Details</string>
|
||||||
<string name="unknown_algorithm">unknown</string>
|
<string name="unknown_algorithm">unknown</string>
|
||||||
<string name="can_sign_not">cannot sign</string>
|
<string name="can_sign_not">cannot sign</string>
|
||||||
|
<string name="error_encoding">Encoding error</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user