@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.Id;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
|
||||
import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.util.IterableIterator;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Primes;
|
||||
import org.sufficientlysecure.keychain.util.ProgressDialogUpdater;
|
||||
@@ -46,6 +47,8 @@ import java.security.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class PgpKeyOperation {
|
||||
@@ -198,7 +201,7 @@ public class PgpKeyOperation {
|
||||
|
||||
public void buildSecretKey(ArrayList<String> userIds, ArrayList<PGPSecretKey> keys,
|
||||
ArrayList<Integer> keysUsages, ArrayList<GregorianCalendar> keysExpiryDates,
|
||||
long masterKeyId, String oldPassPhrase,
|
||||
PGPPublicKey oldPublicKey, String oldPassPhrase,
|
||||
String newPassPhrase) throws PgpGeneralException, NoSuchProviderException,
|
||||
PGPException, NoSuchAlgorithmException, SignatureException, IOException {
|
||||
|
||||
@@ -215,131 +218,166 @@ public class PgpKeyOperation {
|
||||
|
||||
updateProgress(R.string.progress_preparing_master_key, 10, 100);
|
||||
|
||||
int usageId = keysUsages.get(0);
|
||||
boolean canSign =
|
||||
(usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
boolean canEncrypt =
|
||||
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
// prepare keyring generator with given master public and secret key
|
||||
PGPKeyRingGenerator keyGen;
|
||||
PGPPublicKey masterPublicKey; {
|
||||
|
||||
String mainUserId = userIds.get(0);
|
||||
String mainUserId = userIds.get(0);
|
||||
|
||||
PGPSecretKey masterKey = keys.get(0);
|
||||
// prepare the master key pair
|
||||
PGPKeyPair masterKeyPair; {
|
||||
|
||||
// this removes all userIds and certifications previously attached to the masterPublicKey
|
||||
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
||||
PGPPublicKey masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
|
||||
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
|
||||
PGPSecretKey masterKey = keys.get(0);
|
||||
|
||||
// already done by code above:
|
||||
// PGPPublicKey masterPublicKey = masterKey.getPublicKey();
|
||||
// // Somehow, the PGPPublicKey already has an empty certification attached to it when the
|
||||
// // keyRing is generated the first time, we remove that when it exists, before adding the
|
||||
// new
|
||||
// // ones
|
||||
// PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
|
||||
// "");
|
||||
// if (masterPublicKeyRmCert != null) {
|
||||
// masterPublicKey = masterPublicKeyRmCert;
|
||||
// }
|
||||
// this removes all userIds and certifications previously attached to the masterPublicKey
|
||||
PGPPublicKey tmpKey = masterKey.getPublicKey();
|
||||
masterPublicKey = new PGPPublicKey(tmpKey.getAlgorithm(),
|
||||
tmpKey.getKey(new BouncyCastleProvider()), tmpKey.getCreationTime());
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
|
||||
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
|
||||
// already done by code above:
|
||||
// PGPPublicKey masterPublicKey = masterKey.getPublicKey();
|
||||
// // Somehow, the PGPPublicKey already has an empty certification attached to it when the
|
||||
// // keyRing is generated the first time, we remove that when it exists, before adding the
|
||||
// new
|
||||
// // ones
|
||||
// PGPPublicKey masterPublicKeyRmCert = PGPPublicKey.removeCertification(masterPublicKey,
|
||||
// "");
|
||||
// if (masterPublicKeyRmCert != null) {
|
||||
// masterPublicKey = masterPublicKeyRmCert;
|
||||
// }
|
||||
|
||||
updateProgress(R.string.progress_certifying_master_key, 20, 100);
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(oldPassPhrase.toCharArray());
|
||||
PGPPrivateKey masterPrivateKey = masterKey.extractPrivateKey(keyDecryptor);
|
||||
|
||||
// TODO: if we are editing a key, keep old certs, don't remake certs we don't have to.
|
||||
updateProgress(R.string.progress_certifying_master_key, 20, 100);
|
||||
|
||||
for (String userId : userIds) {
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
// re-add old certificates, or create new ones for new uids
|
||||
for (String userId : userIds) {
|
||||
// re-add certs for this uid, take a note if self-signed cert is in there
|
||||
boolean foundSelfSign = false;
|
||||
Iterator<PGPSignature> it = tmpKey.getSignaturesForID(userId);
|
||||
if(it != null) for(PGPSignature sig : new IterableIterator<PGPSignature>(it)) {
|
||||
if(sig.getKeyID() == masterPublicKey.getKeyID()) {
|
||||
// already have a self sign? skip this other one, then.
|
||||
// note: PGPKeyRingGenerator adds one cert for the main user id, which
|
||||
// will lead to duplicates. unfortunately, if we add any other here
|
||||
// first, that will change the main user id order...
|
||||
if(foundSelfSign)
|
||||
continue;
|
||||
foundSelfSign = true;
|
||||
}
|
||||
Log.d(Constants.TAG, "adding old sig for " + userId + " from "
|
||||
+ PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()));
|
||||
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, sig);
|
||||
}
|
||||
|
||||
sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
|
||||
// there was an old self-signed certificate for this uid
|
||||
if(foundSelfSign)
|
||||
continue;
|
||||
|
||||
PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
|
||||
Log.d(Constants.TAG, "generating self-signed cert for " + userId);
|
||||
|
||||
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
|
||||
}
|
||||
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterPublicKey.getAlgorithm(), HashAlgorithmTags.SHA1)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
|
||||
|
||||
PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
|
||||
sGen.init(PGPSignature.POSITIVE_CERTIFICATION, masterPrivateKey);
|
||||
|
||||
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
PGPSignature certification = sGen.generateCertification(userId, masterPublicKey);
|
||||
|
||||
int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
|
||||
if (canEncrypt) {
|
||||
keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
|
||||
}
|
||||
hashedPacketsGen.setKeyFlags(true, keyFlags);
|
||||
masterPublicKey = PGPPublicKey.addCertification(masterPublicKey, userId, certification);
|
||||
}
|
||||
|
||||
hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
|
||||
|
||||
if (keysExpiryDates.get(0) != null) {
|
||||
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
creationDate.setTime(masterPublicKey.getCreationTime());
|
||||
GregorianCalendar expiryDate = keysExpiryDates.get(0);
|
||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||
long numDays =
|
||||
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
|
||||
}
|
||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||
} else {
|
||||
//do this explicitly, although since we're rebuilding,
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||
//this happens anyway
|
||||
|
||||
PGPSignatureSubpacketGenerator hashedPacketsGen;
|
||||
PGPSignatureSubpacketGenerator unhashedPacketsGen; {
|
||||
|
||||
hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
|
||||
int usageId = keysUsages.get(0);
|
||||
boolean canEncrypt =
|
||||
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
|
||||
int keyFlags = KeyFlags.CERTIFY_OTHER | KeyFlags.SIGN_DATA;
|
||||
if (canEncrypt) {
|
||||
keyFlags |= KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE;
|
||||
}
|
||||
hashedPacketsGen.setKeyFlags(true, keyFlags);
|
||||
|
||||
hashedPacketsGen.setPreferredSymmetricAlgorithms(true, PREFERRED_SYMMETRIC_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredHashAlgorithms(true, PREFERRED_HASH_ALGORITHMS);
|
||||
hashedPacketsGen.setPreferredCompressionAlgorithms(true, PREFERRED_COMPRESSION_ALGORITHMS);
|
||||
|
||||
if (keysExpiryDates.get(0) != null) {
|
||||
GregorianCalendar creationDate = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
|
||||
creationDate.setTime(masterPublicKey.getCreationTime());
|
||||
GregorianCalendar expiryDate = keysExpiryDates.get(0);
|
||||
//note that the below, (a/c) - (b/c) is *not* the same as (a - b) /c
|
||||
//here we purposefully ignore partial days in each date - long type has no fractional part!
|
||||
long numDays =
|
||||
(expiryDate.getTimeInMillis() / 86400000) - (creationDate.getTimeInMillis() / 86400000);
|
||||
if (numDays <= 0) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_expiry_must_come_after_creation));
|
||||
}
|
||||
hashedPacketsGen.setKeyExpirationTime(false, numDays * 86400);
|
||||
} else {
|
||||
//do this explicitly, although since we're rebuilding,
|
||||
hashedPacketsGen.setKeyExpirationTime(false, 0);
|
||||
//this happens anyway
|
||||
}
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_building_master_key, 30, 100);
|
||||
|
||||
// define hashing and signing algos
|
||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
|
||||
HashAlgorithmTags.SHA1);
|
||||
PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
|
||||
|
||||
// Build key encrypter based on passphrase
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
PGPEncryptedData.CAST5, sha1Calc)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
newPassPhrase.toCharArray());
|
||||
|
||||
keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
|
||||
masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
|
||||
unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
|
||||
|
||||
}
|
||||
|
||||
updateProgress(R.string.progress_building_master_key, 30, 100);
|
||||
|
||||
// define hashing and signing algos
|
||||
PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build().get(
|
||||
HashAlgorithmTags.SHA1);
|
||||
PGPContentSignerBuilder certificationSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
masterKeyPair.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
|
||||
|
||||
// Build key encrypter based on passphrase
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
PGPEncryptedData.CAST5, sha1Calc)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
newPassPhrase.toCharArray());
|
||||
|
||||
PGPKeyRingGenerator keyGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION,
|
||||
masterKeyPair, mainUserId, sha1Calc, hashedPacketsGen.generate(),
|
||||
unhashedPacketsGen.generate(), certificationSignerBuilder, keyEncryptor);
|
||||
|
||||
updateProgress(R.string.progress_adding_sub_keys, 40, 100);
|
||||
|
||||
for (int i = 1; i < keys.size(); ++i) {
|
||||
updateProgress(40 + 50 * (i - 1) / (keys.size() - 1), 100);
|
||||
updateProgress(40 + 40 * (i - 1) / (keys.size() - 1), 100);
|
||||
|
||||
PGPSecretKey subKey = keys.get(i);
|
||||
PGPPublicKey subPublicKey = subKey.getPublicKey();
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor2 = new JcePBESecretKeyDecryptorBuilder()
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(
|
||||
oldPassPhrase.toCharArray());
|
||||
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor2);
|
||||
PGPPrivateKey subPrivateKey = subKey.extractPrivateKey(keyDecryptor);
|
||||
|
||||
// TODO: now used without algorithm and creation time?! (APG 1)
|
||||
PGPKeyPair subKeyPair = new PGPKeyPair(subPublicKey, subPrivateKey);
|
||||
|
||||
hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
PGPSignatureSubpacketGenerator unhashedPacketsGen = new PGPSignatureSubpacketGenerator();
|
||||
|
||||
keyFlags = 0;
|
||||
int keyFlags = 0;
|
||||
|
||||
usageId = keysUsages.get(i);
|
||||
canSign =
|
||||
int usageId = keysUsages.get(i);
|
||||
boolean canSign =
|
||||
(usageId == Id.choice.usage.sign_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
canEncrypt =
|
||||
boolean canEncrypt =
|
||||
(usageId == Id.choice.usage.encrypt_only || usageId == Id.choice.usage.sign_and_encrypt);
|
||||
if (canSign) {
|
||||
Date todayDate = new Date(); //both sig times the same
|
||||
@@ -388,53 +426,99 @@ public class PgpKeyOperation {
|
||||
PGPSecretKeyRing secretKeyRing = keyGen.generateSecretKeyRing();
|
||||
PGPPublicKeyRing publicKeyRing = keyGen.generatePublicKeyRing();
|
||||
|
||||
updateProgress(R.string.progress_re_adding_certs, 80, 100);
|
||||
|
||||
// re-add certificates from old public key
|
||||
// TODO: this only takes care of user id certificates, what about others?
|
||||
PGPPublicKey pubkey = publicKeyRing.getPublicKey();
|
||||
for(String uid : new IterableIterator<String>(pubkey.getUserIDs())) {
|
||||
for(PGPSignature sig : new IterableIterator<PGPSignature>(oldPublicKey.getSignaturesForID(uid), true)) {
|
||||
// but skip self certificates
|
||||
if(sig.getKeyID() == pubkey.getKeyID())
|
||||
continue;
|
||||
pubkey = PGPPublicKey.addCertification(pubkey, uid, sig);
|
||||
}
|
||||
}
|
||||
publicKeyRing = PGPPublicKeyRing.insertPublicKey(publicKeyRing, pubkey);
|
||||
|
||||
updateProgress(R.string.progress_saving_key_ring, 90, 100);
|
||||
|
||||
/* additional handy debug info
|
||||
Log.d(Constants.TAG, " ------- in private key -------");
|
||||
for(String uid : new IterableIterator<String>(secretKeyRing.getPublicKey().getUserIDs())) {
|
||||
for(PGPSignature sig : new IterableIterator<PGPSignature>(secretKeyRing.getPublicKey().getSignaturesForID(uid))) {
|
||||
Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
|
||||
}
|
||||
}
|
||||
Log.d(Constants.TAG, " ------- in public key -------");
|
||||
for(String uid : new IterableIterator<String>(publicKeyRing.getPublicKey().getUserIDs())) {
|
||||
for(PGPSignature sig : new IterableIterator<PGPSignature>(publicKeyRing.getPublicKey().getSignaturesForID(uid))) {
|
||||
Log.d(Constants.TAG, "sig: " + PgpKeyHelper.convertKeyIdToHex(sig.getKeyID()) + " for " + uid);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
ProviderHelper.saveKeyRing(mContext, secretKeyRing);
|
||||
ProviderHelper.saveKeyRing(mContext, publicKeyRing);
|
||||
|
||||
updateProgress(R.string.progress_done, 100, 100);
|
||||
}
|
||||
|
||||
public PGPPublicKeyRing certifyKey(long masterKeyId, long pubKeyId, String passphrase)
|
||||
/**
|
||||
* Certify the given pubkeyid with the given masterkeyid.
|
||||
*
|
||||
* @param masterKeyId Certifying key, must be available as secret key
|
||||
* @param pubKeyId ID of public key to certify
|
||||
* @param userIds User IDs to certify, must not be null or empty
|
||||
* @param passphrase Passphrase of the secret key
|
||||
* @return A keyring with added certifications
|
||||
*/
|
||||
public PGPPublicKeyRing certifyKey(long masterKeyId, long pubKeyId, List<String> userIds, String passphrase)
|
||||
throws PgpGeneralException, NoSuchAlgorithmException, NoSuchProviderException,
|
||||
PGPException, SignatureException {
|
||||
if (passphrase == null) {
|
||||
throw new PgpGeneralException("Unable to obtain passphrase");
|
||||
} else {
|
||||
|
||||
// create a signatureGenerator from the supplied masterKeyId and passphrase
|
||||
PGPSignatureGenerator signatureGenerator; {
|
||||
|
||||
PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId);
|
||||
if (certificationKey == null) {
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
||||
}
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||
PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor);
|
||||
if (signaturePrivateKey == null) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
||||
}
|
||||
|
||||
// TODO: SHA256 fixed?
|
||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
|
||||
signatureGenerator = new PGPSignatureGenerator(contentSignerBuilder);
|
||||
signatureGenerator.init(PGPSignature.DEFAULT_CERTIFICATION, signaturePrivateKey);
|
||||
}
|
||||
|
||||
{ // supply signatureGenerator with a SubpacketVector
|
||||
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
|
||||
PGPSignatureSubpacketVector packetVector = spGen.generate();
|
||||
signatureGenerator.setHashedSubpackets(packetVector);
|
||||
}
|
||||
|
||||
// fetch public key ring, add the certification and return it
|
||||
PGPPublicKeyRing pubring = ProviderHelper
|
||||
.getPGPPublicKeyRingByKeyId(mContext, pubKeyId);
|
||||
|
||||
PGPSecretKey certificationKey = PgpKeyHelper.getCertificationKey(mContext, masterKeyId);
|
||||
if (certificationKey == null) {
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_signature_failed));
|
||||
PGPPublicKey signedKey = pubring.getPublicKey(pubKeyId);
|
||||
for(String userId : new IterableIterator<String>(userIds.iterator())) {
|
||||
PGPSignature sig = signatureGenerator.generateCertification(userId, signedKey);
|
||||
signedKey = PGPPublicKey.addCertification(signedKey, userId, sig);
|
||||
}
|
||||
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passphrase.toCharArray());
|
||||
PGPPrivateKey signaturePrivateKey = certificationKey.extractPrivateKey(keyDecryptor);
|
||||
if (signaturePrivateKey == null) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_could_not_extract_private_key));
|
||||
}
|
||||
|
||||
// TODO: SHA256 fixed?
|
||||
JcaPGPContentSignerBuilder contentSignerBuilder = new JcaPGPContentSignerBuilder(
|
||||
certificationKey.getPublicKey().getAlgorithm(), PGPUtil.SHA256)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
|
||||
|
||||
PGPSignatureGenerator signatureGenerator = new PGPSignatureGenerator(
|
||||
contentSignerBuilder);
|
||||
|
||||
signatureGenerator.init(PGPSignature.DIRECT_KEY, signaturePrivateKey);
|
||||
|
||||
PGPSignatureSubpacketGenerator spGen = new PGPSignatureSubpacketGenerator();
|
||||
|
||||
PGPSignatureSubpacketVector packetVector = spGen.generate();
|
||||
signatureGenerator.setHashedSubpackets(packetVector);
|
||||
|
||||
PGPPublicKey signedKey = PGPPublicKey.addCertification(pubring.getPublicKey(pubKeyId),
|
||||
signatureGenerator.generate());
|
||||
pubring = PGPPublicKeyRing.insertPublicKey(pubring, signedKey);
|
||||
|
||||
return pubring;
|
||||
|
||||
Reference in New Issue
Block a user