Example usage for org.bouncycastle.openpgp PGPPublicKey getCreationTime

List of usage examples for org.bouncycastle.openpgp PGPPublicKey getCreationTime

Introduction

In this page you can find the example usage for org.bouncycastle.openpgp PGPPublicKey getCreationTime.

Prototype

public Date getCreationTime() 

Source Link

Usage

From source file:com.github.chrbayer84.keybits.GnuPGP.java

License:Open Source License

public String showPublicKey(PGPPublicKey public_key) throws Exception {
    String ret = Long.toHexString(public_key.getKeyID()) + "\n";
    ret = ret + "   created     : " + public_key.getCreationTime() + "\n";
    ret = ret + "   valid (days): " + public_key.getValidDays() + "\n";
    ret = ret + "   users       : ";

    Iterator<String> user_iterator = public_key.getUserIDs();
    int n = 0;/*from  w ww.  j  ava 2 s.  com*/
    if (user_iterator.hasNext())
        n = 2;

    while (user_iterator.hasNext())
        ret = ret + user_iterator.next() + ", ";

    ret = ret.substring(0, ret.length() - n) + "\n";

    return ret;
}

From source file:com.github.jpks.core.service.impl.PublicKeyReaderServiceImpl.java

License:Apache License

private PublicKeyImpl convert(final PGPPublicKey pgpPublicKey) {
    PublicKeyImpl key = new PublicKeyImpl();
    key.setUserIds(new ArrayList<UserIdImpl>());

    key.setKeyId(Long.toHexString(pgpPublicKey.getKeyID()).toUpperCase());
    key.setAlgo(pgpPublicKey.getAlgorithm());
    key.setKeyLen(pgpPublicKey.getBitStrength());
    key.setCreationDate(pgpPublicKey.getCreationTime());

    key.setMaster(pgpPublicKey.isMasterKey());
    key.setRevoked(pgpPublicKey.isRevoked());
    Iterator userIDs = pgpPublicKey.getUserIDs();

    while (userIDs.hasNext()) {
        String userUd = (String) userIDs.next();
        UserIdImpl userId = convert(userUd);
        userId.setCreationDate(pgpPublicKey.getCreationTime());
        key.addUserId(userId);/*w w w .  j  a  v a 2  s . c o  m*/
    }

    return key;
}

From source file:com.google.gerrit.gpg.PublicKeyChecker.java

License:Apache License

private CheckResult check(PGPPublicKey key, PublicKeyStore store, int depth, boolean expand,
        Set<Fingerprint> seen) {
    List<String> problems = new ArrayList<>();
    if (key.isRevoked()) {
        // TODO(dborowitz): isRevoked is overeager:
        // http://www.bouncycastle.org/jira/browse/BJB-45
        problems.add("Key is revoked");
    }//from w w w .  java 2  s.  c  o  m

    long validSecs = key.getValidSeconds();
    if (validSecs != 0) {
        long createdSecs = key.getCreationTime().getTime() / 1000;
        long nowSecs = System.currentTimeMillis() / 1000;
        if (nowSecs - createdSecs > validSecs) {
            problems.add("Key is expired");
        }
    }
    checkCustom(key, problems);

    CheckResult trustResult = checkWebOfTrust(key, store, depth, seen);
    if (expand) {
        problems.addAll(trustResult.getProblems());
    } else if (!trustResult.isOk()) {
        problems.add("Key is not trusted");
    }
    return new CheckResult(problems);
}

From source file:com.google.gerrit.server.git.gpg.PublicKeyChecker.java

License:Apache License

/**
 * Check a public key./*from  w ww .j a v  a2s .c  o m*/
 *
 * @param key the public key.
 * @param expectedKeyId the key ID that the caller expects.
 */
public final CheckResult check(PGPPublicKey key, long expectedKeyId) {
    List<String> problems = new ArrayList<>();
    if (key.getKeyID() != expectedKeyId) {
        problems.add("Public key does not match ID " + keyIdToString(expectedKeyId));
    }
    if (key.isRevoked()) {
        // TODO(dborowitz): isRevoked is overeager:
        // http://www.bouncycastle.org/jira/browse/BJB-45
        problems.add("Key is revoked");
    }

    long validSecs = key.getValidSeconds();
    if (validSecs != 0) {
        long createdSecs = key.getCreationTime().getTime() / 1000;
        long nowSecs = System.currentTimeMillis() / 1000;
        if (nowSecs - createdSecs > validSecs) {
            problems.add("Key is expired");
        }
    }
    checkCustom(key, expectedKeyId, problems);
    return new CheckResult(problems);
}

