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}