1 package org.bouncycastle.crypto.util;
2 
3 import java.util.HashMap;
4 import java.util.Map;
5 
6 import org.bouncycastle.asn1.ASN1ObjectIdentifier;
7 import org.bouncycastle.asn1.DERNull;
8 import org.bouncycastle.asn1.cryptopro.CryptoProObjectIdentifiers;
9 import org.bouncycastle.asn1.gm.GMObjectIdentifiers;
10 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
11 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
12 import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
13 import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
14 import org.bouncycastle.util.Integers;
15 
16 /**
17  * Configuration class for a PBKDF using PKCS#5 Scheme 2.
18  */
19 public class PBKDF2Config
20     extends PBKDFConfig
21 {
22     /**
23      * AlgorithmIdentifier for a PRF using HMac with SHA-1
24      */
25     public static final AlgorithmIdentifier PRF_SHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE);
26 
27     /**
28      * AlgorithmIdentifier for a PRF using HMac with SHA-256
29      */
30     public static final AlgorithmIdentifier PRF_SHA256 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA256, DERNull.INSTANCE);
31 
32     /**
33      * AlgorithmIdentifier for a PRF using HMac with SHA-512
34      */
35     public static final AlgorithmIdentifier PRF_SHA512 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA512, DERNull.INSTANCE);
36 
37     /**
38      * AlgorithmIdentifier for a PRF using HMac with SHA3-256
39      */
40     public static final AlgorithmIdentifier PRF_SHA3_256 = new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_256, DERNull.INSTANCE);
41 
42     /**
43      * AlgorithmIdentifier for a PRF using SHA3-512
44      */
45     public static final AlgorithmIdentifier PRF_SHA3_512 = new AlgorithmIdentifier(NISTObjectIdentifiers.id_hmacWithSHA3_512, DERNull.INSTANCE);
46 
47     private static final Map PRFS_SALT = new HashMap();
48 
49     static
50     {
PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA1, Integers.valueOf(20))51         PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA1, Integers.valueOf(20));
PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA256, Integers.valueOf(32))52         PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA256, Integers.valueOf(32));
PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA512, Integers.valueOf(64))53         PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA512, Integers.valueOf(64));
PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA224, Integers.valueOf(28))54         PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA224, Integers.valueOf(28));
PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA384, Integers.valueOf(48))55         PRFS_SALT.put(PKCSObjectIdentifiers.id_hmacWithSHA384, Integers.valueOf(48));
PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_224, Integers.valueOf(28))56         PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_224, Integers.valueOf(28));
PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_256, Integers.valueOf(32))57         PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_256, Integers.valueOf(32));
PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_384, Integers.valueOf(48))58         PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_384, Integers.valueOf(48));
PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_512, Integers.valueOf(64))59         PRFS_SALT.put(NISTObjectIdentifiers.id_hmacWithSHA3_512, Integers.valueOf(64));
PRFS_SALT.put(CryptoProObjectIdentifiers.gostR3411Hmac, Integers.valueOf(32))60         PRFS_SALT.put(CryptoProObjectIdentifiers.gostR3411Hmac, Integers.valueOf(32));
PRFS_SALT.put(RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256, Integers.valueOf(32))61         PRFS_SALT.put(RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_256, Integers.valueOf(32));
PRFS_SALT.put(RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512, Integers.valueOf(64))62         PRFS_SALT.put(RosstandartObjectIdentifiers.id_tc26_hmac_gost_3411_12_512, Integers.valueOf(64));
PRFS_SALT.put(GMObjectIdentifiers.hmac_sm3, Integers.valueOf(32))63         PRFS_SALT.put(GMObjectIdentifiers.hmac_sm3, Integers.valueOf(32));
64     }
65 
getSaltSize(ASN1ObjectIdentifier algorithm)66     static int getSaltSize(ASN1ObjectIdentifier algorithm)
67     {
68         if (!PRFS_SALT.containsKey(algorithm))
69         {
70             throw new IllegalStateException("no salt size for algorithm: " + algorithm);
71         }
72 
73         return ((Integer)PRFS_SALT.get(algorithm)).intValue();
74     }
75 
76     public static class Builder
77     {
78         private int iterationCount = 1024;
79         private int saltLength = -1;
80         private AlgorithmIdentifier prf = PRF_SHA1;
81 
82         /**
83          * Base constructor.
84          *
85          * This configures the builder to use an iteration count of 1024, and the HMacSHA1 PRF.
86          */
Builder()87         public Builder()
88         {
89         }
90 
91         /**
92          * Set the iteration count for the PBE calculation.
93          *
94          * @param iterationCount the iteration count to apply to the key creation.
95          * @return the current builder.
96          */
withIterationCount(int iterationCount)97         public Builder withIterationCount(int iterationCount)
98         {
99             this.iterationCount = iterationCount;
100 
101             return this;
102         }
103 
104         /**
105          * Set the PRF to use for key generation. By default this is HmacSHA1.
106          *
107          * @param prf algorithm id for PRF.
108          * @return the current builder.
109          */
withPRF(AlgorithmIdentifier prf)110         public Builder withPRF(AlgorithmIdentifier prf)
111         {
112             this.prf = prf;
113 
114             return this;
115         }
116 
117         /**
118          * Set the length of the salt to use.
119          *
120          * @param saltLength the length of the salt (in octets) to use.
121          * @return the current builder.
122          */
withSaltLength(int saltLength)123         public Builder withSaltLength(int saltLength)
124         {
125             this.saltLength = saltLength;
126 
127             return this;
128         }
129 
build()130         public PBKDF2Config build()
131         {
132             return new PBKDF2Config(this);
133         }
134     }
135 
136     private final int iterationCount;
137     private final int saltLength;
138     private final AlgorithmIdentifier prf;
139 
PBKDF2Config(Builder builder)140     private PBKDF2Config(Builder builder)
141     {
142         super(PKCSObjectIdentifiers.id_PBKDF2);
143 
144         this.iterationCount = builder.iterationCount;
145         this.prf = builder.prf;
146 
147         if (builder.saltLength < 0)
148         {
149             this.saltLength = getSaltSize(prf.getAlgorithm());
150         }
151         else
152         {
153             this.saltLength = builder.saltLength;
154         }
155     }
156 
getIterationCount()157     public int getIterationCount()
158     {
159         return iterationCount;
160     }
161 
getPRF()162     public AlgorithmIdentifier getPRF()
163     {
164         return prf;
165     }
166 
getSaltLength()167     public int getSaltLength()
168     {
169         return saltLength;
170     }
171 }
172