From source file:org.kontalk.certgen.X509Bridge.java

License:Open Source License

public static X509Certificate createCertificate(PGPPublicKeyRing publicKeyRing, PGPPrivateKey privateKey,
        String subjectAltName)// w  w w. ja va2s  . c o m
        throws InvalidKeyException, IllegalStateException, NoSuchAlgorithmException, SignatureException,
        CertificateException, NoSuchProviderException, PGPException, IOException, OperatorCreationException {

    X500NameBuilder x500NameBuilder = new X500NameBuilder();

    /*
     * The X.509 Name to be the subject DN is prepared.
     * The CN is extracted from the Secret Key user ID.
     */

    x500NameBuilder.addRDN(BCStyle.O, DN_COMMON_PART_O);

    PGPPublicKey publicKey = publicKeyRing.getPublicKey();

    for (@SuppressWarnings("unchecked")
    Iterator<Object> it = publicKey.getUserIDs(); it.hasNext();) {
        Object attrib = it.next();
        x500NameBuilder.addRDN(BCStyle.CN, attrib.toString());
    }

    X500Name x509name = x500NameBuilder.build();

    /*
     * To check the signature from the certificate on the recipient side,
     * the creation time needs to be embedded in the certificate.
     * It seems natural to make this creation time be the "not-before"
     * date of the X.509 certificate.
     * Unlimited PGP keys have a validity of 0 second. In this case,
     * the "not-after" date will be the same as the not-before date.
     * This is something that needs to be checked by the service
     * receiving this certificate.
     */
    Date creationTime = publicKey.getCreationTime();
    Date validTo = null;
    if (publicKey.getValidSeconds() > 0)
        validTo = new Date(creationTime.getTime() + 1000L * publicKey.getValidSeconds());

    return createCertificate(PGP.convertPublicKey(publicKey), PGP.convertPrivateKey(privateKey), x509name,
            creationTime, validTo, subjectAltName, publicKeyRing.getEncoded());
}

From source file:org.kontalk.xmppserver.pgp.PGPUtils.java

License:Open Source License

public static boolean isExpired(PGPPublicKey key) {
    // TODO check creation time signature
    Date creationDate = key.getCreationTime();
    Date expiryDate = key.getValidSeconds() > 0
            ? new Date(creationDate.getTime() + key.getValidSeconds() * 1000)
            : null;//from   w ww. j a v a  2  s.  c  o  m

    Date now = new Date();
    return creationDate.after(now) || (expiryDate != null && expiryDate.before(now));
}

From source file:org.mule.module.pgp.KeyBasedEncryptionStrategy.java

License:Open Source License

private void checkKeyExpirity(PGPPublicKey publicKey) {
    if (this.isCheckKeyExpirity() && publicKey.getValidDays() != 0) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(publicKey.getCreationTime());
        calendar.add(Calendar.DATE, publicKey.getValidDays());

        if (!calendar.getTime().after(Calendar.getInstance().getTime())) {
            throw new InvalidPublicKeyException(PGPMessages.pgpPublicKeyExpired());
        }/*from  ww  w  .ja  v a2s .  co m*/
    }
}

From source file:org.pgptool.gui.encryption.implpgp.KeyFilesOperationsPgpImpl.java

License:Open Source License

private static void fillDates(KeyInfo ret, PGPPublicKey key) {
    ret.setCreatedOn(new Date(key.getCreationTime().getTime()));
    if (key.getValidSeconds() != 0) {
        java.util.Date expiresAt = DateUtils.addSeconds(key.getCreationTime(), (int) key.getValidSeconds());
        ret.setExpiresAt(new Date(expiresAt.getTime()));
    }/*from   w  w w .  j a v  a 2 s.c  om*/
}

From source file:org.sufficientlysecure.keychain.pgp.PgpKeyOperation.java

License:Open Source License

