create new keys without lots of extra certification

This commit is contained in:
Ashley Hughes 2014-02-01 17:01:03 +00:00
commit af5e01db8e
8 changed files with 89 additions and 90 deletions

View File

@ -80,9 +80,27 @@ public class PgpConversionHelper {
* @return * @return
*/ */
public static PGPSecretKey BytesToPGPSecretKey(byte[] keyBytes) { 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;
} }
/** /**

View File

@ -103,15 +103,12 @@ public class PgpKeyOperation {
} }
/** /**
* Creates new secret key. The returned PGPSecretKeyRing contains only one newly generated key * Creates new secret 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).
* *
* @param algorithmChoice * @param algorithmChoice
* @param keySize * @param keySize
* @param passPhrase * @param passPhrase
* @param masterSecretKey * @param isMasterKey
* @return * @return
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
* @throws PGPException * @throws PGPException
@ -119,9 +116,11 @@ public class PgpKeyOperation {
* @throws PgpGeneralException * @throws PgpGeneralException
* @throws InvalidAlgorithmParameterException * @throws InvalidAlgorithmParameterException
*/ */
public PGPSecretKeyRing createKey(int algorithmChoice, int keySize, String passPhrase,
PGPSecretKey masterSecretKey) throws NoSuchAlgorithmException, PGPException, // TODO: key flags?
NoSuchProviderException, PgpGeneralException, InvalidAlgorithmParameterException { public PGPSecretKey createKey(int algorithmChoice, int keySize, String passPhrase,
boolean isMasterKey) throws NoSuchAlgorithmException, PGPException, NoSuchProviderException,
PgpGeneralException, InvalidAlgorithmParameterException {
if (keySize < 512) { if (keySize < 512) {
throw new PgpGeneralException(mContext.getString(R.string.error_key_size_minimum512bit)); throw new PgpGeneralException(mContext.getString(R.string.error_key_size_minimum512bit));
@ -143,7 +142,7 @@ public class PgpKeyOperation {
} }
case Id.choice.algorithm.elgamal: { case Id.choice.algorithm.elgamal: {
if (masterSecretKey == null) { if (isMasterKey) {
throw new PgpGeneralException( throw new PgpGeneralException(
mContext.getString(R.string.error_master_key_must_not_be_el_gamal)); mContext.getString(R.string.error_master_key_must_not_be_el_gamal));
} }
@ -183,36 +182,11 @@ public class PgpKeyOperation {
PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder( PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
PGPEncryptedData.CAST5, sha1Calc) PGPEncryptedData.CAST5, sha1Calc)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(passPhrase.toCharArray()); .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; PGPSecretKey secKey = new PGPSecretKey(keyPair.getPrivateKey(), keyPair.getPublicKey(),
PGPContentSignerBuilder certificationSignerBuilder = null; sha1Calc, isMasterKey, keyEncryptor);
if (masterSecretKey == null) {
certificationSignerBuilder = new JcaPGPContentSignerBuilder(keyPair.getPublicKey()
.getAlgorithm(), HashAlgorithmTags.SHA1);
// build keyRing with only this one master key in it! return secKey;
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;
} }
public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase, public void changeSecretKeyPassphrase(PGPSecretKeyRing keyRing, String oldPassPhrase,

View File

@ -561,21 +561,17 @@ public class KeychainIntentService extends IntentService implements ProgressDial
int algorithm = data.getInt(GENERATE_KEY_ALGORITHM); int algorithm = data.getInt(GENERATE_KEY_ALGORITHM);
String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE); String passphrase = data.getString(GENERATE_KEY_SYMMETRIC_PASSPHRASE);
int keysize = data.getInt(GENERATE_KEY_KEY_SIZE); int keysize = data.getInt(GENERATE_KEY_KEY_SIZE);
PGPSecretKey masterKey = null; boolean masterKey = data.getBoolean(GENERATE_KEY_MASTER_KEY);
if (data.containsKey(GENERATE_KEY_MASTER_KEY)) {
masterKey = PgpConversionHelper.BytesToPGPSecretKey(data
.getByteArray(GENERATE_KEY_MASTER_KEY));
}
/* Operation */ /* Operation */
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this); PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
PGPSecretKeyRing newKeyRing = keyOperations.createKey(algorithm, keysize, PGPSecretKey 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,
PgpConversionHelper.PGPSecretKeyRingToBytes(newKeyRing)); PgpConversionHelper.PGPSecretKeyToBytes(newKey));
OtherHelper.logDebugBundle(resultData, "resultData"); OtherHelper.logDebugBundle(resultData, "resultData");
@ -592,18 +588,21 @@ public class KeychainIntentService extends IntentService implements ProgressDial
/* Operation */ /* Operation */
PgpKeyOperation keyOperations = new PgpKeyOperation(this, this); PgpKeyOperation keyOperations = new PgpKeyOperation(this, this);
PGPSecretKeyRing masterKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa, PGPSecretKey masterKey = keyOperations.createKey(Id.choice.algorithm.rsa,
4096, passphrase, null); 4096, passphrase, true);
PGPSecretKeyRing subKeyRing = keyOperations.createKey(Id.choice.algorithm.rsa, PGPSecretKey subKey = keyOperations.createKey(Id.choice.algorithm.rsa,
4096, passphrase, masterKeyRing.getSecretKey()); 4096, passphrase, false);
// TODO: default to one master for cert, one sub for encrypt and one sub
// for sign
/* Output */ /* Output */
Bundle resultData = new Bundle(); Bundle resultData = new Bundle();
resultData.putByteArray(RESULT_NEW_KEY, resultData.putByteArray(RESULT_NEW_KEY,
PgpConversionHelper.PGPSecretKeyRingToBytes(masterKeyRing)); PgpConversionHelper.PGPSecretKeyToBytes(masterKey));
resultData.putByteArray(RESULT_NEW_KEY2, resultData.putByteArray(RESULT_NEW_KEY2,
PgpConversionHelper.PGPSecretKeyRingToBytes(subKeyRing)); PgpConversionHelper.PGPSecretKeyToBytes(subKey));
OtherHelper.logDebugBundle(resultData, "resultData"); OtherHelper.logDebugBundle(resultData, "resultData");

View File

@ -193,25 +193,20 @@ public class EditKeyActivity extends SherlockFragmentActivity {
if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
// get new key from data bundle returned from service // get new key from data bundle returned from service
Bundle data = message.getData(); Bundle data = message.getData();
PGPSecretKeyRing masterKeyRing = (PGPSecretKeyRing) PgpConversionHelper PGPSecretKey masterKey = (PGPSecretKey) PgpConversionHelper
.BytesToPGPKeyRing(data .BytesToPGPSecretKey(data
.getByteArray(KeychainIntentService.RESULT_NEW_KEY)); .getByteArray(KeychainIntentService.RESULT_NEW_KEY));
PGPSecretKeyRing subKeyRing = (PGPSecretKeyRing) PgpConversionHelper PGPSecretKey subKey = (PGPSecretKey) PgpConversionHelper
.BytesToPGPKeyRing(data .BytesToPGPSecretKey(data
.getByteArray(KeychainIntentService.RESULT_NEW_KEY2)); .getByteArray(KeychainIntentService.RESULT_NEW_KEY2));
// add master key // add master key
@SuppressWarnings("unchecked") mKeys.add(masterKey);
Iterator<PGPSecretKey> masterIt = masterKeyRing.getSecretKeys(); mKeysUsages.add(Id.choice.usage.sign_only); //TODO: get from key flags
mKeys.add(masterIt.next());
mKeysUsages.add(Id.choice.usage.sign_only);
// add sub key // add sub key
@SuppressWarnings("unchecked") mKeys.add(subKey);
Iterator<PGPSecretKey> subIt = subKeyRing.getSecretKeys(); mKeysUsages.add(Id.choice.usage.encrypt_only); //TODO: get from key flags
subIt.next(); // masterkey
mKeys.add(subIt.next());
mKeysUsages.add(Id.choice.usage.encrypt_only);
buildLayout(); buildLayout();
} }

