fix subkey addition

This commit is contained in:
Vincent Breitmoser 2014-07-02 15:03:28 +02:00
parent 858be93f3d
commit 9fb92c8642
2 changed files with 62 additions and 37 deletions

View File

@ -102,18 +102,13 @@ public class PgpKeyOperation {
} }
/** Creates new secret key. */ /** Creates new secret key. */
private PGPSecretKey createKey(int algorithmChoice, int keySize, String passphrase, private PGPKeyPair createKey(int algorithmChoice, int keySize) throws PgpGeneralMsgIdException {
boolean isMasterKey) throws PgpGeneralMsgIdException {
try { try {
if (keySize < 512) { if (keySize < 512) {
throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit); throw new PgpGeneralMsgIdException(R.string.error_key_size_minimum512bit);
} }
if (passphrase == null) {
passphrase = "";
}
int algorithm; int algorithm;
KeyPairGenerator keyGen; KeyPairGenerator keyGen;
@ -126,9 +121,6 @@ public class PgpKeyOperation {
} }
case Constants.choice.algorithm.elgamal: { case Constants.choice.algorithm.elgamal: {
if (isMasterKey) {
throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal);
}
keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME); keyGen = KeyPairGenerator.getInstance("ElGamal", Constants.BOUNCY_CASTLE_PROVIDER_NAME);
BigInteger p = Primes.getBestPrime(keySize); BigInteger p = Primes.getBestPrime(keySize);
BigInteger g = new BigInteger("2"); BigInteger g = new BigInteger("2");
@ -154,19 +146,8 @@ public class PgpKeyOperation {
} }
// build new key pair // build new key pair
PGPKeyPair keyPair = new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date()); return new JcaPGPKeyPair(algorithm, keyGen.generateKeyPair(), new Date());
// define hashing and signing algos
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
HashAlgorithmTags.SHA1);
// Build key encrypter and decrypter based on passphrase
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
return new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
sha1Calc, isMasterKey, keyEncryptor);
} catch(NoSuchProviderException e) { } catch(NoSuchProviderException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} catch(NoSuchAlgorithmException e) { } catch(NoSuchAlgorithmException e) {
@ -193,12 +174,26 @@ public class PgpKeyOperation {
} }
SubkeyAdd add = saveParcel.addSubKeys.remove(0); SubkeyAdd add = saveParcel.addSubKeys.remove(0);
PGPSecretKey masterSecretKey = createKey(add.mAlgorithm, add.mKeysize, PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize);
saveParcel.newPassphrase, true);
if (add.mAlgorithm == Constants.choice.algorithm.elgamal) {
throw new PgpGeneralMsgIdException(R.string.error_master_key_must_not_be_el_gamal);
}
// define hashing and signing algos
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(HashAlgorithmTags.SHA1);
// Build key encrypter and decrypter based on passphrase
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
PGPSecretKey masterSecretKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
sha1Calc, true, keyEncryptor);
PGPSecretKeyRing sKR = new PGPSecretKeyRing( PGPSecretKeyRing sKR = new PGPSecretKeyRing(
masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator()); masterSecretKey.getEncoded(), new JcaKeyFingerprintCalculator());
return internal(sKR, masterSecretKey, saveParcel, saveParcel.newPassphrase, log, indent); return internal(sKR, masterSecretKey, saveParcel, "", log, indent);
} catch (PGPException e) { } catch (PGPException e) {
Log.e(Constants.TAG, "pgp error encoding key", e); Log.e(Constants.TAG, "pgp error encoding key", e);
@ -207,6 +202,7 @@ public class PgpKeyOperation {
Log.e(Constants.TAG, "io error encoding key", e); Log.e(Constants.TAG, "io error encoding key", e);
return null; return null;
} catch (PgpGeneralMsgIdException e) { } catch (PgpGeneralMsgIdException e) {
Log.e(Constants.TAG, "pgp msg id error", e);
return null; return null;
} }
@ -374,16 +370,36 @@ public class PgpKeyOperation {
} }
log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent); log.add(LogLevel.INFO, LogType.MSG_MF_SUBKEY_NEW, indent);
PGPSecretKey sKey = createKey(add.mAlgorithm, add.mKeysize, passphrase, false);
// generate a new secret key (privkey only for now)
PGPKeyPair keyPair = createKey(add.mAlgorithm, add.mKeysize);
// add subkey binding signature (making this a sub rather than master key)
PGPPublicKey pKey = keyPair.getPublicKey();
PGPSignature cert = generateSubkeyBindingSignature(
masterPublicKey, masterPrivateKey, keyPair.getPrivateKey(), pKey,
add.mFlags, add.mExpiry);
pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
PGPSecretKey sKey; {
// define hashing and signing algos
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder()
.build().get(HashAlgorithmTags.SHA1);
// Build key encrypter and decrypter based on passphrase
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build("".toCharArray());
sKey = new PGPSecretKey(keyPair.getPrivateKey(), pKey,
sha1Calc, false, keyEncryptor);
}
log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID, log.add(LogLevel.DEBUG, LogType.MSG_MF_SUBKEY_NEW_ID,
indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID())); indent+1, PgpKeyHelper.convertKeyIdToHex(sKey.getKeyID()));
PGPPublicKey pKey = sKey.getPublicKey(); sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
PGPSignature cert = generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey,
sKey, pKey, add.mFlags, add.mExpiry, passphrase);
pKey = PGPPublicKey.addCertification(pKey, cert);
sKey = PGPSecretKey.replacePublicKey(sKey, pKey);
sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
} catch (PgpGeneralMsgIdException e) { } catch (PgpGeneralMsgIdException e) {
return null; return null;
} }
@ -478,6 +494,18 @@ public class PgpKeyOperation {
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey, PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
PGPSecretKey sKey, PGPPublicKey pKey, int flags, Long expiry, String passphrase) PGPSecretKey sKey, PGPPublicKey pKey, int flags, Long expiry, String passphrase)
throws IOException, PGPException, SignatureException { throws IOException, PGPException, SignatureException {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
passphrase.toCharArray());
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
return generateSubkeyBindingSignature(masterPublicKey, masterPrivateKey, subPrivateKey,
pKey, flags, expiry);
}
private static PGPSignature generateSubkeyBindingSignature(
PGPPublicKey masterPublicKey, PGPPrivateKey masterPrivateKey,
PGPPrivateKey subPrivateKey, PGPPublicKey pKey, int flags, Long expiry)
throws IOException, PGPException, SignatureException {
// date for signing // date for signing
Date todayDate = new Date(); Date todayDate = new Date();
@ -485,12 +513,6 @@ public class PgpKeyOperation {
// If this key can sign, we need a primary key binding signature // If this key can sign, we need a primary key binding signature
if ((flags & KeyFlags.SIGN_DATA) != 0) { if ((flags & KeyFlags.SIGN_DATA) != 0) {
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
passphrase.toCharArray());
PGPPrivateKey subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
// cross-certify signing keys // cross-certify signing keys
PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator(); PGPSignatureSubpacketGenerator subHashedPacketsGen = new PGPSignatureSubpacketGenerator();
subHashedPacketsGen.setSignatureCreationTime(false, todayDate); subHashedPacketsGen.setSignatureCreationTime(false, todayDate);

View File

@ -27,8 +27,10 @@ import android.support.v4.app.FragmentManager;
import com.devspark.appmsg.AppMsg; import com.devspark.appmsg.AppMsg;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment; import org.sufficientlysecure.keychain.ui.dialog.ProgressDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
public class KeychainIntentServiceHandler extends Handler { public class KeychainIntentServiceHandler extends Handler {
@ -126,6 +128,7 @@ public class KeychainIntentServiceHandler extends Handler {
break; break;
default: default:
Log.e(Constants.TAG, "unknown handler message!");
break; break;
} }
} }