private PgpEditKeyResult internal(PGPSecretKeyRing sKR, PGPSecretKey masterSecretKey, int masterKeyFlags,
        long masterKeyExpiry, CryptoInputParcel cryptoInput, SaveKeyringParcel saveParcel, OperationLog log,
        int indent) {

    SecurityTokenSignOperationsBuilder nfcSignOps = new SecurityTokenSignOperationsBuilder(
            cryptoInput.getSignatureTime(), masterSecretKey.getKeyID(), masterSecretKey.getKeyID());
    SecurityTokenKeyToCardOperationsBuilder nfcKeyToCardOps = new SecurityTokenKeyToCardOperationsBuilder(
            masterSecretKey.getKeyID());

    progress(R.string.progress_modify, 0);

    PGPPublicKey masterPublicKey = masterSecretKey.getPublicKey();

    PGPPrivateKey masterPrivateKey;/*from   ww  w  .  j a  v  a  2  s . c  o m*/

    if (isDivertToCard(masterSecretKey)) {
        masterPrivateKey = null;
        log.add(LogType.MSG_MF_DIVERT, indent);
    } else {

        // 1. Unlock private key
        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 {

        // Check if we were cancelled
        if (checkCancelled()) {
            log.add(LogType.MSG_OPERATION_CANCELLED, indent);
            return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
        }

        { // work on master secret key

            PGPPublicKey modifiedPublicKey = masterPublicKey;

            // 2a. Add certificates for new user ids
            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 ("".equals(userId)) {
                    log.add(LogType.MSG_MF_UID_ERROR_EMPTY, indent + 1);
                    return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                }

                // this operation supersedes all previous binding and revocation certificates,
                // so remove those to retain assertions from canonicalization for later operations
                @SuppressWarnings("unchecked")
                Iterator<PGPSignature> it = modifiedPublicKey.getSignaturesForID(userId);
                if (it != null) {
                    for (PGPSignature cert : new IterableIterator<>(it)) {
                        if (cert.getKeyID() != masterPublicKey.getKeyID()) {
                            // foreign certificate?! error error error
                            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);
                        }
                    }
                }

                // if it's supposed to be primary, we can do that here as well
                boolean isPrimary = saveParcel.mChangePrimaryUserId != null
                        && userId.equals(saveParcel.mChangePrimaryUserId);
                // generate and add new certificate
                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();

            // 2b. Add certificates for new user ids
            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()) {
                // the 'none' type must not succeed
                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();

                // generate and add new certificate
                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();

            // 2c. Add revocations for revoked user ids
            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);

                // Make sure the user id exists (yes these are 10 LoC in Java!)
                boolean exists = false;
                //noinspection unchecked
                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);
                }

                // a duplicate revocation will be removed during canonicalization, so no need to
                // take care of that here.
                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();

            // 3. If primary user id changed, generate new certificates for both old and new
            if (saveParcel.mChangePrimaryUserId != null) {
                progress(R.string.progress_modify_primaryuid, 40);

                // keep track if we actually changed one
                boolean ok = false;
                log.add(LogType.MSG_MF_UID_PRIMARY, indent, saveParcel.mChangePrimaryUserId);
                indent += 1;

                // we work on the modifiedPublicKey here, to respect new or newly revoked uids
                // noinspection unchecked
                for (String userId : new IterableIterator<String>(modifiedPublicKey.getUserIDs())) {
                    boolean isRevoked = false;
                    PGPSignature currentCert = null;
                    // noinspection unchecked
                    for (PGPSignature cert : new IterableIterator<PGPSignature>(
                            modifiedPublicKey.getSignaturesForID(userId))) {
                        if (cert.getKeyID() != masterPublicKey.getKeyID()) {
                            // foreign certificate?! error error error
                            log.add(LogType.MSG_MF_ERROR_INTEGRITY, indent);
                            return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                        }
                        // we know from canonicalization that if there is any revocation here, it
                        // is valid and not superseded by a newer certification.
                        if (cert.getSignatureType() == PGPSignature.CERTIFICATION_REVOCATION) {
                            isRevoked = true;
                            continue;
                        }
                        // we know from canonicalization that there is only one binding
                        // certification here, so we can just work with the first one.
                        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) {
                        // no certificate found?! error error error
                        log.add(LogType.MSG_MF_ERROR_INTEGRITY, indent);
                        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                    }

                    // we definitely should not update certifications of revoked keys, so just leave it.
                    if (isRevoked) {
                        // revoked user ids cannot be primary!
                        if (userId.equals(saveParcel.mChangePrimaryUserId)) {
                            log.add(LogType.MSG_MF_ERROR_REVOKED_PRIMARY, indent);
                            return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                        }
                        continue;
                    }

                    // if this is~ the/a primary user id
                    if (currentCert.getHashedSubPackets() != null
                            && currentCert.getHashedSubPackets().isPrimaryUserID()) {
                        // if it's the one we want, just leave it as is
                        if (userId.equals(saveParcel.mChangePrimaryUserId)) {
                            ok = true;
                            continue;
                        }
                        // otherwise, generate new non-primary certification
                        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 we are here, this is not currently a primary user id

                    // if it should be
                    if (userId.equals(saveParcel.mChangePrimaryUserId)) {
                        // add shiny new primary user id certificate
                        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;
                    }

                    // user id is not primary and is not supposed to be - nothing to do here.

                }

                indent -= 1;

                if (!ok) {
                    log.add(LogType.MSG_MF_ERROR_NOEXIST_PRIMARY, indent);
                    return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                }
            }

            // Update the secret key ring
            if (modifiedPublicKey != masterPublicKey) {
                masterSecretKey = PGPSecretKey.replacePublicKey(masterSecretKey, modifiedPublicKey);
                masterPublicKey = modifiedPublicKey;
                sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey);
            }

        }

        // Check if we were cancelled - again
        if (checkCancelled()) {
            log.add(LogType.MSG_OPERATION_CANCELLED, indent);
            return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
        }

        // 4a. For each subkey change, generate new subkey binding certificate
        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) {
                // IT'S DANGEROUS~
                // no really, it is. this operation irrevocably removes the private key data from the key
                sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey());
                sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
            } else if (change.mMoveKeyToSecurityToken) {
                if (checkSecurityTokenCompatibility(sKey, log, indent + 1)) {
                    log.add(LogType.MSG_MF_KEYTOCARD_START, indent + 1,
                            KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
                    nfcKeyToCardOps.addSubkey(change.mKeyId);
                } else {
                    // Appropriate log message already set by checkSecurityTokenCompatibility
                    return new PgpEditKeyResult(EditKeyResult.RESULT_ERROR, log, null);
                }
            } else if (change.mSecurityTokenSerialNo != null) {
                // NOTE: Does this code get executed? Or always handled in internalRestricted?
                if (change.mSecurityTokenSerialNo.length != 16) {
                    log.add(LogType.MSG_MF_ERROR_DIVERT_SERIAL, indent + 1,
                            KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
                    return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                }
                log.add(LogType.MSG_MF_KEYTOCARD_FINISH, indent + 1,
                        KeyFormattingUtils.convertKeyIdToHex(change.mKeyId),
                        Hex.toHexString(change.mSecurityTokenSerialNo, 8, 6));
                sKey = PGPSecretKey.constructGnuDummyKey(sKey.getPublicKey(), change.mSecurityTokenSerialNo);
                sKR = PGPSecretKeyRing.insertSecretKey(sKR, sKey);
            }

            // This doesn't concern us any further
            if (!change.mRecertify && (change.mExpiry == null && change.mFlags == null)) {
                continue;
            }

            // expiry must not be in the past
            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 this is the master key, update uid certificates instead
            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) {
                    // error log entry has already been added by updateMasterCertificates itself
                    return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                }
                masterSecretKey = PGPSecretKey.replacePublicKey(sKey, pKey);
                masterPublicKey = pKey;
                sKR = PGPSecretKeyRing.insertSecretKey(sKR, masterSecretKey);
                continue;
            }

            // otherwise, continue working on the public key
            PGPPublicKey pKey = sKey.getPublicKey();

            // keep old flags, or replace with new ones
            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;
            }

            // drop all old signatures, they will be superseded by the new one
            //noinspection unchecked
            for (PGPSignature sig : new IterableIterator<PGPSignature>(pKey.getSignatures())) {
                // special case: if there is a revocation, don't use expiry from before
                if ((change.mExpiry == null || change.mExpiry == 0L)
                        && sig.getSignatureType() == PGPSignature.SUBKEY_REVOCATION) {
                    expiry = 0;
                }
                pKey = PGPPublicKey.removeCertification(pKey, sig);
            }

            PGPPrivateKey subPrivateKey;
            if (!isDivertToCard(sKey)) {
                PBESecretKeyDecryptor keyDecryptor = new JcePBESecretKeyDecryptorBuilder()
                        .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
                        .build(cryptoInput.getPassphrase().getCharArray());
                subPrivateKey = sKey.extractPrivateKey(keyDecryptor);
                // super special case: subkey is allowed to sign, but isn't available
                if (subPrivateKey == null) {
                    log.add(LogType.MSG_MF_ERROR_SUB_STRIPPED, indent + 1,
                            KeyFormattingUtils.convertKeyIdToHex(change.mKeyId));
                    return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
                }
            } else {
                subPrivateKey = null;
            }
            try {
                PGPSignature sig = generateSubkeyBindingSignature(
                        getSignatureGenerator(masterSecretKey, cryptoInput), cryptoInput.getSignatureTime(),
                        masterPublicKey, masterPrivateKey, getSignatureGenerator(sKey, cryptoInput),
                        subPrivateKey, pKey, flags, expiry);

                // generate and add new signature
                pKey = PGPPublicKey.addCertification(pKey, sig);
                sKR = PGPSecretKeyRing.insertSecretKey(sKR, PGPSecretKey.replacePublicKey(sKey, pKey));
            } catch (NfcInteractionNeeded e) {
                nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
            }

        }
        subProgressPop();

        // 4b. For each subkey revocation, generate new subkey revocation certificate
        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();

            // generate and add new signature
            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();

        // 5. Generate and add new subkeys
        subProgressPush(70, 90);
        for (int i = 0; i < saveParcel.mAddSubKeys.size(); i++) {

            // Check if we were cancelled - again. This operation is expensive so we do it each loop.
            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 (isDivertToCard(masterSecretKey)) {
                log.add(LogType.MSG_MF_ERROR_DIVERT_NEWSUB, indent + 1);
                return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
            }

            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);
            }

            // generate a new secret key (privkey only for now)
            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);
            }

            // add subkey binding signature (making this a sub rather than master key)
            PGPPublicKey pKey = keyPair.getPublicKey();
            try {
                PGPSignature cert = generateSubkeyBindingSignature(
                        getSignatureGenerator(masterSecretKey, cryptoInput), cryptoInput.getSignatureTime(),
                        masterPublicKey, masterPrivateKey, getSignatureGenerator(pKey, cryptoInput, false),
                        keyPair.getPrivateKey(), pKey, add.mFlags, add.mExpiry);
                pKey = PGPPublicKey.addSubkeyBindingCertification(pKey, cert);
            } catch (NfcInteractionNeeded e) {
                nfcSignOps.addHash(e.hashToSign, e.hashAlgo);
            }

            PGPSecretKey sKey;
            {
                // Build key encrypter and decrypter based on passphrase
                PGPDigestCalculator encryptorHashCalc = new JcaPGPDigestCalculatorProviderBuilder().build()
                        .get(PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_HASH_ALGO);
                PBESecretKeyEncryptor keyEncryptor = new JcePBESecretKeyEncryptorBuilder(
                        PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_SYMMETRIC_ALGO, encryptorHashCalc,
                        PgpSecurityConstants.SECRET_KEY_ENCRYPTOR_S2K_COUNT)
                                .setProvider(Constants.BOUNCY_CASTLE_PROVIDER_NAME)
                                .build(cryptoInput.getPassphrase().getCharArray());

                PGPDigestCalculator sha1Calc = new JcaPGPDigestCalculatorProviderBuilder().build()
                        .get(PgpSecurityConstants.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();

        // Check if we were cancelled - again. This operation is expensive so we do it each loop.
        if (checkCancelled()) {
            log.add(LogType.MSG_OPERATION_CANCELLED, indent);
            return new PgpEditKeyResult(PgpEditKeyResult.RESULT_CANCELLED, log, null);
        }

        // 6. If requested, change passphrase
        if (saveParcel.getChangeUnlockParcel() != null) {
            progress(R.string.progress_modify_passphrase, 90);
            log.add(LogType.MSG_MF_PASSPHRASE, indent);
            indent += 1;

            sKR = applyNewPassphrase(sKR, masterPublicKey, cryptoInput.getPassphrase(),
                    saveParcel.getChangeUnlockParcel().mNewPassphrase, log, indent);
            if (sKR == null) {
                // The error has been logged above, just return a bad state
                return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
            }

            indent -= 1;
        }

        // 7. if requested, change PIN and/or Admin PIN on security token
        if (saveParcel.mSecurityTokenPin != null) {
            progress(R.string.progress_modify_pin, 90);
            log.add(LogType.MSG_MF_PIN, indent);
            indent += 1;

            nfcKeyToCardOps.setPin(saveParcel.mSecurityTokenPin);

            indent -= 1;
        }
        if (saveParcel.mSecurityTokenAdminPin != null) {
            progress(R.string.progress_modify_admin_pin, 90);
            log.add(LogType.MSG_MF_ADMIN_PIN, indent);
            indent += 1;

            nfcKeyToCardOps.setAdminPin(saveParcel.mSecurityTokenAdminPin);

            indent -= 1;
        }

    } catch (IOException e) {
        Log.e(Constants.TAG, "encountered IOException while modifying key", 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, "encountered pgp error while modifying key", 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, "encountered SignatureException while modifying key", 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() && !nfcKeyToCardOps.isEmpty()) {
        log.add(LogType.MSG_MF_ERROR_CONFLICTING_NFC_COMMANDS, indent + 1);
        return new PgpEditKeyResult(PgpEditKeyResult.RESULT_ERROR, log, null);
    }

    if (!nfcSignOps.isEmpty()) {
        log.add(LogType.MSG_MF_REQUIRE_DIVERT, indent);
        return new PgpEditKeyResult(log, nfcSignOps.build(), cryptoInput);
    }

    if (!nfcKeyToCardOps.isEmpty()) {
        log.add(LogType.MSG_MF_REQUIRE_DIVERT, indent);
        return new PgpEditKeyResult(log, nfcKeyToCardOps.build(), cryptoInput);
    }

    log.add(LogType.MSG_MF_SUCCESS, indent);
    return new PgpEditKeyResult(OperationResult.RESULT_OK, log, new UncachedKeyRing(sKR));

}

From source file:org.sufficientlysecure.keychain.pgp.PgpKeyOperation.java

License:Open Source License

private static PGPSignatureSubpacketGenerator generateHashedSelfSigSubpackets(Date creationTime,
        PGPPublicKey pKey, boolean primary, int flags, long expiry) {

    PGPSignatureSubpacketGenerator hashedPacketsGen = new PGPSignatureSubpacketGenerator();
    {/*from ww  w.  jav  a 2 s.  c o m*/
        /*
         * From RFC about critical subpackets:
         * If a subpacket is encountered that is
         * marked critical but is unknown to the evaluating software, the
         * evaluator SHOULD consider the signature to be in error.
         * An evaluator may "recognize" a subpacket, but not implement it.  The
         * purpose of the critical bit is to allow the signer to tell an
         * evaluator that it would prefer a new, unknown feature to generate an
         * error than be ignored.
         */
        /* non-critical subpackets: */
        hashedPacketsGen.setPreferredSymmetricAlgorithms(false,
                PgpSecurityConstants.PREFERRED_SYMMETRIC_ALGORITHMS);
        hashedPacketsGen.setPreferredHashAlgorithms(false, PgpSecurityConstants.PREFERRED_HASH_ALGORITHMS);
        hashedPacketsGen.setPreferredCompressionAlgorithms(false,
                PgpSecurityConstants.PREFERRED_COMPRESSION_ALGORITHMS);
        hashedPacketsGen.setPrimaryUserID(false, primary);

        /* critical subpackets: we consider those important for a modern pgp implementation */
        hashedPacketsGen.setSignatureCreationTime(true, creationTime);
        // Request that senders add the MDC to the message (authenticate unsigned messages)
        hashedPacketsGen.setFeature(true, Features.FEATURE_MODIFICATION_DETECTION);
        hashedPacketsGen.setKeyFlags(true, flags);
        if (expiry > 0) {
            hashedPacketsGen.setKeyExpirationTime(true, expiry - pKey.getCreationTime().getTime() / 1000);
        }
    }

    return hashedPacketsGen;
}