mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-12-25 00:18:51 -05:00
fix subkey addition
This commit is contained in:
parent
858be93f3d
commit
9fb92c8642
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user