| package org.bouncycastle.jcajce.spec; |
| |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.OutputStreamWriter; |
| import java.security.spec.AlgorithmParameterSpec; |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.bouncycastle.util.Arrays; |
| import org.bouncycastle.util.Integers; |
| |
| /** |
| * Parameters for the Skein hash function - a series of byte[] strings identified by integer tags. |
| * <p> |
| * Parameterised Skein can be used for: |
| * <ul> |
| * <li>MAC generation, by providing a {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setKey(byte[]) key}.</li> |
| * <li>Randomised hashing, by providing a {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setNonce(byte[]) nonce}.</li> |
| * <li>A hash function for digital signatures, associating a |
| * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPublicKey(byte[]) public key} with the message digest.</li> |
| * <li>A key derivation function, by providing a |
| * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setKeyIdentifier(byte[]) key identifier}.</li> |
| * <li>Personalised hashing, by providing a |
| * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPersonalisation(java.util.Date, String, String) recommended format} or |
| * {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec.Builder#setPersonalisation(byte[]) arbitrary} personalisation string.</li> |
| * </ul> |
| * |
| * @see org.bouncycastle.crypto.digests.SkeinEngine |
| * @see org.bouncycastle.crypto.digests.SkeinDigest |
| * @see org.bouncycastle.crypto.macs.SkeinMac |
| */ |
| public class SkeinParameterSpec |
| implements AlgorithmParameterSpec |
| { |
| /** |
| * The parameter type for a secret key, supporting MAC or KDF functions: {@value |
| * #PARAM_TYPE_KEY}. |
| */ |
| public static final int PARAM_TYPE_KEY = 0; |
| |
| /** |
| * The parameter type for the Skein configuration block: {@value #PARAM_TYPE_CONFIG}. |
| */ |
| public static final int PARAM_TYPE_CONFIG = 4; |
| |
| /** |
| * The parameter type for a personalisation string: {@value #PARAM_TYPE_PERSONALISATION}. |
| */ |
| public static final int PARAM_TYPE_PERSONALISATION = 8; |
| |
| /** |
| * The parameter type for a public key: {@value #PARAM_TYPE_PUBLIC_KEY}. |
| */ |
| public static final int PARAM_TYPE_PUBLIC_KEY = 12; |
| |
| /** |
| * The parameter type for a key identifier string: {@value #PARAM_TYPE_KEY_IDENTIFIER}. |
| */ |
| public static final int PARAM_TYPE_KEY_IDENTIFIER = 16; |
| |
| /** |
| * The parameter type for a nonce: {@value #PARAM_TYPE_NONCE}. |
| */ |
| public static final int PARAM_TYPE_NONCE = 20; |
| |
| /** |
| * The parameter type for the message: {@value #PARAM_TYPE_MESSAGE}. |
| */ |
| public static final int PARAM_TYPE_MESSAGE = 48; |
| |
| /** |
| * The parameter type for the output transformation: {@value #PARAM_TYPE_OUTPUT}. |
| */ |
| public static final int PARAM_TYPE_OUTPUT = 63; |
| |
| private Map parameters; |
| |
| public SkeinParameterSpec() |
| { |
| this(new HashMap()); |
| } |
| |
| private SkeinParameterSpec(Map parameters) |
| { |
| this.parameters = Collections.unmodifiableMap(parameters); |
| } |
| |
| /** |
| * Obtains a map of type (Integer) to value (byte[]) for the parameters tracked in this object. |
| */ |
| public Map getParameters() |
| { |
| return parameters; |
| } |
| |
| /** |
| * Obtains the value of the {@link #PARAM_TYPE_KEY key parameter}, or <code>null</code> if not |
| * set. |
| */ |
| public byte[] getKey() |
| { |
| return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY))); |
| } |
| |
| /** |
| * Obtains the value of the {@link #PARAM_TYPE_PERSONALISATION personalisation parameter}, or |
| * <code>null</code> if not set. |
| */ |
| public byte[] getPersonalisation() |
| { |
| return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PERSONALISATION))); |
| } |
| |
| /** |
| * Obtains the value of the {@link #PARAM_TYPE_PUBLIC_KEY public key parameter}, or |
| * <code>null</code> if not set. |
| */ |
| public byte[] getPublicKey() |
| { |
| return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_PUBLIC_KEY))); |
| } |
| |
| /** |
| * Obtains the value of the {@link #PARAM_TYPE_KEY_IDENTIFIER key identifier parameter}, or |
| * <code>null</code> if not set. |
| */ |
| public byte[] getKeyIdentifier() |
| { |
| return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_KEY_IDENTIFIER))); |
| } |
| |
| /** |
| * Obtains the value of the {@link #PARAM_TYPE_NONCE nonce parameter}, or <code>null</code> if |
| * not set. |
| */ |
| public byte[] getNonce() |
| { |
| return Arrays.clone((byte[])parameters.get(Integers.valueOf(PARAM_TYPE_NONCE))); |
| } |
| |
| /** |
| * A builder for {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec}. |
| */ |
| public static class Builder |
| { |
| private Map parameters = new HashMap(); |
| |
| public Builder() |
| { |
| } |
| |
| public Builder(SkeinParameterSpec params) |
| { |
| Iterator keys = params.parameters.keySet().iterator(); |
| while (keys.hasNext()) |
| { |
| Integer key = (Integer)keys.next(); |
| parameters.put(key, params.parameters.get(key)); |
| } |
| } |
| |
| /** |
| * Sets a parameters to apply to the Skein hash function.<br> |
| * Parameter types must be in the range 0,5..62, and cannot use the value {@value |
| * org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE} (reserved for message body). |
| * <p> |
| * Parameters with type < {@value org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE} are processed before |
| * the message content, parameters with type > {@value org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_MESSAGE} |
| * are processed after the message and prior to output. |
| * </p> |
| * |
| * @param type the type of the parameter, in the range 5..62. |
| * @param value the byte sequence of the parameter. |
| * @return the current builder instance. |
| */ |
| public Builder set(int type, byte[] value) |
| { |
| if (value == null) |
| { |
| throw new IllegalArgumentException("Parameter value must not be null."); |
| } |
| if ((type != PARAM_TYPE_KEY) |
| && (type <= PARAM_TYPE_CONFIG || type >= PARAM_TYPE_OUTPUT || type == PARAM_TYPE_MESSAGE)) |
| { |
| throw new IllegalArgumentException("Parameter types must be in the range 0,5..47,49..62."); |
| } |
| if (type == PARAM_TYPE_CONFIG) |
| { |
| throw new IllegalArgumentException("Parameter type " + PARAM_TYPE_CONFIG |
| + " is reserved for internal use."); |
| } |
| this.parameters.put(Integers.valueOf(type), value); |
| return this; |
| } |
| |
| /** |
| * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY} parameter. |
| */ |
| public Builder setKey(byte[] key) |
| { |
| return set(PARAM_TYPE_KEY, key); |
| } |
| |
| /** |
| * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_PERSONALISATION} parameter. |
| */ |
| public Builder setPersonalisation(byte[] personalisation) |
| { |
| return set(PARAM_TYPE_PERSONALISATION, personalisation); |
| } |
| |
| /** |
| * Implements the recommended personalisation format for Skein defined in Section 4.11 of |
| * the Skein 1.3 specification. |
| * <p> |
| * The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte |
| * sequence using UTF-8 encoding. |
| * </p> |
| * |
| * @param date the date the personalised application of the Skein was defined. |
| * @param emailAddress the email address of the creation of the personalised application. |
| * @param distinguisher an arbitrary personalisation string distinguishing the application. |
| * @return the current builder instance. |
| */ |
| public Builder setPersonalisation(Date date, String emailAddress, String distinguisher) |
| { |
| try |
| { |
| final ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
| final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8"); |
| final DateFormat format = new SimpleDateFormat("YYYYMMDD"); |
| out.write(format.format(date)); |
| out.write(" "); |
| out.write(emailAddress); |
| out.write(" "); |
| out.write(distinguisher); |
| out.close(); |
| return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray()); |
| } |
| catch (IOException e) |
| { |
| throw new IllegalStateException("Byte I/O failed: " + e); |
| } |
| } |
| |
| /** |
| * Implements the recommended personalisation format for Skein defined in Section 4.11 of |
| * the Skein 1.3 specification. You may need to use this method if the default locale |
| * doesn't use a Gregorian calender so that the GeneralizedTime produced is compatible implementations. |
| * <p> |
| * The format is <code>YYYYMMDD email@address distinguisher</code>, encoded to a byte |
| * sequence using UTF-8 encoding. |
| * |
| * @param date the date the personalised application of the Skein was defined. |
| * @param dateLocale locale to be used for date interpretation. |
| * @param emailAddress the email address of the creation of the personalised application. |
| * @param distinguisher an arbitrary personalisation string distinguishing the application. |
| * @return the current builder instance. |
| */ |
| public Builder setPersonalisation(Date date, Locale dateLocale, String emailAddress, String distinguisher) |
| { |
| try |
| { |
| final ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
| final OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8"); |
| final DateFormat format = new SimpleDateFormat("YYYYMMDD", dateLocale); |
| out.write(format.format(date)); |
| out.write(" "); |
| out.write(emailAddress); |
| out.write(" "); |
| out.write(distinguisher); |
| out.close(); |
| return set(PARAM_TYPE_PERSONALISATION, bout.toByteArray()); |
| } |
| catch (IOException e) |
| { |
| throw new IllegalStateException("Byte I/O failed: " + e); |
| } |
| } |
| |
| /** |
| * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY_IDENTIFIER} parameter. |
| * |
| * @return the current builder instance. |
| */ |
| public Builder setPublicKey(byte[] publicKey) |
| { |
| return set(PARAM_TYPE_PUBLIC_KEY, publicKey); |
| } |
| |
| /** |
| * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_KEY_IDENTIFIER} parameter. |
| * |
| * @return the current builder instance. |
| */ |
| public Builder setKeyIdentifier(byte[] keyIdentifier) |
| { |
| return set(PARAM_TYPE_KEY_IDENTIFIER, keyIdentifier); |
| } |
| |
| /** |
| * Sets the {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec#PARAM_TYPE_NONCE} parameter. |
| * |
| * @return the current builder instance. |
| */ |
| public Builder setNonce(byte[] nonce) |
| { |
| return set(PARAM_TYPE_NONCE, nonce); |
| } |
| |
| /** |
| * Constructs a new {@link org.bouncycastle.jcajce.spec.SkeinParameterSpec} instance with the parameters provided to this |
| * builder. |
| */ |
| public SkeinParameterSpec build() |
| { |
| return new SkeinParameterSpec(parameters); |
| } |
| } |
| } |