001// SPDX-FileCopyrightText: 2018 Paul Schaub <vanitasvitae@fsfe.org>
002//
003// SPDX-License-Identifier: Apache-2.0
004
005package org.pgpainless.algorithm;
006
007import java.util.ArrayList;
008import java.util.List;
009
010import org.bouncycastle.bcpg.sig.KeyFlags;
011
012/**
013 * Enumeration of different key flags.
014 * Key flags denote different capabilities of a key pair.
015 *
016 * @see <a href="https://tools.ietf.org/html/rfc4880#section-5.2.3.21">RFC4880: Key Flags</a>
017 */
018public enum KeyFlag {
019
020    /**
021     * This key may be used to certify other keys.
022     */
023    CERTIFY_OTHER  (KeyFlags.CERTIFY_OTHER),
024
025    /**
026     * This key may be used to sign data.
027     */
028    SIGN_DATA      (KeyFlags.SIGN_DATA),
029
030    /**
031     * This key may be used to encrypt communications.
032     */
033    ENCRYPT_COMMS  (KeyFlags.ENCRYPT_COMMS),
034
035    /**
036     * This key may be used to encrypt storage.
037     */
038    ENCRYPT_STORAGE(KeyFlags.ENCRYPT_STORAGE),
039
040    /**
041     * The private component of this key may have been split by a secret-sharing mechanism.
042     */
043    SPLIT          (KeyFlags.SPLIT),
044
045    /**
046     * This key may be used for authentication.
047     */
048    AUTHENTICATION (KeyFlags.AUTHENTICATION),
049
050    /**
051     * The private component of this key may be in the possession of more than one person.
052     */
053    SHARED         (KeyFlags.SHARED),
054    ;
055
056    private final int flag;
057
058    KeyFlag(int flag) {
059        this.flag = flag;
060    }
061
062    /**
063     * Return the numeric id of the {@link KeyFlag}.
064     *
065     * @return numeric id
066     */
067    public int getFlag() {
068        return flag;
069    }
070
071    /**
072     * Convert a bitmask into a list of {@link KeyFlag KeyFlags}.
073     *
074     * @param bitmask bitmask
075     * @return list of key flags encoded by the bitmask
076     */
077    public static List<KeyFlag> fromBitmask(int bitmask) {
078        List<KeyFlag> flags = new ArrayList<>();
079        for (KeyFlag f : KeyFlag.values()) {
080            if ((bitmask & f.flag) != 0) {
081                flags.add(f);
082            }
083        }
084        return flags;
085    }
086
087    /**
088     * Encode a list of {@link KeyFlag KeyFlags} into a bitmask.
089     *
090     * @param flags list of flags
091     * @return bitmask
092     */
093    public static int toBitmask(KeyFlag... flags) {
094        int mask = 0;
095        for (KeyFlag f : flags) {
096            mask |= f.getFlag();
097        }
098        return mask;
099    }
100
101    /**
102     * Return true if the provided bitmask has the bit for the provided flag set.
103     * Return false if the mask does not contain the flag.
104     *
105     * @param mask bitmask
106     * @param flag flag to be tested for
107     * @return true if flag is set, false otherwise
108     */
109    public static boolean hasKeyFlag(int mask, KeyFlag flag) {
110        return (mask & flag.getFlag()) == flag.getFlag();
111    }
112
113    public static boolean containsAny(int mask, KeyFlag... flags) {
114        for (KeyFlag flag : flags) {
115            if (hasKeyFlag(mask, flag)) {
116                return true;
117            }
118        }
119        return false;
120    }
121}