mirror of
https://github.com/moparisthebest/open-keychain
synced 2024-11-30 12:32:17 -05:00
create new keys without lots of extra certification
This commit is contained in:
commit
af5e01db8e
@ -80,9 +80,27 @@ public class PgpConversionHelper {
|
||||
* @return
|
||||
*/
|
||||
public static PGPSecretKey BytesToPGPSecretKey(byte[] keyBytes) {
|
||||
PGPSecretKey key = BytesToPGPSecretKeyList(keyBytes).get(0);
|
||||
PGPObjectFactory factory = new PGPObjectFactory(keyBytes);
|
||||
Object obj = null;
|
||||
try {
|
||||
obj = factory.nextObject();
|
||||
} catch (IOException e) {
|
||||
Log.e(Constants.TAG, "Error while converting to PGPSecretKey!", e);
|
||||
}
|
||||
PGPSecretKey secKey = null;
|
||||
if(obj instanceof PGPSecretKey) {
|
||||
if ((secKey = (PGPSecretKey)obj ) == null) {
|
||||
Log.e(Constants.TAG, "No keys given!");
|
||||
}
|
||||
} else if(obj instanceof PGPSecretKeyRing) { //master keys are sent as keyrings
|
||||
PGPSecretKeyRing keyRing = null;
|
||||
if ((keyRing = (PGPSecretKeyRing)obj) == null) {
|
||||
Log.e(Constants.TAG, "No keys given!");
|
||||
}
|
||||
secKey = keyRing.getSecretKey();
|
||||
}
|
||||
|
||||
return key;
|
||||
return secKey;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -103,15 +103,12 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key
|
||||
* when this key is the new masterkey. If a masterkey is supplied in the parameters
|
||||
* PGPSecretKeyRing contains the masterkey and the new key as a subkey (certified by the
|
||||
* masterkey).
|
||||
* Creates new secret key.
|
||||
*
|
||||
* @param algorithmChoice
|
||||
* @param keySize
|
||||
* @param passPhrase
|
||||
* @param masterSecretKey
|
||||
* @param isMasterKey
|
||||
* @return
|
||||
* @throws NoSuchAlgorithmException
|
||||
* @throws PGPException
|
||||
@ -119,9 +116,11 @@ public class PgpKeyOperation {
|
||||
* @throws PgpGeneralException
|
||||
* @throws InvalidAlgorithmParameterException
|
||||
*/
|
||||
public PGPSecretKeyRing createKey(int algorithmChoice, int keySize, String passPhrase,
|
||||
PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, PGPException,
|
||||
NoSuchProviderException, PgpGeneralException, InvalidAlgorithmParameterException {
|
||||
|
||||
// TODO: key flags?
|
||||
public PGPSecretKey createKey(int algorithmChoice, int keySize, String passPhrase,
|
||||
boolean isMasterKey) throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
|
||||
PgpGeneralException, InvalidAlgorithmParameterException {
|
||||
|
||||
if (keySize < 512) {
|
||||
throw new PgpGeneralException(mContext.getString(R.string.error_key_size_minimum512bit));
|
||||
@ -143,7 +142,7 @@ public class PgpKeyOperation {
|
||||
}
|
||||
|
||||
case Id.choice.algorithm.elgamal: {
|
||||
if (masterSecretKey == null) {
|
||||
if (isMasterKey) {
|
||||
throw new PgpGeneralException(
|
||||
mContext.getString(R.string.error_master_key_must_not_be_el_gamal));
|
||||
}
|
||||
@ -183,36 +182,11 @@ public class PgpKeyOperation {
|
||||
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
|
||||
PGPEncryptedData.CAST5, sha1Calc)
|
||||
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray());
|
||||
PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder().setProvider(
|
||||
Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray());
|
||||
|
||||
PGPKeyRingGenerator ringGen = null;
|
||||
PGPContentSignerBuilder certificationSignerBuilder = null;
|
||||
if (masterSecretKey == null) {
|
||||
certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair.getPublicKey()
|
||||
.getAlgorithm(), HashAlgorithmTags.SHA1);
|
||||
PGPSecretKey secKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
|
||||
sha1Calc, isMasterKey, keyEncryptor);
|
||||
|
||||
// build keyRing with only this one master key in it!
|
||||
ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, keyPair, "",
|
||||
sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
|
||||
} else {
|
||||
PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();
|
||||
PGPPrivateKey masterPrivateKey = masterSecretKey.extractPrivateKey(keyDecryptor);
|
||||
PGPKeyPair masterKeyPair = new PGPKeyPair(masterPublicKey, masterPrivateKey);
|
||||
|
||||
certificationSignerBuilder = new JcaPGPContentSignerBuilder(masterKeyPair
|
||||
.getPublicKey().getAlgorithm(), HashAlgorithmTags.SHA1);
|
||||
|
||||
// build keyRing with master key and new key as subkey (certified by masterkey)
|
||||
ringGen = new PGPKeyRingGenerator(PGPSignature.POSITIVE_CERTIFICATION, masterKeyPair,
|
||||
"", sha1Calc, null, null, certificationSignerBuilder, keyEncryptor);
|
||||
|
||||
ringGen.addSubKey(keyPair);
|
||||
}
|
||||
|
||||
PGPSecretKeyRing secKeyRing = ringGen.generateSecretKeyRing();
|
||||
|
||||
return secKeyRing;
|
||||
return secKey;
|
||||
}
|
||||
|
||||
public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,
|
||||
|
@ -561,21 +561,17 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
int algorithm = data.getInt(GENERATE_KEY_ALGORITHM);
|
||||
String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
|
||||
int keysize = data.getInt(GENERATE_KEY_KEY_SIZE);
|
||||
PGPSecretKey masterKey = null;
|
||||
if (data.containsKey(GENERATE_KEY_MASTER_KEY)) {
|
||||
masterKey = PgpConversionHelper.BytesToPGPSecretKey(data
|
||||
.getByteArray(GENERATE_KEY_MASTER_KEY));
|
||||
}
|
||||
boolean masterKey = data.getBoolean(GENERATE_KEY_MASTER_KEY);
|
||||
|
||||
/* Operation */
|
||||
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
|
||||
PGPSecretKeyRing newKeyRing = keyOperations.createKey(algorithm, keysize,
|
||||
PGPSecretKey newKey = keyOperations.createKey(algorithm, keysize,
|
||||
passphrase, masterKey);
|
||||
|
||||
/* Output */
|
||||
Bundle resultData = new Bundle();
|
||||
resultData.putByteArray(RESULT_NEW_KEY,
|
||||
PgpConversionHelper.PGPSecretKeyRingToBytes(newKeyRing));
|
||||
PgpConversionHelper.PGPSecretKeyToBytes(newKey));
|
||||
|
||||
OtherHelper.logDebugBundle(resultData, "resultData");
|
||||
|
||||
@ -592,18 +588,21 @@ public class KeychainIntentService extends IntentService implements ProgressDial
|
||||
/* Operation */
|
||||
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
|
||||
|
||||
PGPSecretKeyRing masterKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
|
||||
4096, passphrase, null);
|
||||
PGPSecretKey masterKey = keyOperations.createKey(Id.choice.algorithm.rsa,
|
||||
4096, passphrase, true);
|
||||
|
||||
PGPSecretKeyRing subKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa,
|
||||
4096, passphrase, masterKeyRing.getSecretKey());
|
||||
PGPSecretKey subKey = keyOperations.createKey(Id.choice.algorithm.rsa,
|
||||
4096, passphrase, false);
|
||||
|
||||
// TODO: default to one master for cert, one sub for encrypt and one sub
|
||||
// for sign
|
||||
|
||||
/* Output */
|
||||
Bundle resultData = new Bundle();
|
||||
resultData.putByteArray(RESULT_NEW_KEY,
|
||||
PgpConversionHelper.PGPSecretKeyRingToBytes(masterKeyRing));
|
||||
PgpConversionHelper.PGPSecretKeyToBytes(masterKey));
|
||||
resultData.putByteArray(RESULT_NEW_KEY2,
|
||||
PgpConversionHelper.PGPSecretKeyRingToBytes(subKeyRing));
|
||||
PgpConversionHelper.PGPSecretKeyToBytes(subKey));
|
||||
|
||||
OtherHelper.logDebugBundle(resultData, "resultData");
|
||||
|
||||
|
@ -193,25 +193,20 @@ public class EditKeyActivity extends SherlockFragmentActivity {
|
||||
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
|
||||
// get new key from data bundle returned from service
|
||||
Bundle data = message.getData();
|
||||
PGPSecretKeyRing masterKeyRing = (PGPSecretKeyRing) PgpConversionHelper
|
||||
.BytesToPGPKeyRing(data
|
||||
PGPSecretKey masterKey = (PGPSecretKey) PgpConversionHelper
|
||||
.BytesToPGPSecretKey(data
|
||||
.getByteArray(KeychainIntentService.RESULT_NEW_KEY));
|
||||
PGPSecretKeyRing subKeyRing = (PGPSecretKeyRing) PgpConversionHelper
|
||||
.BytesToPGPKeyRing(data
|
||||
PGPSecretKey subKey = (PGPSecretKey) PgpConversionHelper
|
||||
.BytesToPGPSecretKey(data
|
||||
.getByteArray(KeychainIntentService.RESULT_NEW_KEY2));
|
||||
|
||||
// add master key
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSecretKey> masterIt = masterKeyRing.getSecretKeys();
|
||||
mKeys.add(masterIt.next());
|
||||
mKeysUsages.add(Id.choice.usage.sign_only);
|
||||
mKeys.add(masterKey);
|
||||
mKeysUsages.add(Id.choice.usage.sign_only); //TODO: get from key flags
|
||||
|
||||
// add sub key
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSecretKey> subIt = subKeyRing.getSecretKeys();
|
||||
subIt.next(); // masterkey
|
||||
mKeys.add(subIt.next());
|
||||
mKeysUsages.add(Id.choice.usage.encrypt_only);
|
||||
mKeys.add(subKey);
|
||||
mKeysUsages.add(Id.choice.usage.encrypt_only); //TODO: get from key flags
|
||||
|
||||
buildLayout();
|
||||
}
|
||||
|
@ -290,18 +290,19 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
|
||||
// fill values for this action
|
||||
Bundle data = new Bundle();
|
||||
Boolean isMasterKey;
|
||||
|
||||
String passPhrase;
|
||||
if (mEditors.getChildCount() > 0) {
|
||||
PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
|
||||
passPhrase = PassphraseCacheService
|
||||
.getCachedPassphrase(mActivity, masterKey.getKeyID());
|
||||
|
||||
data.putByteArray(KeychainIntentService.GENERATE_KEY_MASTER_KEY,
|
||||
PgpConversionHelper.PGPSecretKeyToBytes(masterKey));
|
||||
isMasterKey = false;
|
||||
} else {
|
||||
passPhrase = "";
|
||||
isMasterKey = true;
|
||||
}
|
||||
data.putBoolean(KeychainIntentService.GENERATE_KEY_MASTER_KEY, isMasterKey);
|
||||
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase);
|
||||
data.putInt(KeychainIntentService.GENERATE_KEY_ALGORITHM, mNewKeyAlgorithmChoice.getId());
|
||||
data.putInt(KeychainIntentService.GENERATE_KEY_KEY_SIZE, mNewKeySize);
|
||||
@ -322,11 +323,10 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
|
||||
// get new key from data bundle returned from service
|
||||
Bundle data = message.getData();
|
||||
PGPSecretKeyRing newKeyRing = (PGPSecretKeyRing) PgpConversionHelper
|
||||
.BytesToPGPKeyRing(data
|
||||
PGPSecretKey newKey = (PGPSecretKey) PgpConversionHelper
|
||||
.BytesToPGPSecretKey(data
|
||||
.getByteArray(KeychainIntentService.RESULT_NEW_KEY));
|
||||
|
||||
addGeneratedKeyToView(newKeyRing);
|
||||
addGeneratedKeyToView(newKey);
|
||||
}
|
||||
};
|
||||
};
|
||||
@ -341,27 +341,12 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
|
||||
mActivity.startService(intent);
|
||||
}
|
||||
|
||||
private void addGeneratedKeyToView(PGPSecretKeyRing newKeyRing) {
|
||||
boolean isMasterKey = (mEditors.getChildCount() == 0);
|
||||
|
||||
// take only the key from this ring
|
||||
PGPSecretKey newKey = null;
|
||||
@SuppressWarnings("unchecked")
|
||||
Iterator<PGPSecretKey> it = newKeyRing.getSecretKeys();
|
||||
|
||||
if (isMasterKey) {
|
||||
newKey = it.next();
|
||||
} else {
|
||||
// first one is the master key
|
||||
it.next();
|
||||
newKey = it.next();
|
||||
}
|
||||
|
||||
private void addGeneratedKeyToView(PGPSecretKey newKey) {
|
||||
// add view with new key
|
||||
KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item,
|
||||
mEditors, false);
|
||||
view.setEditorListener(SectionView.this);
|
||||
view.setValue(newKey, isMasterKey, -1);
|
||||
view.setValue(newKey, newKey.isMasterKey(), -1);
|
||||
mEditors.addView(view);
|
||||
SectionView.this.updateEditorsVisible();
|
||||
}
|
||||
|
@ -103,6 +103,15 @@ public class PGPObjectFactory
|
||||
{
|
||||
throw new IOException("can't create secret key object: " + e);
|
||||
}
|
||||
case PacketTags.SECRET_SUBKEY:
|
||||
try
|
||||
{
|
||||
return PGPSecretKeyRing.readSubkey(in, fingerPrintCalculator);
|
||||
}
|
||||
catch (PGPException e)
|
||||
{
|
||||
throw new IOException("processing error: " + e.getMessage());
|
||||
}
|
||||
case PacketTags.PUBLIC_KEY:
|
||||
return new PGPPublicKeyRing(in, fingerPrintCalculator);
|
||||
case PacketTags.PUBLIC_SUBKEY:
|
||||
|
@ -64,7 +64,7 @@ public class PGPSecretKey
|
||||
this(privKey, pubKey, checksumCalculator, false, keyEncryptor);
|
||||
}
|
||||
|
||||
PGPSecretKey(
|
||||
public PGPSecretKey(
|
||||
PGPPrivateKey privKey,
|
||||
PGPPublicKey pubKey,
|
||||
PGPDigestCalculator checksumCalculator,
|
||||
|
@ -477,4 +477,23 @@ public class PGPSecretKeyRing
|
||||
|
||||
return new PGPSecretKeyRing(keys, secRing.extraPubKeys);
|
||||
}
|
||||
|
||||
static PGPSecretKey readSubkey(BCPGInputStream in, KeyFingerPrintCalculator fingerPrintCalculator)
|
||||
throws IOException, PGPException
|
||||
{
|
||||
SecretSubkeyPacket sub = (SecretSubkeyPacket)in.readPacket();
|
||||
|
||||
//
|
||||
// ignore GPG comment packets if found.
|
||||
//
|
||||
while (in.nextPacketTag() == PacketTags.EXPERIMENTAL_2)
|
||||
{
|
||||
in.readPacket();
|
||||
}
|
||||
|
||||
TrustPacket subTrust = readOptionalTrustPacket(in);
|
||||
List sigList = readSignaturesAndTrust(in);
|
||||
|
||||
return new PGPSecretKey(sub, new PGPPublicKey(sub.getPublicKeyPacket(), subTrust, sigList, fingerPrintCalculator));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user