mirror of
https://github.com/moparisthebest/open-keychain
synced 2025-02-26 00:11:52 -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
|
* @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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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,
|
||||||
|
@ -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");
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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,
|
||||||
|
@ -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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user