001package org.apache.commons.ssl.org.bouncycastle.asn1.pkcs; 002 003import java.math.BigInteger; 004import java.util.Enumeration; 005 006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector; 007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Integer; 008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object; 009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1OctetString; 010import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive; 011import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence; 012import org.apache.commons.ssl.org.bouncycastle.asn1.DERNull; 013import org.apache.commons.ssl.org.bouncycastle.asn1.DEROctetString; 014import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence; 015import org.apache.commons.ssl.org.bouncycastle.asn1.x509.AlgorithmIdentifier; 016 017/** 018 * <pre> 019 * PBKDF2-params ::= SEQUENCE { 020 * salt CHOICE { 021 * specified OCTET STRING, 022 * otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}} 023 * }, 024 * iterationCount INTEGER (1..MAX), 025 * keyLength INTEGER (1..MAX) OPTIONAL, 026 * prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 } 027 * </pre> 028 */ 029public class PBKDF2Params 030 extends ASN1Object 031{ 032 private static final AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE); 033 034 private ASN1OctetString octStr; 035 private ASN1Integer iterationCount; 036 private ASN1Integer keyLength; 037 private AlgorithmIdentifier prf; 038 039 /** 040 * Create PBKDF2Params from the passed in object, 041 * 042 * @param obj either PBKDF2Params or an ASN2Sequence. 043 * @return a PBKDF2Params instance. 044 */ 045 public static PBKDF2Params getInstance( 046 Object obj) 047 { 048 if (obj instanceof PBKDF2Params) 049 { 050 return (PBKDF2Params)obj; 051 } 052 053 if (obj != null) 054 { 055 return new PBKDF2Params(ASN1Sequence.getInstance(obj)); 056 } 057 058 return null; 059 } 060 061 /** 062 * Create a PBKDF2Params with the specified salt, iteration count, and algid-hmacWithSHA1 for the prf. 063 * 064 * @param salt input salt. 065 * @param iterationCount input iteration count. 066 */ 067 public PBKDF2Params( 068 byte[] salt, 069 int iterationCount) 070 { 071 this.octStr = new DEROctetString(salt); 072 this.iterationCount = new ASN1Integer(iterationCount); 073 } 074 075 /** 076 * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and algid-hmacWithSHA1 for the prf. 077 * 078 * @param salt input salt. 079 * @param iterationCount input iteration count. 080 * @param keyLength intended key length to be produced. 081 */ 082 public PBKDF2Params( 083 byte[] salt, 084 int iterationCount, 085 int keyLength) 086 { 087 this(salt, iterationCount); 088 089 this.keyLength = new ASN1Integer(keyLength); 090 } 091 092 /** 093 * Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf. 094 * 095 * @param salt input salt. 096 * @param iterationCount input iteration count. 097 * @param keyLength intended key length to be produced. 098 * @param prf the pseudo-random function to use. 099 */ 100 public PBKDF2Params( 101 byte[] salt, 102 int iterationCount, 103 int keyLength, 104 AlgorithmIdentifier prf) 105 { 106 this(salt, iterationCount); 107 108 this.keyLength = new ASN1Integer(keyLength); 109 this.prf = prf; 110 } 111 112 /** 113 * Create a PBKDF2Params with the specified salt, iteration count, and a defined prf. 114 * 115 * @param salt input salt. 116 * @param iterationCount input iteration count. 117 * @param prf the pseudo-random function to use. 118 */ 119 public PBKDF2Params( 120 byte[] salt, 121 int iterationCount, 122 AlgorithmIdentifier prf) 123 { 124 this(salt, iterationCount); 125 this.prf = prf; 126 } 127 128 private PBKDF2Params( 129 ASN1Sequence seq) 130 { 131 Enumeration e = seq.getObjects(); 132 133 octStr = (ASN1OctetString)e.nextElement(); 134 iterationCount = (ASN1Integer)e.nextElement(); 135 136 if (e.hasMoreElements()) 137 { 138 Object o = e.nextElement(); 139 140 if (o instanceof ASN1Integer) 141 { 142 keyLength = ASN1Integer.getInstance(o); 143 if (e.hasMoreElements()) 144 { 145 o = e.nextElement(); 146 } 147 else 148 { 149 o = null; 150 } 151 } 152 else 153 { 154 keyLength = null; 155 } 156 157 if (o != null) 158 { 159 prf = AlgorithmIdentifier.getInstance(o); 160 } 161 } 162 } 163 164 /** 165 * Return the salt to use. 166 * 167 * @return the input salt. 168 */ 169 public byte[] getSalt() 170 { 171 return octStr.getOctets(); 172 } 173 174 /** 175 * Return the iteration count to use. 176 * 177 * @return the input iteration count. 178 */ 179 public BigInteger getIterationCount() 180 { 181 return iterationCount.getValue(); 182 } 183 184 /** 185 * Return the intended length in octets of the derived key. 186 * 187 * @return length in octets for derived key, if specified. 188 */ 189 public BigInteger getKeyLength() 190 { 191 if (keyLength != null) 192 { 193 return keyLength.getValue(); 194 } 195 196 return null; 197 } 198 199 /** 200 * Return true if the PRF is the default (hmacWithSHA1) 201 * 202 * @return true if PRF is default, false otherwise. 203 */ 204 public boolean isDefaultPrf() 205 { 206 return prf == null || prf.equals(algid_hmacWithSHA1); 207 } 208 209 /** 210 * Return the algId of the underlying pseudo random function to use. 211 * 212 * @return the prf algorithm identifier. 213 */ 214 public AlgorithmIdentifier getPrf() 215 { 216 if (prf != null) 217 { 218 return prf; 219 } 220 221 return algid_hmacWithSHA1; 222 } 223 224 /** 225 * Return an ASN.1 structure suitable for encoding. 226 * 227 * @return the object as an ASN.1 encodable structure. 228 */ 229 public ASN1Primitive toASN1Primitive() 230 { 231 ASN1EncodableVector v = new ASN1EncodableVector(); 232 233 v.add(octStr); 234 v.add(iterationCount); 235 236 if (keyLength != null) 237 { 238 v.add(keyLength); 239 } 240 241 if (prf != null && !prf.equals(algid_hmacWithSHA1)) 242 { 243 v.add(prf); 244 } 245 246 return new DERSequence(v); 247 } 248}