001/*
002 * Copyright 2018 Paul Schaub.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.pgpainless.key.generation;
017
018import javax.annotation.Nonnull;
019
020import org.bouncycastle.bcpg.sig.Features;
021import org.bouncycastle.openpgp.PGPSignatureSubpacketGenerator;
022import org.pgpainless.algorithm.AlgorithmSuite;
023import org.pgpainless.algorithm.CompressionAlgorithm;
024import org.pgpainless.algorithm.Feature;
025import org.pgpainless.algorithm.HashAlgorithm;
026import org.pgpainless.algorithm.KeyFlag;
027import org.pgpainless.algorithm.SymmetricKeyAlgorithm;
028import org.pgpainless.key.generation.type.KeyType;
029
030public class KeySpecBuilder implements KeySpecBuilderInterface {
031
032    private KeyType type;
033    private PGPSignatureSubpacketGenerator hashedSubPackets = new PGPSignatureSubpacketGenerator();
034
035    KeySpecBuilder(@Nonnull KeyType type) {
036        this.type = type;
037    }
038
039    @Override
040    public WithDetailedConfiguration withKeyFlags(@Nonnull KeyFlag... flags) {
041        int val = 0;
042        for (KeyFlag f : flags) {
043            val |= f.getFlag();
044        }
045        this.hashedSubPackets.setKeyFlags(false, val);
046        return new WithDetailedConfigurationImpl();
047    }
048
049    @Override
050    public WithDetailedConfiguration withDefaultKeyFlags() {
051        return withKeyFlags(
052                KeyFlag.CERTIFY_OTHER,
053                KeyFlag.SIGN_DATA,
054                KeyFlag.ENCRYPT_COMMS,
055                KeyFlag.ENCRYPT_STORAGE,
056                KeyFlag.AUTHENTICATION);
057    }
058
059    @Override
060    public KeySpec withInheritedSubPackets() {
061        return new KeySpec(type, null, true);
062    }
063
064    class WithDetailedConfigurationImpl implements WithDetailedConfiguration {
065
066        @Deprecated
067        @Override
068        public WithPreferredSymmetricAlgorithms withDetailedConfiguration() {
069            return new WithPreferredSymmetricAlgorithmsImpl();
070        }
071
072        @Override
073        public KeySpec withDefaultAlgorithms() {
074            AlgorithmSuite defaultSuite = AlgorithmSuite.getDefaultAlgorithmSuite();
075            hashedSubPackets.setPreferredCompressionAlgorithms(false, defaultSuite.getCompressionAlgorithmIds());
076            hashedSubPackets.setPreferredSymmetricAlgorithms(false, defaultSuite.getSymmetricKeyAlgorithmIds());
077            hashedSubPackets.setPreferredHashAlgorithms(false, defaultSuite.getHashAlgorithmIds());
078            hashedSubPackets.setFeature(false, Features.FEATURE_MODIFICATION_DETECTION);
079
080            return new KeySpec(
081                    KeySpecBuilder.this.type,
082                    KeySpecBuilder.this.hashedSubPackets,
083                    false);
084        }
085    }
086
087    class WithPreferredSymmetricAlgorithmsImpl implements WithPreferredSymmetricAlgorithms {
088
089        @Override
090        public WithPreferredHashAlgorithms withPreferredSymmetricAlgorithms(@Nonnull SymmetricKeyAlgorithm... algorithms) {
091            int[] ids = new int[algorithms.length];
092            for (int i = 0; i < ids.length; i++) {
093                ids[i] = algorithms[i].getAlgorithmId();
094            }
095            KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false, ids);
096            return new WithPreferredHashAlgorithmsImpl();
097        }
098
099        @Override
100        public WithPreferredHashAlgorithms withDefaultSymmetricAlgorithms() {
101            KeySpecBuilder.this.hashedSubPackets.setPreferredSymmetricAlgorithms(false,
102                    AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
103            return new WithPreferredHashAlgorithmsImpl();
104        }
105
106        @Override
107        public WithFeatures withDefaultAlgorithms() {
108            hashedSubPackets.setPreferredSymmetricAlgorithms(false,
109                    AlgorithmSuite.getDefaultAlgorithmSuite().getSymmetricKeyAlgorithmIds());
110            hashedSubPackets.setPreferredCompressionAlgorithms(false,
111                    AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
112            hashedSubPackets.setPreferredHashAlgorithms(false,
113                    AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
114            return new WithFeaturesImpl();
115        }
116    }
117
118    class WithPreferredHashAlgorithmsImpl implements WithPreferredHashAlgorithms {
119
120        @Override
121        public WithPreferredCompressionAlgorithms withPreferredHashAlgorithms(@Nonnull HashAlgorithm... algorithms) {
122            int[] ids = new int[algorithms.length];
123            for (int i = 0; i < ids.length; i++) {
124                ids[i] = algorithms[i].getAlgorithmId();
125            }
126            KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false, ids);
127            return new WithPreferredCompressionAlgorithmsImpl();
128        }
129
130        @Override
131        public WithPreferredCompressionAlgorithms withDefaultHashAlgorithms() {
132            KeySpecBuilder.this.hashedSubPackets.setPreferredHashAlgorithms(false,
133                    AlgorithmSuite.getDefaultAlgorithmSuite().getHashAlgorithmIds());
134            return new WithPreferredCompressionAlgorithmsImpl();
135        }
136    }
137
138    class WithPreferredCompressionAlgorithmsImpl implements WithPreferredCompressionAlgorithms {
139
140        @Override
141        public WithFeatures withPreferredCompressionAlgorithms(@Nonnull CompressionAlgorithm... algorithms) {
142            int[] ids = new int[algorithms.length];
143            for (int i = 0; i < ids.length; i++) {
144                ids[i] = algorithms[i].getAlgorithmId();
145            }
146            KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false, ids);
147            return new WithFeaturesImpl();
148        }
149
150        @Override
151        public WithFeatures withDefaultCompressionAlgorithms() {
152            KeySpecBuilder.this.hashedSubPackets.setPreferredCompressionAlgorithms(false,
153                    AlgorithmSuite.getDefaultAlgorithmSuite().getCompressionAlgorithmIds());
154            return new WithFeaturesImpl();
155        }
156    }
157
158    class WithFeaturesImpl implements WithFeatures {
159
160        @Override
161        public WithFeatures withFeature(@Nonnull Feature feature) {
162            KeySpecBuilder.this.hashedSubPackets.setFeature(false, feature.getFeatureId());
163            return this;
164        }
165
166        @Override
167        public KeySpec done() {
168            return new KeySpec(
169                    KeySpecBuilder.this.type,
170                    hashedSubPackets,
171                    false);
172        }
173    }
174}