Merge pull request #196 from ashh87/master

cross-cert changes
This commit is contained in:
Dominik Schürmann 2014-01-14 23:54:40 -08:00
commit 9c0432d24c
3 changed files with 116 additions and 7 deletions

View File

@ -378,7 +378,7 @@ public class PgpKeyOperation {
keyFlags |= KeyFlags.SIGN_DATA; keyFlags |= KeyFlags.SIGN_DATA;
//cross-certify signing keys //cross-certify signing keys
PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder( PGPContentSignerBuilder signerBuilder = new JcaPGPContentSignerBuilder(
subKey.getPublicKey().getAlgorithm(), PGPUtil.SHA1) subPublicKey.getAlgorithm(), PGPUtil.SHA1)
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME); .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder); PGPSignatureGenerator sGen = new PGPSignatureGenerator(signerBuilder);
sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey); sGen.init(PGPSignature.PRIMARYKEY_BINDING, subPrivateKey);

View File

@ -33,7 +33,13 @@ import java.util.Iterator;
import org.spongycastle.bcpg.ArmoredInputStream; import org.spongycastle.bcpg.ArmoredInputStream;
import org.spongycastle.bcpg.ArmoredOutputStream; import org.spongycastle.bcpg.ArmoredOutputStream;
import org.spongycastle.bcpg.BCPGInputStream;
import org.spongycastle.bcpg.BCPGOutputStream; import org.spongycastle.bcpg.BCPGOutputStream;
import org.spongycastle.bcpg.SignaturePacket;
import org.spongycastle.bcpg.SignatureSubpacket;
import org.spongycastle.bcpg.SignatureSubpacketTags;
import org.spongycastle.openpgp.PGPCompressedData; import org.spongycastle.openpgp.PGPCompressedData;
import org.spongycastle.openpgp.PGPCompressedDataGenerator; import org.spongycastle.openpgp.PGPCompressedDataGenerator;
import org.spongycastle.openpgp.PGPEncryptedData; import org.spongycastle.openpgp.PGPEncryptedData;
@ -56,6 +62,7 @@ import org.spongycastle.openpgp.PGPSignature;
import org.spongycastle.openpgp.PGPSignatureGenerator; import org.spongycastle.openpgp.PGPSignatureGenerator;
import org.spongycastle.openpgp.PGPSignatureList; import org.spongycastle.openpgp.PGPSignatureList;
import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator; import org.spongycastle.openpgp.PGPSignatureSubpacketGenerator;
import org.spongycastle.openpgp.PGPSignatureSubpacketVector;
import org.spongycastle.openpgp.PGPUtil; import org.spongycastle.openpgp.PGPUtil;
import org.spongycastle.openpgp.PGPV3SignatureGenerator; import org.spongycastle.openpgp.PGPV3SignatureGenerator;
import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory; import org.spongycastle.openpgp.operator.PBEDataDecryptorFactory;
@ -757,11 +764,11 @@ public class PgpOperation {
PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject(); PGPSignatureList signatureList = (PGPSignatureList) plainFact.nextObject();
PGPSignature messageSignature = signatureList.get(signatureIndex); PGPSignature messageSignature = signatureList.get(signatureIndex);
if (signature.verify(messageSignature)) {
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, true); //Now check binding signatures
} else { boolean keyBinding_isok = verifyKeyBinding(mContext, messageSignature, signatureKey);
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, false); boolean sig_isok = signature.verify(messageSignature);
} returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, keyBinding_isok & sig_isok);
} }
} }
@ -887,12 +894,114 @@ public class PgpOperation {
} while (lookAhead != -1); } while (lookAhead != -1);
} }
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, signature.verify()); boolean sig_isok = signature.verify();
//Now check binding signatures
boolean keyBinding_isok = verifyKeyBinding(mContext, signature, signatureKey);
returnData.putBoolean(KeychainIntentService.RESULT_SIGNATURE_SUCCESS, sig_isok & keyBinding_isok);
updateProgress(R.string.progress_done, 100, 100); updateProgress(R.string.progress_done, 100, 100);
return returnData; return returnData;
} }
public boolean verifyKeyBinding(Context mContext, PGPSignature signature, PGPPublicKey signatureKey)
{
long signatureKeyId = signature.getKeyID();
boolean keyBinding_isok = false;
String userId = null;
PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByKeyId(mContext,
signatureKeyId);
PGPPublicKey mKey = null;
if (signKeyRing != null) {
mKey = PgpKeyHelper.getMasterKey(signKeyRing);
}
if (signature.getKeyID() != mKey.getKeyID()) {
keyBinding_isok = verifyKeyBinding(mKey, signatureKey);
} else { //if the key used to make the signature was the master key, no need to check binding sigs
keyBinding_isok = true;
}
return keyBinding_isok;
}
public boolean verifyKeyBinding(PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey)
{
boolean subkeyBinding_isok = false;
boolean tmp_subkeyBinding_isok = false;
boolean primkeyBinding_isok = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
Iterator<PGPSignature> itr = signingPublicKey.getSignatures();
subkeyBinding_isok = false;
tmp_subkeyBinding_isok = false;
primkeyBinding_isok = false;
while (itr.hasNext()) { //what does gpg do if the subkey binding is wrong?
//gpg has an invalid subkey binding error on key import I think, but doesn't shout
//about keys without subkey signing. Can't get it to import a slightly broken one
//either, so we will err on bad subkey binding here.
PGPSignature sig = itr.next();
if (sig.getKeyID() == masterPublicKey.getKeyID() && sig.getSignatureType() == PGPSignature.SUBKEY_BINDING) {
//check and if ok, check primary key binding.
try {
sig.init(contentVerifierBuilderProvider, masterPublicKey);
tmp_subkeyBinding_isok = sig.verifyCertification(masterPublicKey, signingPublicKey);
} catch (PGPException e) {
continue;
} catch (SignatureException e) {
continue;
}
if (tmp_subkeyBinding_isok)
subkeyBinding_isok = true;
if (tmp_subkeyBinding_isok) {
primkeyBinding_isok = verifyPrimaryBinding(sig.getUnhashedSubPackets(), masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
break;
primkeyBinding_isok = verifyPrimaryBinding(sig.getHashedSubPackets(), masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
break;
}
}
}
return (subkeyBinding_isok & primkeyBinding_isok);
}
private boolean verifyPrimaryBinding(PGPSignatureSubpacketVector Pkts, PGPPublicKey masterPublicKey, PGPPublicKey signingPublicKey)
{
boolean primkeyBinding_isok = false;
JcaPGPContentVerifierBuilderProvider contentVerifierBuilderProvider = new JcaPGPContentVerifierBuilderProvider()
.setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME);
PGPSignatureList eSigList;
if (Pkts.hasSubpacket(SignatureSubpacketTags.EMBEDDED_SIGNATURE)) {
try {
eSigList = Pkts.getEmbeddedSignatures();
} catch (IOException e) {
return false;
} catch (PGPException e) {
return false;
}
for (int j = 0; j < eSigList.size(); ++j) {
PGPSignature emSig = eSigList.get(j);
if (emSig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
try {
emSig.init(contentVerifierBuilderProvider, signingPublicKey);
primkeyBinding_isok = emSig.verifyCertification(masterPublicKey, signingPublicKey);
if (primkeyBinding_isok)
break;
} catch (PGPException e) {
continue;
} catch (SignatureException e) {
continue;
}
}
}
}
return primkeyBinding_isok;
}
private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput, private static void processLine(final String pLine, final ArmoredOutputStream pArmoredOutput,
final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException { final PGPSignatureGenerator pSignatureGenerator) throws IOException, SignatureException {