Program: 8352
Project: 8352
Buggy source:
/** 
 * "Canonicalizes" a public key, removing inconsistencies in the process. More specifically: - Remove all non-verifying self-certificates - Remove all "future" self-certificates - Remove all certificates flagged as "local" - Remove all certificates which are superseded by a newer one on the same target, including revocations with later re-certifications. - Remove all certificates in other positions if not of known type: - key revocation signatures on the master key - subkey binding signatures for subkeys - certifications and certification revocations for user ids - If a subkey retains no valid subkey binding certificate, remove it - If a user id retains no valid self certificate, remove it - If the key is a secret key, remove all certificates by foreign keys - If no valid user id remains, log an error and return null This operation writes an OperationLog which can be used as part of an OperationResultParcel.
 * @return A canonicalized key, or null on fatal error (log will include a message in this case)
 */
@SuppressWarnings("String_Node_Str") public CanonicalizedKeyRing canonicalize(OperationLog log,int indent){
  log.add(isSecret() ? LogType.MSG_KC_SECRET : LogType.MSG_KC_PUBLIC,indent,KeyFormattingUtils.convertKeyIdToHex(getMasterKeyId()));
  indent+=1;
  if (getVersion() <= 3) {
    log.add(LogType.MSG_KC_ERROR_V3,indent);
    return null;
  }
  final Date now=new Date();
  int redundantCerts=0, badCerts=0;
  PGPKeyRing ring=mRing;
  PGPPublicKey masterKey=mRing.getPublicKey();
  final long masterKeyId=masterKey.getKeyID();
  if (Arrays.binarySearch(KNOWN_ALGORITHMS,masterKey.getAlgorithm()) < 0) {
    log.add(LogType.MSG_KC_ERROR_MASTER_ALGO,indent,Integer.toString(masterKey.getAlgorithm()));
    return null;
  }
{
    log.add(LogType.MSG_KC_MASTER,indent,KeyFormattingUtils.convertKeyIdToHex(masterKey.getKeyID()));
    indent+=1;
    PGPPublicKey modified=masterKey;
    PGPSignature revocation=null;
    for (    PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getKeySignatures())) {
      int type=zert.getSignatureType();
      if (type == PGPSignature.NO_CERTIFICATION || type == PGPSignature.DEFAULT_CERTIFICATION || type == PGPSignature.CASUAL_CERTIFICATION || type == PGPSignature.POSITIVE_CERTIFICATION || type == PGPSignature.CERTIFICATION_REVOCATION) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TYPE_UID,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      WrappedSignature cert=new WrappedSignature(zert);
      if (type != PGPSignature.KEY_REVOCATION) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(type,16));
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (cert.getCreationTime().after(now)) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TIME,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (cert.isLocal()) {
        log.add(LogType.MSG_KC_REVOKE_BAD_LOCAL,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      try {
        cert.init(masterKey);
        if (!cert.verifySignature(masterKey)) {
          log.add(LogType.MSG_KC_REVOKE_BAD,indent);
          modified=PGPPublicKey.removeCertification(modified,zert);
          badCerts+=1;
          continue;
        }
      }
 catch (      PgpGeneralException e) {
        log.add(LogType.MSG_KC_REVOKE_BAD_ERR,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (revocation == null) {
        revocation=zert;
      }
 else       if (revocation.getCreationTime().before(zert.getCreationTime())) {
        log.add(LogType.MSG_KC_REVOKE_DUP,indent);
        modified=PGPPublicKey.removeCertification(modified,revocation);
        redundantCerts+=1;
        revocation=zert;
      }
 else {
        log.add(LogType.MSG_KC_REVOKE_DUP,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        redundantCerts+=1;
      }
    }
    ArrayList<byte[]> processedUserIds=new ArrayList<byte[]>();
    for (    byte[] rawUserId : new IterableIterator<byte[]>(masterKey.getRawUserIDs())) {
      String userId=Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId);
      if (processedUserIds.contains(rawUserId)) {
        log.add(LogType.MSG_KC_UID_DUP,indent,userId);
        modified=PGPPublicKey.removeCertification(modified,rawUserId);
      }
      processedUserIds.add(rawUserId);
      PGPSignature selfCert=null;
      revocation=null;
      @SuppressWarnings("String_Node_Str") Iterator<PGPSignature> signaturesIt=masterKey.getSignaturesForID(rawUserId);
      if (signaturesIt != null) {
        for (        PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
          WrappedSignature cert=new WrappedSignature(zert);
          long certId=cert.getKeyId();
          int type=zert.getSignatureType();
          if (type != PGPSignature.DEFAULT_CERTIFICATION && type != PGPSignature.NO_CERTIFICATION && type != PGPSignature.CASUAL_CERTIFICATION && type != PGPSignature.POSITIVE_CERTIFICATION && type != PGPSignature.CERTIFICATION_REVOCATION) {
            log.add(LogType.MSG_KC_UID_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(zert.getSignatureType(),16));
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (cert.getCreationTime().after(now)) {
            log.add(LogType.MSG_KC_UID_BAD_TIME,indent);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (cert.isLocal()) {
            log.add(LogType.MSG_KC_UID_BAD_LOCAL,indent);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (certId != masterKeyId) {
            if (isSecret()) {
              log.add(LogType.MSG_KC_UID_FOREIGN,indent,KeyFormattingUtils.convertKeyIdToHex(certId));
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              badCerts+=1;
            }
            continue;
          }
          try {
            cert.init(masterKey);
            if (!cert.verifySignature(masterKey,rawUserId)) {
              log.add(LogType.MSG_KC_UID_BAD,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              badCerts+=1;
              continue;
            }
            if (!Utf8Util.isValidUTF8(rawUserId)) {
              log.add(LogType.MSG_KC_UID_WARN_ENCODING,indent);
            }
          }
 catch (          PgpGeneralException e) {
            log.add(LogType.MSG_KC_UID_BAD_ERR,indent,userId);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
switch (type) {
case PGPSignature.DEFAULT_CERTIFICATION:
case PGPSignature.NO_CERTIFICATION:
case PGPSignature.CASUAL_CERTIFICATION:
case PGPSignature.POSITIVE_CERTIFICATION:
            if (selfCert == null) {
              selfCert=zert;
            }
 else             if (selfCert.getCreationTime().before(cert.getCreationTime())) {
              log.add(LogType.MSG_KC_UID_CERT_DUP,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,selfCert);
              redundantCerts+=1;
              selfCert=zert;
            }
 else {
              log.add(LogType.MSG_KC_UID_CERT_DUP,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              redundantCerts+=1;
            }
          if (revocation != null && revocation.getCreationTime().before(selfCert.getCreationTime())) {
            log.add(LogType.MSG_KC_UID_REVOKE_OLD,indent,userId);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,revocation);
            revocation=null;
            redundantCerts+=1;
          }
        break;
case PGPSignature.CERTIFICATION_REVOCATION:
      if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) {
        log.add(LogType.MSG_KC_UID_REVOKE_OLD,indent,userId);
        modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
        redundantCerts+=1;
        continue;
      }
    if (revocation == null) {
      revocation=zert;
    }
 else     if (revocation.getCreationTime().before(cert.getCreationTime())) {
      log.add(LogType.MSG_KC_UID_REVOKE_DUP,indent,userId);
      modified=PGPPublicKey.removeCertification(modified,rawUserId,revocation);
      redundantCerts+=1;
      revocation=zert;
    }
 else {
      log.add(LogType.MSG_KC_UID_REVOKE_DUP,indent,userId);
      modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
      redundantCerts+=1;
    }
  break;
}
}
}
if (selfCert == null && revocation == null) {
log.add(LogType.MSG_KC_UID_REMOVE,indent,userId);
modified=PGPPublicKey.removeCertification(modified,rawUserId);
}
}
if (modified == null || !modified.getUserIDs().hasNext()) {
log.add(LogType.MSG_KC_ERROR_NO_UID,indent);
return null;
}
ring=replacePublicKey(ring,modified);
indent-=1;
}
Set<Long> knownIds=new HashSet<Long>();
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(ring.getPublicKeys())) {
if (knownIds.contains(key.getKeyID())) {
log.add(LogType.MSG_KC_ERROR_DUP_KEY,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
return null;
}
knownIds.add(key.getKeyID());
if (key.isMasterKey()) {
continue;
}
log.add(LogType.MSG_KC_SUB,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
indent+=1;
if (Arrays.binarySearch(KNOWN_ALGORITHMS,key.getAlgorithm()) < 0) {
ring=removeSubKey(ring,key);
log.add(LogType.MSG_KC_SUB_UNKNOWN_ALGO,indent,Integer.toString(key.getAlgorithm()));
indent-=1;
continue;
}
PGPPublicKey modified=key;
PGPSignature selfCert=null, revocation=null;
uids: for (PGPSignature zert : new IterableIterator<PGPSignature>(key.getSignatures())) {
modified=PGPPublicKey.removeCertification(modified,zert);
WrappedSignature cert=new WrappedSignature(zert);
int type=cert.getSignatureType();
if (cert.getKeyId() != masterKey.getKeyID()) {
log.add(LogType.MSG_KC_SUB_BAD_KEYID,indent);
badCerts+=1;
continue;
}
if (type != PGPSignature.SUBKEY_BINDING && type != PGPSignature.SUBKEY_REVOCATION) {
log.add(LogType.MSG_KC_SUB_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(type,16));
badCerts+=1;
continue;
}
if (cert.getCreationTime().after(now)) {
log.add(LogType.MSG_KC_SUB_BAD_TIME,indent);
badCerts+=1;
continue;
}
if (cert.isLocal()) {
log.add(LogType.MSG_KC_SUB_BAD_LOCAL,indent);
badCerts+=1;
continue;
}
if (type == PGPSignature.SUBKEY_BINDING) {
try {
cert.init(masterKey);
if (!cert.verifySignature(masterKey,key)) {
log.add(LogType.MSG_KC_SUB_BAD,indent);
badCerts+=1;
continue;
}
}
 catch (PgpGeneralException e) {
log.add(LogType.MSG_KC_SUB_BAD_ERR,indent);
badCerts+=1;
continue;
}
boolean needsPrimaryBinding=false;
if (isSigningAlgo(key.getAlgorithm())) {
if (zert.getHashedSubPackets() != null && zert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.KEY_FLAGS)) {
int flags=((KeyFlags)zert.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.KEY_FLAGS)).getFlags();
if ((flags & KeyFlags.SIGN_DATA) == KeyFlags.SIGN_DATA) {
  needsPrimaryBinding=true;
}
}
 else {
needsPrimaryBinding=true;
}
}
if (needsPrimaryBinding) {
boolean ok=false;
if (zert.getUnhashedSubPackets() != null) try {
PGPSignatureList list=zert.getUnhashedSubPackets().getEmbeddedSignatures();
for (int i=0; i < list.size(); i++) {
  WrappedSignature subsig=new WrappedSignature(list.get(i));
  if (subsig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
    subsig.init(key);
    if (subsig.verifySignature(masterKey,key)) {
      ok=true;
    }
 else {
      log.add(LogType.MSG_KC_SUB_PRIMARY_BAD,indent);
      badCerts+=1;
      continue uids;
    }
  }
}
}
 catch (Exception e) {
log.add(LogType.MSG_KC_SUB_PRIMARY_BAD_ERR,indent);
badCerts+=1;
continue;
}
if (!ok) {
log.add(LogType.MSG_KC_SUB_PRIMARY_NONE,indent);
badCerts+=1;
continue;
}
}
if (selfCert != null && cert.getCreationTime().before(selfCert.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_DUP,indent);
redundantCerts+=1;
continue;
}
selfCert=zert;
if (revocation != null && selfCert.getCreationTime().after(revocation.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_REVOKE_DUP,indent);
redundantCerts+=1;
revocation=null;
}
}
 else {
try {
cert.init(masterKey);
if (!cert.verifySignature(masterKey,key)) {
log.add(LogType.MSG_KC_SUB_REVOKE_BAD,indent);
badCerts+=1;
continue;
}
}
 catch (PgpGeneralException e) {
log.add(LogType.MSG_KC_SUB_REVOKE_BAD_ERR,indent);
badCerts+=1;
continue;
}
if (selfCert != null && selfCert.getCreationTime().after(cert.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_REVOKE_DUP,indent);
redundantCerts+=1;
continue;
}
revocation=zert;
}
}
if (selfCert == null) {
ring=removeSubKey(ring,key);
log.add(LogType.MSG_KC_SUB_NO_CERT,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
indent-=1;
continue;
}
if (selfCert.getHashedSubPackets() == null && selfCert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.KEY_FLAGS)) {
int flags=((KeyFlags)selfCert.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.KEY_FLAGS)).getFlags();
int algo=key.getAlgorithm();
if (!isSigningAlgo(algo) && (flags & KeyFlags.SIGN_DATA) == KeyFlags.SIGN_DATA) {
log.add(LogType.MSG_KC_SUB_ALGO_BAD_SIGN,indent);
}
if (!isEncryptionAlgo(algo) && ((flags & KeyFlags.ENCRYPT_STORAGE) == KeyFlags.ENCRYPT_STORAGE || (flags & KeyFlags.ENCRYPT_COMMS) == KeyFlags.ENCRYPT_COMMS)) {
log.add(LogType.MSG_KC_SUB_ALGO_BAD_ENCRYPT,indent);
}
}
modified=PGPPublicKey.addCertification(modified,selfCert);
if (revocation != null) {
modified=PGPPublicKey.addCertification(modified,revocation);
}
ring=replacePublicKey(ring,modified);
indent-=1;
}
if (badCerts > 0 && redundantCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_BAD_AND_RED,indent,Integer.toString(badCerts),Integer.toString(redundantCerts));
}
 else if (badCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_BAD,indent,badCerts);
}
 else if (redundantCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_REDUNDANT,indent,redundantCerts);
}
 else {
log.add(LogType.MSG_KC_SUCCESS,indent);
}
return isSecret() ? new CanonicalizedSecretKeyRing((PGPSecretKeyRing)ring,1) : new CanonicalizedPublicKeyRing((PGPPublicKeyRing)ring,0);
}

Fixed version (ground truth):
/** 
 * "Canonicalizes" a public key, removing inconsistencies in the process. More specifically: - Remove all non-verifying self-certificates - Remove all "future" self-certificates - Remove all certificates flagged as "local" - Remove all certificates which are superseded by a newer one on the same target, including revocations with later re-certifications. - Remove all certificates in other positions if not of known type: - key revocation signatures on the master key - subkey binding signatures for subkeys - certifications and certification revocations for user ids - If a subkey retains no valid subkey binding certificate, remove it - If a user id retains no valid self certificate, remove it - If the key is a secret key, remove all certificates by foreign keys - If no valid user id remains, log an error and return null This operation writes an OperationLog which can be used as part of an OperationResultParcel.
 * @return A canonicalized key, or null on fatal error (log will include a message in this case)
 */
@SuppressWarnings("String_Node_Str") public CanonicalizedKeyRing canonicalize(OperationLog log,int indent){
  log.add(isSecret() ? LogType.MSG_KC_SECRET : LogType.MSG_KC_PUBLIC,indent,KeyFormattingUtils.convertKeyIdToHex(getMasterKeyId()));
  indent+=1;
  if (getVersion() <= 3) {
    log.add(LogType.MSG_KC_ERROR_V3,indent);
    return null;
  }
  final Date now=new Date();
  int redundantCerts=0, badCerts=0;
  PGPKeyRing ring=mRing;
  PGPPublicKey masterKey=mRing.getPublicKey();
  final long masterKeyId=masterKey.getKeyID();
  if (Arrays.binarySearch(KNOWN_ALGORITHMS,masterKey.getAlgorithm()) < 0) {
    log.add(LogType.MSG_KC_ERROR_MASTER_ALGO,indent,Integer.toString(masterKey.getAlgorithm()));
    return null;
  }
{
    log.add(LogType.MSG_KC_MASTER,indent,KeyFormattingUtils.convertKeyIdToHex(masterKey.getKeyID()));
    indent+=1;
    PGPPublicKey modified=masterKey;
    PGPSignature revocation=null;
    for (    PGPSignature zert : new IterableIterator<PGPSignature>(masterKey.getKeySignatures())) {
      int type=zert.getSignatureType();
      if (type == PGPSignature.NO_CERTIFICATION || type == PGPSignature.DEFAULT_CERTIFICATION || type == PGPSignature.CASUAL_CERTIFICATION || type == PGPSignature.POSITIVE_CERTIFICATION || type == PGPSignature.CERTIFICATION_REVOCATION) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TYPE_UID,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      WrappedSignature cert=new WrappedSignature(zert);
      if (type != PGPSignature.KEY_REVOCATION) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(type,16));
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (cert.getCreationTime().after(now)) {
        log.add(LogType.MSG_KC_REVOKE_BAD_TIME,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (cert.isLocal()) {
        log.add(LogType.MSG_KC_REVOKE_BAD_LOCAL,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      try {
        cert.init(masterKey);
        if (!cert.verifySignature(masterKey)) {
          log.add(LogType.MSG_KC_REVOKE_BAD,indent);
          modified=PGPPublicKey.removeCertification(modified,zert);
          badCerts+=1;
          continue;
        }
      }
 catch (      PgpGeneralException e) {
        log.add(LogType.MSG_KC_REVOKE_BAD_ERR,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        badCerts+=1;
        continue;
      }
      if (revocation == null) {
        revocation=zert;
      }
 else       if (revocation.getCreationTime().before(zert.getCreationTime())) {
        log.add(LogType.MSG_KC_REVOKE_DUP,indent);
        modified=PGPPublicKey.removeCertification(modified,revocation);
        redundantCerts+=1;
        revocation=zert;
      }
 else {
        log.add(LogType.MSG_KC_REVOKE_DUP,indent);
        modified=PGPPublicKey.removeCertification(modified,zert);
        redundantCerts+=1;
      }
    }
    ArrayList<byte[]> processedUserIds=new ArrayList<byte[]>();
    for (    byte[] rawUserId : new IterableIterator<byte[]>(masterKey.getRawUserIDs())) {
      String userId=Utf8Util.fromUTF8ByteArrayReplaceBadEncoding(rawUserId);
      if (processedUserIds.contains(rawUserId)) {
        log.add(LogType.MSG_KC_UID_DUP,indent,userId);
        modified=PGPPublicKey.removeCertification(modified,rawUserId);
      }
      processedUserIds.add(rawUserId);
      PGPSignature selfCert=null;
      revocation=null;
      @SuppressWarnings("String_Node_Str") Iterator<PGPSignature> signaturesIt=masterKey.getSignaturesForID(rawUserId);
      if (signaturesIt != null) {
        for (        PGPSignature zert : new IterableIterator<PGPSignature>(signaturesIt)) {
          WrappedSignature cert=new WrappedSignature(zert);
          long certId=cert.getKeyId();
          int type=zert.getSignatureType();
          if (type != PGPSignature.DEFAULT_CERTIFICATION && type != PGPSignature.NO_CERTIFICATION && type != PGPSignature.CASUAL_CERTIFICATION && type != PGPSignature.POSITIVE_CERTIFICATION && type != PGPSignature.CERTIFICATION_REVOCATION) {
            log.add(LogType.MSG_KC_UID_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(zert.getSignatureType(),16));
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (cert.getCreationTime().after(now)) {
            log.add(LogType.MSG_KC_UID_BAD_TIME,indent);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (cert.isLocal()) {
            log.add(LogType.MSG_KC_UID_BAD_LOCAL,indent);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
          if (certId != masterKeyId) {
            if (isSecret()) {
              log.add(LogType.MSG_KC_UID_FOREIGN,indent,KeyFormattingUtils.convertKeyIdToHex(certId));
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              badCerts+=1;
            }
            continue;
          }
          try {
            cert.init(masterKey);
            if (!cert.verifySignature(masterKey,rawUserId)) {
              log.add(LogType.MSG_KC_UID_BAD,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              badCerts+=1;
              continue;
            }
            if (!Utf8Util.isValidUTF8(rawUserId)) {
              log.add(LogType.MSG_KC_UID_WARN_ENCODING,indent);
            }
          }
 catch (          PgpGeneralException e) {
            log.add(LogType.MSG_KC_UID_BAD_ERR,indent,userId);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
            badCerts+=1;
            continue;
          }
switch (type) {
case PGPSignature.DEFAULT_CERTIFICATION:
case PGPSignature.NO_CERTIFICATION:
case PGPSignature.CASUAL_CERTIFICATION:
case PGPSignature.POSITIVE_CERTIFICATION:
            if (selfCert == null) {
              selfCert=zert;
            }
 else             if (selfCert.getCreationTime().before(cert.getCreationTime())) {
              log.add(LogType.MSG_KC_UID_CERT_DUP,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,selfCert);
              redundantCerts+=1;
              selfCert=zert;
            }
 else {
              log.add(LogType.MSG_KC_UID_CERT_DUP,indent,userId);
              modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
              redundantCerts+=1;
            }
          if (revocation != null && revocation.getCreationTime().before(selfCert.getCreationTime())) {
            log.add(LogType.MSG_KC_UID_REVOKE_OLD,indent,userId);
            modified=PGPPublicKey.removeCertification(modified,rawUserId,revocation);
            revocation=null;
            redundantCerts+=1;
          }
        break;
case PGPSignature.CERTIFICATION_REVOCATION:
      if (selfCert != null && selfCert.getCreationTime().after(zert.getCreationTime())) {
        log.add(LogType.MSG_KC_UID_REVOKE_OLD,indent,userId);
        modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
        redundantCerts+=1;
        continue;
      }
    if (revocation == null) {
      revocation=zert;
    }
 else     if (revocation.getCreationTime().before(cert.getCreationTime())) {
      log.add(LogType.MSG_KC_UID_REVOKE_DUP,indent,userId);
      modified=PGPPublicKey.removeCertification(modified,rawUserId,revocation);
      redundantCerts+=1;
      revocation=zert;
    }
 else {
      log.add(LogType.MSG_KC_UID_REVOKE_DUP,indent,userId);
      modified=PGPPublicKey.removeCertification(modified,rawUserId,zert);
      redundantCerts+=1;
    }
  break;
}
}
}
if (selfCert == null && revocation == null) {
log.add(LogType.MSG_KC_UID_REMOVE,indent,userId);
modified=PGPPublicKey.removeCertification(modified,rawUserId);
}
}
if (modified == null || !modified.getUserIDs().hasNext()) {
log.add(LogType.MSG_KC_ERROR_NO_UID,indent);
return null;
}
ring=replacePublicKey(ring,modified);
indent-=1;
}
Set<Long> knownIds=new HashSet<Long>();
for (PGPPublicKey key : new IterableIterator<PGPPublicKey>(ring.getPublicKeys())) {
if (knownIds.contains(key.getKeyID())) {
log.add(LogType.MSG_KC_ERROR_DUP_KEY,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
return null;
}
knownIds.add(key.getKeyID());
if (key.isMasterKey()) {
continue;
}
log.add(LogType.MSG_KC_SUB,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
indent+=1;
if (Arrays.binarySearch(KNOWN_ALGORITHMS,key.getAlgorithm()) < 0) {
ring=removeSubKey(ring,key);
log.add(LogType.MSG_KC_SUB_UNKNOWN_ALGO,indent,Integer.toString(key.getAlgorithm()));
indent-=1;
continue;
}
PGPPublicKey modified=key;
PGPSignature selfCert=null, revocation=null;
uids: for (PGPSignature zert : new IterableIterator<PGPSignature>(key.getSignatures())) {
modified=PGPPublicKey.removeCertification(modified,zert);
WrappedSignature cert=new WrappedSignature(zert);
int type=cert.getSignatureType();
if (cert.getKeyId() != masterKey.getKeyID()) {
log.add(LogType.MSG_KC_SUB_BAD_KEYID,indent);
badCerts+=1;
continue;
}
if (type != PGPSignature.SUBKEY_BINDING && type != PGPSignature.SUBKEY_REVOCATION) {
log.add(LogType.MSG_KC_SUB_BAD_TYPE,indent,"String_Node_Str" + Integer.toString(type,16));
badCerts+=1;
continue;
}
if (cert.getCreationTime().after(now)) {
log.add(LogType.MSG_KC_SUB_BAD_TIME,indent);
badCerts+=1;
continue;
}
if (cert.isLocal()) {
log.add(LogType.MSG_KC_SUB_BAD_LOCAL,indent);
badCerts+=1;
continue;
}
if (type == PGPSignature.SUBKEY_BINDING) {
try {
cert.init(masterKey);
if (!cert.verifySignature(masterKey,key)) {
log.add(LogType.MSG_KC_SUB_BAD,indent);
badCerts+=1;
continue;
}
}
 catch (PgpGeneralException e) {
log.add(LogType.MSG_KC_SUB_BAD_ERR,indent);
badCerts+=1;
continue;
}
boolean needsPrimaryBinding=false;
if (isSigningAlgo(key.getAlgorithm())) {
if (zert.getHashedSubPackets() != null && zert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.KEY_FLAGS)) {
int flags=((KeyFlags)zert.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.KEY_FLAGS)).getFlags();
if ((flags & KeyFlags.SIGN_DATA) == KeyFlags.SIGN_DATA) {
  needsPrimaryBinding=true;
}
}
 else {
needsPrimaryBinding=true;
}
}
if (needsPrimaryBinding) {
boolean ok=false;
if (zert.getUnhashedSubPackets() != null) try {
PGPSignatureList list=zert.getUnhashedSubPackets().getEmbeddedSignatures();
for (int i=0; i < list.size(); i++) {
  WrappedSignature subsig=new WrappedSignature(list.get(i));
  if (subsig.getSignatureType() == PGPSignature.PRIMARYKEY_BINDING) {
    subsig.init(key);
    if (subsig.verifySignature(masterKey,key)) {
      ok=true;
    }
 else {
      log.add(LogType.MSG_KC_SUB_PRIMARY_BAD,indent);
      badCerts+=1;
      continue uids;
    }
  }
}
}
 catch (Exception e) {
log.add(LogType.MSG_KC_SUB_PRIMARY_BAD_ERR,indent);
badCerts+=1;
continue;
}
if (!ok) {
log.add(LogType.MSG_KC_SUB_PRIMARY_NONE,indent);
badCerts+=1;
continue;
}
}
if (selfCert != null && cert.getCreationTime().before(selfCert.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_DUP,indent);
redundantCerts+=1;
continue;
}
selfCert=zert;
if (revocation != null && selfCert.getCreationTime().after(revocation.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_REVOKE_DUP,indent);
redundantCerts+=1;
revocation=null;
}
}
 else {
try {
cert.init(masterKey);
if (!cert.verifySignature(masterKey,key)) {
log.add(LogType.MSG_KC_SUB_REVOKE_BAD,indent);
badCerts+=1;
continue;
}
}
 catch (PgpGeneralException e) {
log.add(LogType.MSG_KC_SUB_REVOKE_BAD_ERR,indent);
badCerts+=1;
continue;
}
if (selfCert != null && selfCert.getCreationTime().after(cert.getCreationTime())) {
log.add(LogType.MSG_KC_SUB_REVOKE_DUP,indent);
redundantCerts+=1;
continue;
}
revocation=zert;
}
}
if (selfCert == null) {
ring=removeSubKey(ring,key);
log.add(LogType.MSG_KC_SUB_NO_CERT,indent,KeyFormattingUtils.convertKeyIdToHex(key.getKeyID()));
indent-=1;
continue;
}
if (selfCert.getHashedSubPackets() != null && selfCert.getHashedSubPackets().hasSubpacket(SignatureSubpacketTags.KEY_FLAGS)) {
int flags=((KeyFlags)selfCert.getHashedSubPackets().getSubpacket(SignatureSubpacketTags.KEY_FLAGS)).getFlags();
int algo=key.getAlgorithm();
if (!isSigningAlgo(algo) && (flags & KeyFlags.SIGN_DATA) == KeyFlags.SIGN_DATA) {
log.add(LogType.MSG_KC_SUB_ALGO_BAD_SIGN,indent);
}
if (!isEncryptionAlgo(algo) && ((flags & KeyFlags.ENCRYPT_STORAGE) == KeyFlags.ENCRYPT_STORAGE || (flags & KeyFlags.ENCRYPT_COMMS) == KeyFlags.ENCRYPT_COMMS)) {
log.add(LogType.MSG_KC_SUB_ALGO_BAD_ENCRYPT,indent);
}
}
modified=PGPPublicKey.addCertification(modified,selfCert);
if (revocation != null) {
modified=PGPPublicKey.addCertification(modified,revocation);
}
ring=replacePublicKey(ring,modified);
indent-=1;
}
if (badCerts > 0 && redundantCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_BAD_AND_RED,indent,Integer.toString(badCerts),Integer.toString(redundantCerts));
}
 else if (badCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_BAD,indent,badCerts);
}
 else if (redundantCerts > 0) {
log.add(LogType.MSG_KC_SUCCESS_REDUNDANT,indent,redundantCerts);
}
 else {
log.add(LogType.MSG_KC_SUCCESS,indent);
}
return isSecret() ? new CanonicalizedSecretKeyRing((PGPSecretKeyRing)ring,1) : new CanonicalizedPublicKeyRing((PGPPublicKeyRing)ring,0);
}