View File

@ -290,18 +290,19 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
// fill values for this action // fill values for this action
Bundle data = new Bundle(); Bundle data = new Bundle();
Boolean isMasterKey;
String passPhrase; String passPhrase;
if (mEditors.getChildCount() > 0) { if (mEditors.getChildCount() > 0) {
PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue(); PGPSecretKey masterKey = ((KeyEditor) mEditors.getChildAt(0)).getValue();
passPhrase = PassphraseCacheService passPhrase = PassphraseCacheService
.getCachedPassphrase(mActivity, masterKey.getKeyID()); .getCachedPassphrase(mActivity, masterKey.getKeyID());
isMasterKey = false;
data.putByteArray(KeychainIntentService.GENERATE_KEY_MASTER_KEY,
PgpConversionHelper.PGPSecretKeyToBytes(masterKey));
} else { } else {
passPhrase = ""; passPhrase = "";
isMasterKey = true;
} }
data.putBoolean(KeychainIntentService.GENERATE_KEY_MASTER_KEY, isMasterKey);
data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase); data.putString(KeychainIntentService.GENERATE_KEY_SYMMETRIC_PASSPHRASE, passPhrase);
data.putInt(KeychainIntentService.GENERATE_KEY_ALGORITHM, mNewKeyAlgorithmChoice.getId()); data.putInt(KeychainIntentService.GENERATE_KEY_ALGORITHM, mNewKeyAlgorithmChoice.getId());
data.putInt(KeychainIntentService.GENERATE_KEY_KEY_SIZE, mNewKeySize); 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) { if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
// get new key from data bundle returned from service // get new key from data bundle returned from service
Bundle data = message.getData(); Bundle data = message.getData();
PGPSecretKeyRing newKeyRing = (PGPSecretKeyRing) PgpConversionHelper PGPSecretKey newKey = (PGPSecretKey) PgpConversionHelper
.BytesToPGPKeyRing(data .BytesToPGPSecretKey(data
.getByteArray(KeychainIntentService.RESULT_NEW_KEY)); .getByteArray(KeychainIntentService.RESULT_NEW_KEY));
addGeneratedKeyToView(newKey);
addGeneratedKeyToView(newKeyRing);
} }
}; };
}; };
@ -341,27 +341,12 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
mActivity.startService(intent); mActivity.startService(intent);
} }
private void addGeneratedKeyToView(PGPSecretKeyRing newKeyRing) { private void addGeneratedKeyToView(PGPSecretKey newKey) {
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();
}
// add view with new key // add view with new key
KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item, KeyEditor view = (KeyEditor) mInflater.inflate(R.layout.edit_key_key_item,
mEditors, false); mEditors, false);
view.setEditorListener(SectionView.this); view.setEditorListener(SectionView.this);
view.setValue(newKey, isMasterKey, -1); view.setValue(newKey, newKey.isMasterKey(), -1);
mEditors.addView(view); mEditors.addView(view);
SectionView.this.updateEditorsVisible(); SectionView.this.updateEditorsVisible();
} }

View File

@ -103,6 +103,15 @@ public class PGPObjectFactory
{ {
throw new IOException("can't create secret key object: " + e); 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: case PacketTags.PUBLIC_KEY:
return new PGPPublicKeyRing(in, fingerPrintCalculator); return new PGPPublicKeyRing(in, fingerPrintCalculator);
case PacketTags.PUBLIC_SUBKEY: case PacketTags.PUBLIC_SUBKEY:

View File

@ -64,7 +64,7 @@ public class PGPSecretKey
this(privKey, pubKey, checksumCalculator, false, keyEncryptor); this(privKey, pubKey, checksumCalculator, false, keyEncryptor);
} }
PGPSecretKey( public PGPSecretKey(
PGPPrivateKey privKey, PGPPrivateKey privKey,
PGPPublicKey pubKey, PGPPublicKey pubKey,
PGPDigestCalculator checksumCalculator, PGPDigestCalculator checksumCalculator,

View File

@ -477,4 +477,23 @@ public class PGPSecretKeyRing
return new PGPSecretKeyRing(keys, secRing.extraPubKeys); 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));
}
} }