Program: 8310
Project: 8310
Buggy source:
private PgpEditKeyResult internal(PGPSecretKeyRing sKR,PGPSecretKey masterSecretKey,int masterKeyFlags,long masterKeyExpiry,CryptoInputParcel cryptoInput,SaveKeyringParcel saveParcel,OperationLog log){
  int indent=1;
  NfcSignOperationsBuilder nfcSignOps=new NfcSignOperationsBuilder(cryptoInput.getSignatureTime(),masterSecretKey.getKeyID(),masterSecretKey.getKeyID());
  progress(R.string.progress_modify,0);
  PGPPublicKey masterPublicKey=masterSecretKey.getPublicKey();
  PGPPrivateKey masterPrivateKey;
  if (isDivertToCard(masterSecretKey)) {
    masterPrivateKey=null;
    log.add(LogType.MSG_MF_DIVERT,indent);
  }
 else {
    progress(R.string.progress_modify_unlock,10);
    log.add(LogType.MSG_MF_UNLOCK,indent);
{
      try {
        PBESecretKeyDecryptor keyDecryptor=new JcePBESecretKeyDecryptorBuilder().setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
        masterPrivateKey=masterSecretKey.extractPrivateKey(keyDecryptor);
      }
 catch (      PGPException e) {
        log.add(LogType.MSG_MF_UNLOCK_ERROR,indent + 1);
        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
      }
    }
  }
  try {
    if (checkCancelled()) {
      log.add(LogType.MSG_OPERATION_CANCELLED,indent);
      return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
    }
{
      PGPPublicKey modifiedPublicKey=masterPublicKey;
      subProgressPush(15,23);
      for (int i=0; i < saveParcel.mAddUserIds.size(); i++) {
        progress(R.string.progress_modify_adduid,(i - 1) * (100 / saveParcel.mAddUserIds.size()));
        String userId=saveParcel.mAddUserIds.get(i);
        log.add(LogType.MSG_MF_UID_ADD,indent,userId);
        if ("String_Node_Str".equals(userId)) {
          log.add(LogType.MSG_MF_UID_ERROR_EMPTY,indent + 1);
          return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
        }
        @SuppressWarnings("String_Node_Str") Iterator<PGPSignature> it=modifiedPublicKey.getSignaturesForID(userId);
        if (it != null) {
          for (          PGPSignature cert : new IterableIterator<>(it)) {
            if (cert.getKeyID() != masterPublicKey.getKeyID()) {
              log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
              return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
            }
            if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
              modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,cert);
            }
          }
        }
        boolean isPrimary=saveParcel.mChangePrimaryUserId != null && userId.equals(saveParcel.mChangePrimaryUserId);
        try {
          PGPSignature cert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,isPrimary,masterKeyFlags,masterKeyExpiry);
          modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,cert);
        }
 catch (        NfcInteractionNeeded e) {
          nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
        }
      }
      subProgressPop();
      subProgressPush(23,32);
      for (int i=0; i < saveParcel.mAddUserAttribute.size(); i++) {
        progress(R.string.progress_modify_adduat,(i - 1) * (100 / saveParcel.mAddUserAttribute.size()));
        WrappedUserAttribute attribute=saveParcel.mAddUserAttribute.get(i);
switch (attribute.getType()) {
case WrappedUserAttribute.UAT_NONE:
          log.add(LogType.MSG_MF_UAT_ERROR_EMPTY,indent);
        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
case WrappedUserAttribute.UAT_IMAGE:
      log.add(LogType.MSG_MF_UAT_ADD_IMAGE,indent);
    break;
default :
  log.add(LogType.MSG_MF_UAT_ADD_UNKNOWN,indent);
break;
}
PGPUserAttributeSubpacketVector vector=attribute.getVector();
try {
PGPSignature cert=generateUserAttributeSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,vector,masterKeyFlags,masterKeyExpiry);
modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,vector,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
subProgressPush(32,40);
for (int i=0; i < saveParcel.mRevokeUserIds.size(); i++) {
progress(R.string.progress_modify_revokeuid,(i - 1) * (100 / saveParcel.mRevokeUserIds.size()));
String userId=saveParcel.mRevokeUserIds.get(i);
log.add(LogType.MSG_MF_UID_REVOKE,indent,userId);
boolean exists=false;
for (String uid : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
if (userId.equals(uid)) {
exists=true;
break;
}
}
if (!exists) {
log.add(LogType.MSG_MF_ERROR_NOEXIST_REVOKE,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
try {
PGPSignature cert=generateRevocationSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId);
modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
if (saveParcel.mChangePrimaryUserId != null) {
progress(R.string.progress_modify_primaryuid,40);
boolean ok=false;
log.add(LogType.MSG_MF_UID_PRIMARY,indent,saveParcel.mChangePrimaryUserId);
indent+=1;
for (String userId : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
boolean isRevoked=false;
PGPSignature currentCert=null;
for (PGPSignature cert : new IterableIterator<PGPSignature>(modifiedPublicKey.getSignaturesForID(userId))) {
if (cert.getKeyID() != masterPublicKey.getKeyID()) {
  log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
  return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) {
  isRevoked=true;
  continue;
}
if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
  currentCert=cert;
}
}
if (currentCert == null) {
log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (isRevoked) {
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
  log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY,indent);
  return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
continue;
}
if (currentCert.getHashedSubPackets() != null && currentCert.getHashedSubPackets().isPrimaryUserID()) {
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
  ok=true;
  continue;
}
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD,indent);
modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,currentCert);
try {
  PGPSignature newCert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,false,masterKeyFlags,masterKeyExpiry);
  modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,newCert);
}
 catch (NfcInteractionNeeded e) {
  nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
continue;
}
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
log.add(LogType.MSG_MF_PRIMARY_NEW,indent);
modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,currentCert);
try {
  PGPSignature newCert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,true,masterKeyFlags,masterKeyExpiry);
  modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,newCert);
}
 catch (NfcInteractionNeeded e) {
  nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
ok=true;
}
}
indent-=1;
if (!ok) {
log.add(LogType.MSG_MF_ERROR_NOEXIST_PRIMARY,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
}
if (modifiedPublicKey != masterPublicKey) {
masterSecretKey=PGPSecretKey.replacePublicKey(masterSecretKey,modifiedPublicKey);
masterPublicKey=modifiedPublicKey;
sKR=PGPSecretKeyRing.insertSecretKey(sKR,masterSecretKey);
}
}
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
subProgressPush(50,60);
for (int i=0; i < saveParcel.mChangeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeychange,(i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change=saveParcel.mChangeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,indent,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
PGPSecretKey sKey=sKR.getSecretKey(change.mKeyId);
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (change.mDummyStrip || change.mDummyDivert != null) {
if (change.mDummyStrip) {
sKey=PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
}
 else {
if (change.mDummyDivert.length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
}
sKR=PGPSecretKeyRing.insertSecretKey(sKR,sKey);
}
if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
continue;
}
if (change.mExpiry != null && change.mExpiry != 0 && new Date(change.mExpiry * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (change.mKeyId == masterPublicKey.getKeyID()) {
int flags=change.mFlags == null ? masterKeyFlags : change.mFlags;
long expiry=change.mExpiry == null ? masterKeyExpiry : change.mExpiry;
if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_MF_ERROR_NO_CERTIFY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=updateMasterCertificates(masterSecretKey,masterPrivateKey,masterPublicKey,flags,expiry,cryptoInput,nfcSignOps,indent,log);
if (pKey == null) {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
masterSecretKey=PGPSecretKey.replacePublicKey(sKey,pKey);
masterPublicKey=pKey;
sKR=PGPSecretKeyRing.insertSecretKey(sKR,masterSecretKey);
continue;
}
PGPPublicKey pKey=sKey.getPublicKey();
int flags=change.mFlags == null ? readKeyFlags(pKey) : change.mFlags;
long expiry;
if (change.mExpiry == null) {
long valid=pKey.getValidSeconds();
expiry=valid == 0 ? 0 : pKey.getCreationTime().getTime() / 1000 + pKey.getValidSeconds();
}
 else {
expiry=change.mExpiry;
}
for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
if ((change.mExpiry == null || change.mExpiry == 0L) && sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
expiry=0;
}
pKey=PGPPublicKey.removeCertification(pKey,sig);
}
PBESecretKeyDecryptor keyDecryptor=new JcePBESecretKeyDecryptorBuilder().setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
PGPPrivateKey subPrivateKey=sKey.extractPrivateKey(keyDecryptor);
PGPSignature sig=generateSubkeyBindingSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,subPrivateKey,pKey,flags,expiry);
pKey=PGPPublicKey.addCertification(pKey,sig);
sKR=PGPSecretKeyRing.insertSecretKey(sKR,PGPSecretKey.replacePublicKey(sKey,pKey));
}
subProgressPop();
subProgressPush(60,65);
for (int i=0; i < saveParcel.mRevokeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeyrevoke,(i - 1) * (100 / saveParcel.mRevokeSubKeys.size()));
long revocation=saveParcel.mRevokeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_REVOKE,indent,KeyFormattingUtils.convertKeyIdToHex(revocation));
PGPSecretKey sKey=sKR.getSecretKey(revocation);
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,indent + 1,KeyFormattingUtils.convertKeyIdToHex(revocation));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=sKey.getPublicKey();
try {
PGPSignature sig=generateRevocationSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,pKey);
pKey=PGPPublicKey.addCertification(pKey,sig);
sKR=PGPSecretKeyRing.insertSecretKey(sKR,PGPSecretKey.replacePublicKey(sKey,pKey));
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
subProgressPush(70,90);
for (int i=0; i < saveParcel.mAddSubKeys.size(); i++) {
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
progress(R.string.progress_modify_subkeyadd,(i - 1) * (100 / saveParcel.mAddSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add=saveParcel.mAddSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_NEW,indent,KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm,add.mKeySize,add.mCurve));
if (add.mExpiry == null) {
log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (add.mExpiry > 0L && new Date(add.mExpiry * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
subProgressPush((i - 1) * (100 / saveParcel.mAddSubKeys.size()),i * (100 / saveParcel.mAddSubKeys.size()));
PGPKeyPair keyPair=createKey(add,cryptoInput.getSignatureTime(),log,indent);
subProgressPop();
if (keyPair == null) {
log.add(LogType.MSG_MF_ERROR_PGP,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=keyPair.getPublicKey();
try {
PGPSignature cert=generateSubkeyBindingSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,keyPair.getPrivateKey(),pKey,add.mFlags,add.mExpiry);
pKey=PGPPublicKey.addSubkeyBindingCertification(pKey,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
PGPSecretKey sKey;
{
PGPDigestCalculator encryptorHashCalc=new JcaPGPDigestCalculatorProviderBuilder().build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyEncryptor keyEncryptor=new JcePBESecretKeyEncryptorBuilder(PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO,encryptorHashCalc,PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc=new JcaPGPDigestCalculatorProviderBuilder().build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
sKey=new PGPSecretKey(keyPair.getPrivateKey(),pKey,sha1Calc,false,keyEncryptor);
}
log.add(LogType.MSG_MF_SUBKEY_NEW_ID,indent + 1,KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID()));
sKR=PGPSecretKeyRing.insertSecretKey(sKR,sKey);
}
subProgressPop();
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
if (saveParcel.mNewUnlock != null) {
progress(R.string.progress_modify_passphrase,90);
log.add(LogType.MSG_MF_PASSPHRASE,indent);
indent+=1;
sKR=applyNewUnlock(sKR,masterPublicKey,masterPrivateKey,cryptoInput.getPassphrase(),saveParcel.mNewUnlock,log,indent);
if (sKR == null) {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
indent-=1;
}
}
 catch (IOException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_ENCODE,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
catch (PGPException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_PGP,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
catch (SignatureException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_SIG,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
progress(R.string.progress_done,100);
if (!nfcSignOps.isEmpty()) {
log.add(LogType.MSG_MF_REQUIRE_DIVERT,indent);
return new PgpEditKeyResult(log,nfcSignOps.build());
}
log.add(LogType.MSG_MF_SUCCESS,indent);
return new PgpEditKeyResult(OperationResult.RESULT_OK,log,new UncachedKeyRing(sKR));
}

Fixed version (ground truth):
private PgpEditKeyResult internal(PGPSecretKeyRing sKR,PGPSecretKey masterSecretKey,int masterKeyFlags,long masterKeyExpiry,CryptoInputParcel cryptoInput,SaveKeyringParcel saveParcel,OperationLog log,int indent){
  NfcSignOperationsBuilder nfcSignOps=new NfcSignOperationsBuilder(cryptoInput.getSignatureTime(),masterSecretKey.getKeyID(),masterSecretKey.getKeyID());
  progress(R.string.progress_modify,0);
  PGPPublicKey masterPublicKey=masterSecretKey.getPublicKey();
  PGPPrivateKey masterPrivateKey;
  if (isDivertToCard(masterSecretKey)) {
    masterPrivateKey=null;
    log.add(LogType.MSG_MF_DIVERT,indent);
  }
 else {
    progress(R.string.progress_modify_unlock,10);
    log.add(LogType.MSG_MF_UNLOCK,indent);
{
      try {
        PBESecretKeyDecryptor keyDecryptor=new JcePBESecretKeyDecryptorBuilder().setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
        masterPrivateKey=masterSecretKey.extractPrivateKey(keyDecryptor);
      }
 catch (      PGPException e) {
        log.add(LogType.MSG_MF_UNLOCK_ERROR,indent + 1);
        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
      }
    }
  }
  try {
    if (checkCancelled()) {
      log.add(LogType.MSG_OPERATION_CANCELLED,indent);
      return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
    }
{
      PGPPublicKey modifiedPublicKey=masterPublicKey;
      subProgressPush(15,23);
      for (int i=0; i < saveParcel.mAddUserIds.size(); i++) {
        progress(R.string.progress_modify_adduid,(i - 1) * (100 / saveParcel.mAddUserIds.size()));
        String userId=saveParcel.mAddUserIds.get(i);
        log.add(LogType.MSG_MF_UID_ADD,indent,userId);
        if ("String_Node_Str".equals(userId)) {
          log.add(LogType.MSG_MF_UID_ERROR_EMPTY,indent + 1);
          return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
        }
        @SuppressWarnings("String_Node_Str") Iterator<PGPSignature> it=modifiedPublicKey.getSignaturesForID(userId);
        if (it != null) {
          for (          PGPSignature cert : new IterableIterator<>(it)) {
            if (cert.getKeyID() != masterPublicKey.getKeyID()) {
              log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
              return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
            }
            if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION || cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
              modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,cert);
            }
          }
        }
        boolean isPrimary=saveParcel.mChangePrimaryUserId != null && userId.equals(saveParcel.mChangePrimaryUserId);
        try {
          PGPSignature cert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,isPrimary,masterKeyFlags,masterKeyExpiry);
          modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,cert);
        }
 catch (        NfcInteractionNeeded e) {
          nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
        }
      }
      subProgressPop();
      subProgressPush(23,32);
      for (int i=0; i < saveParcel.mAddUserAttribute.size(); i++) {
        progress(R.string.progress_modify_adduat,(i - 1) * (100 / saveParcel.mAddUserAttribute.size()));
        WrappedUserAttribute attribute=saveParcel.mAddUserAttribute.get(i);
switch (attribute.getType()) {
case WrappedUserAttribute.UAT_NONE:
          log.add(LogType.MSG_MF_UAT_ERROR_EMPTY,indent);
        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
case WrappedUserAttribute.UAT_IMAGE:
      log.add(LogType.MSG_MF_UAT_ADD_IMAGE,indent);
    break;
default :
  log.add(LogType.MSG_MF_UAT_ADD_UNKNOWN,indent);
break;
}
PGPUserAttributeSubpacketVector vector=attribute.getVector();
try {
PGPSignature cert=generateUserAttributeSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,vector,masterKeyFlags,masterKeyExpiry);
modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,vector,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
subProgressPush(32,40);
for (int i=0; i < saveParcel.mRevokeUserIds.size(); i++) {
progress(R.string.progress_modify_revokeuid,(i - 1) * (100 / saveParcel.mRevokeUserIds.size()));
String userId=saveParcel.mRevokeUserIds.get(i);
log.add(LogType.MSG_MF_UID_REVOKE,indent,userId);
boolean exists=false;
for (String uid : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
if (userId.equals(uid)) {
exists=true;
break;
}
}
if (!exists) {
log.add(LogType.MSG_MF_ERROR_NOEXIST_REVOKE,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
try {
PGPSignature cert=generateRevocationSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId);
modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
if (saveParcel.mChangePrimaryUserId != null) {
progress(R.string.progress_modify_primaryuid,40);
boolean ok=false;
log.add(LogType.MSG_MF_UID_PRIMARY,indent,saveParcel.mChangePrimaryUserId);
indent+=1;
for (String userId : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
boolean isRevoked=false;
PGPSignature currentCert=null;
for (PGPSignature cert : new IterableIterator<PGPSignature>(modifiedPublicKey.getSignaturesForID(userId))) {
if (cert.getKeyID() != masterPublicKey.getKeyID()) {
  log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
  return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) {
  isRevoked=true;
  continue;
}
if (cert.getSignatureType() == PGPSignature.NO_CERTIFICATION || cert.getSignatureType() == PGPSignature.CASUAL_CERTIFICATION || cert.getSignatureType() == PGPSignature.POSITIVE_CERTIFICATION || cert.getSignatureType() == PGPSignature.DEFAULT_CERTIFICATION) {
  currentCert=cert;
}
}
if (currentCert == null) {
log.add(LogType.MSG_MF_ERROR_INTEGRITY,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (isRevoked) {
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
  log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY,indent);
  return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
continue;
}
if (currentCert.getHashedSubPackets() != null && currentCert.getHashedSubPackets().isPrimaryUserID()) {
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
  ok=true;
  continue;
}
log.add(LogType.MSG_MF_PRIMARY_REPLACE_OLD,indent);
modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,currentCert);
try {
  PGPSignature newCert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,false,masterKeyFlags,masterKeyExpiry);
  modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,newCert);
}
 catch (NfcInteractionNeeded e) {
  nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
continue;
}
if (userId.equals(saveParcel.mChangePrimaryUserId)) {
log.add(LogType.MSG_MF_PRIMARY_NEW,indent);
modifiedPublicKey=PGPPublicKey.removeCertification(modifiedPublicKey,userId,currentCert);
try {
  PGPSignature newCert=generateUserIdSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPrivateKey,masterPublicKey,userId,true,masterKeyFlags,masterKeyExpiry);
  modifiedPublicKey=PGPPublicKey.addCertification(modifiedPublicKey,userId,newCert);
}
 catch (NfcInteractionNeeded e) {
  nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
ok=true;
}
}
indent-=1;
if (!ok) {
log.add(LogType.MSG_MF_ERROR_NOEXIST_PRIMARY,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
}
if (modifiedPublicKey != masterPublicKey) {
masterSecretKey=PGPSecretKey.replacePublicKey(masterSecretKey,modifiedPublicKey);
masterPublicKey=modifiedPublicKey;
sKR=PGPSecretKeyRing.insertSecretKey(sKR,masterSecretKey);
}
}
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
subProgressPush(50,60);
for (int i=0; i < saveParcel.mChangeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeychange,(i - 1) * (100 / saveParcel.mChangeSubKeys.size()));
SaveKeyringParcel.SubkeyChange change=saveParcel.mChangeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_CHANGE,indent,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
PGPSecretKey sKey=sKR.getSecretKey(change.mKeyId);
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (change.mDummyStrip || change.mDummyDivert != null) {
if (change.mDummyStrip) {
sKey=PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
}
 else {
if (change.mDummyDivert.length != 16) {
log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
}
sKR=PGPSecretKeyRing.insertSecretKey(sKR,sKey);
}
if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
continue;
}
if (change.mExpiry != null && change.mExpiry != 0 && new Date(change.mExpiry * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,indent + 1,KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (change.mKeyId == masterPublicKey.getKeyID()) {
int flags=change.mFlags == null ? masterKeyFlags : change.mFlags;
long expiry=change.mExpiry == null ? masterKeyExpiry : change.mExpiry;
if ((flags & KeyFlags.CERTIFY_OTHER) != KeyFlags.CERTIFY_OTHER) {
log.add(LogType.MSG_MF_ERROR_NO_CERTIFY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=updateMasterCertificates(masterSecretKey,masterPrivateKey,masterPublicKey,flags,expiry,cryptoInput,nfcSignOps,indent,log);
if (pKey == null) {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
masterSecretKey=PGPSecretKey.replacePublicKey(sKey,pKey);
masterPublicKey=pKey;
sKR=PGPSecretKeyRing.insertSecretKey(sKR,masterSecretKey);
continue;
}
PGPPublicKey pKey=sKey.getPublicKey();
int flags=change.mFlags == null ? readKeyFlags(pKey) : change.mFlags;
long expiry;
if (change.mExpiry == null) {
long valid=pKey.getValidSeconds();
expiry=valid == 0 ? 0 : pKey.getCreationTime().getTime() / 1000 + pKey.getValidSeconds();
}
 else {
expiry=change.mExpiry;
}
for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
if ((change.mExpiry == null || change.mExpiry == 0L) && sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
expiry=0;
}
pKey=PGPPublicKey.removeCertification(pKey,sig);
}
PBESecretKeyDecryptor keyDecryptor=new JcePBESecretKeyDecryptorBuilder().setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
PGPPrivateKey subPrivateKey=sKey.extractPrivateKey(keyDecryptor);
PGPSignature sig=generateSubkeyBindingSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,subPrivateKey,pKey,flags,expiry);
pKey=PGPPublicKey.addCertification(pKey,sig);
sKR=PGPSecretKeyRing.insertSecretKey(sKR,PGPSecretKey.replacePublicKey(sKey,pKey));
}
subProgressPop();
subProgressPush(60,65);
for (int i=0; i < saveParcel.mRevokeSubKeys.size(); i++) {
progress(R.string.progress_modify_subkeyrevoke,(i - 1) * (100 / saveParcel.mRevokeSubKeys.size()));
long revocation=saveParcel.mRevokeSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_REVOKE,indent,KeyFormattingUtils.convertKeyIdToHex(revocation));
PGPSecretKey sKey=sKR.getSecretKey(revocation);
if (sKey == null) {
log.add(LogType.MSG_MF_ERROR_SUBKEY_MISSING,indent + 1,KeyFormattingUtils.convertKeyIdToHex(revocation));
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=sKey.getPublicKey();
try {
PGPSignature sig=generateRevocationSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,pKey);
pKey=PGPPublicKey.addCertification(pKey,sig);
sKR=PGPSecretKeyRing.insertSecretKey(sKR,PGPSecretKey.replacePublicKey(sKey,pKey));
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
}
subProgressPop();
subProgressPush(70,90);
for (int i=0; i < saveParcel.mAddSubKeys.size(); i++) {
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
progress(R.string.progress_modify_subkeyadd,(i - 1) * (100 / saveParcel.mAddSubKeys.size()));
SaveKeyringParcel.SubkeyAdd add=saveParcel.mAddSubKeys.get(i);
log.add(LogType.MSG_MF_SUBKEY_NEW,indent,KeyFormattingUtils.getAlgorithmInfo(add.mAlgorithm,add.mKeySize,add.mCurve));
if (add.mExpiry == null) {
log.add(LogType.MSG_MF_ERROR_NULL_EXPIRY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
if (add.mExpiry > 0L && new Date(add.mExpiry * 1000).before(new Date())) {
log.add(LogType.MSG_MF_ERROR_PAST_EXPIRY,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
subProgressPush((i - 1) * (100 / saveParcel.mAddSubKeys.size()),i * (100 / saveParcel.mAddSubKeys.size()));
PGPKeyPair keyPair=createKey(add,cryptoInput.getSignatureTime(),log,indent);
subProgressPop();
if (keyPair == null) {
log.add(LogType.MSG_MF_ERROR_PGP,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
PGPPublicKey pKey=keyPair.getPublicKey();
try {
PGPSignature cert=generateSubkeyBindingSignature(getSignatureGenerator(masterSecretKey,cryptoInput),cryptoInput.getSignatureTime(),masterPublicKey,masterPrivateKey,keyPair.getPrivateKey(),pKey,add.mFlags,add.mExpiry);
pKey=PGPPublicKey.addSubkeyBindingCertification(pKey,cert);
}
 catch (NfcInteractionNeeded e) {
nfcSignOps.addHash(e.hashToSign,e.hashAlgo);
}
PGPSecretKey sKey;
{
PGPDigestCalculator encryptorHashCalc=new JcaPGPDigestCalculatorProviderBuilder().build().get(PgpConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
PBESecretKeyEncryptor keyEncryptor=new JcePBESecretKeyEncryptorBuilder(PgpConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO,encryptorHashCalc,PgpConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT).setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME).build(cryptoInput.getPassphrase().getCharArray());
PGPDigestCalculator sha1Calc=new JcaPGPDigestCalculatorProviderBuilder().build().get(PgpConstants.SECRET_KEY_SIGNATURE_CHECKSUM_HASH_ALGO);
sKey=new PGPSecretKey(keyPair.getPrivateKey(),pKey,sha1Calc,false,keyEncryptor);
}
log.add(LogType.MSG_MF_SUBKEY_NEW_ID,indent + 1,KeyFormattingUtils.convertKeyIdToHex(sKey.getKeyID()));
sKR=PGPSecretKeyRing.insertSecretKey(sKR,sKey);
}
subProgressPop();
if (checkCancelled()) {
log.add(LogType.MSG_OPERATION_CANCELLED,indent);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED,log,null);
}
if (saveParcel.mNewUnlock != null) {
progress(R.string.progress_modify_passphrase,90);
log.add(LogType.MSG_MF_PASSPHRASE,indent);
indent+=1;
sKR=applyNewUnlock(sKR,masterPublicKey,masterPrivateKey,cryptoInput.getPassphrase(),saveParcel.mNewUnlock,log,indent);
if (sKR == null) {
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
indent-=1;
}
}
 catch (IOException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_ENCODE,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
catch (PGPException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_PGP,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
catch (SignatureException e) {
Log.e(Constants.TAG,"String_Node_Str",e);
log.add(LogType.MSG_MF_ERROR_SIG,indent + 1);
return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR,log,null);
}
progress(R.string.progress_done,100);
if (!nfcSignOps.isEmpty()) {
log.add(LogType.MSG_MF_REQUIRE_DIVERT,indent);
return new PgpEditKeyResult(log,nfcSignOps.build());
}
log.add(LogType.MSG_MF_SUCCESS,indent);
return new PgpEditKeyResult(OperationResult.RESULT_OK,log,new UncachedKeyRing(sKR));
}