blob: 6a6ad559c463051a4b59c8eca56550c5bf1844f6 [file] [log] [blame]
package org.bouncycastle.asn1.pkcs;
import java.math.BigInteger;
import java.util.Enumeration;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Object;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERNull;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.util.Arrays;
/**
* <pre>
* PBKDF2-params ::= SEQUENCE {
* salt CHOICE {
* specified OCTET STRING,
* otherSource AlgorithmIdentifier {{PBKDF2-SaltSources}}
* },
* iterationCount INTEGER (1..MAX),
* keyLength INTEGER (1..MAX) OPTIONAL,
* prf AlgorithmIdentifier {{PBKDF2-PRFs}} DEFAULT algid-hmacWithSHA1 }
* </pre>
*/
public class PBKDF2Params
extends ASN1Object
{
private static final AlgorithmIdentifier algid_hmacWithSHA1 = new AlgorithmIdentifier(PKCSObjectIdentifiers.id_hmacWithSHA1, DERNull.INSTANCE);
private final ASN1OctetString octStr;
private final ASN1Integer iterationCount;
private final ASN1Integer keyLength;
private final AlgorithmIdentifier prf;
/**
* Create PBKDF2Params from the passed in object,
*
* @param obj either PBKDF2Params or an ASN1Sequence.
* @return a PBKDF2Params instance.
*/
public static PBKDF2Params getInstance(
Object obj)
{
if (obj instanceof PBKDF2Params)
{
return (PBKDF2Params)obj;
}
if (obj != null)
{
return new PBKDF2Params(ASN1Sequence.getInstance(obj));
}
return null;
}
/**
* Create a PBKDF2Params with the specified salt, iteration count, and algid-hmacWithSHA1 for the prf.
*
* @param salt input salt.
* @param iterationCount input iteration count.
*/
public PBKDF2Params(
byte[] salt,
int iterationCount)
{
this(salt, iterationCount, 0);
}
/**
* Create a PBKDF2Params with the specified salt, iteration count, keyLength, and algid-hmacWithSHA1 for the prf.
*
* @param salt input salt.
* @param iterationCount input iteration count.
* @param keyLength intended key length to be produced.
*/
public PBKDF2Params(
byte[] salt,
int iterationCount,
int keyLength)
{
this(salt, iterationCount, keyLength, null);
}
/**
* Create a PBKDF2Params with the specified salt, iteration count, keyLength, and a defined prf.
*
* @param salt input salt.
* @param iterationCount input iteration count.
* @param keyLength intended key length to be produced.
* @param prf the pseudo-random function to use.
*/
public PBKDF2Params(
byte[] salt,
int iterationCount,
int keyLength,
AlgorithmIdentifier prf)
{
this.octStr = new DEROctetString(Arrays.clone(salt));
this.iterationCount = new ASN1Integer(iterationCount);
if (keyLength > 0)
{
this.keyLength = new ASN1Integer(keyLength);
}
else
{
this.keyLength = null;
}
this.prf = prf;
}
/**
* Create a PBKDF2Params with the specified salt, iteration count, and a defined prf.
*
* @param salt input salt.
* @param iterationCount input iteration count.
* @param prf the pseudo-random function to use.
*/
public PBKDF2Params(
byte[] salt,
int iterationCount,
AlgorithmIdentifier prf)
{
this(salt, iterationCount, 0, prf);
}
private PBKDF2Params(
ASN1Sequence seq)
{
Enumeration e = seq.getObjects();
octStr = (ASN1OctetString)e.nextElement();
iterationCount = (ASN1Integer)e.nextElement();
if (e.hasMoreElements())
{
Object o = e.nextElement();
if (o instanceof ASN1Integer)
{
keyLength = ASN1Integer.getInstance(o);
if (e.hasMoreElements())
{
o = e.nextElement();
}
else
{
o = null;
}
}
else
{
keyLength = null;
}
if (o != null)
{
prf = AlgorithmIdentifier.getInstance(o);
}
else
{
prf = null;
}
}
else
{
keyLength = null;
prf = null;
}
}
/**
* Return the salt to use.
*
* @return the input salt.
*/
public byte[] getSalt()
{
return octStr.getOctets();
}
/**
* Return the iteration count to use.
*
* @return the input iteration count.
*/
public BigInteger getIterationCount()
{
return iterationCount.getValue();
}
/**
* Return the intended length in octets of the derived key.
*
* @return length in octets for derived key, if specified.
*/
public BigInteger getKeyLength()
{
if (keyLength != null)
{
return keyLength.getValue();
}
return null;
}
/**
* Return true if the PRF is the default (hmacWithSHA1)
*
* @return true if PRF is default, false otherwise.
*/
public boolean isDefaultPrf()
{
return prf == null || prf.equals(algid_hmacWithSHA1);
}
/**
* Return the algId of the underlying pseudo random function to use.
*
* @return the prf algorithm identifier.
*/
public AlgorithmIdentifier getPrf()
{
if (prf != null)
{
return prf;
}
return algid_hmacWithSHA1;
}
/**
* Return an ASN.1 structure suitable for encoding.
*
* @return the object as an ASN.1 encodable structure.
*/
public ASN1Primitive toASN1Primitive()
{
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(octStr);
v.add(iterationCount);
if (keyLength != null)
{
v.add(keyLength);
}
if (prf != null && !prf.equals(algid_hmacWithSHA1))
{
v.add(prf);
}
return new DERSequence(v);
}
}