1/*
2 *  Licensed to the Apache Software Foundation (ASF) under one or more
3 *  contributor license agreements.  See the NOTICE file distributed with
4 *  this work for additional information regarding copyright ownership.
5 *  The ASF licenses this file to You under the Apache License, Version 2.0
6 *  (the "License"); you may not use this file except in compliance with
7 *  the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *  Unless required by applicable law or agreed to in writing, software
12 *  distributed under the License is distributed on an "AS IS" BASIS,
13 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *  See the License for the specific language governing permissions and
15 *  limitations under the License.
16 */
17
18package javax.crypto.spec;
19
20import java.security.spec.AlgorithmParameterSpec;
21import java.util.Arrays;
22
23/**
24 * The algorithm parameter specification for the <a
25 * href="http://www.ietf.org/rfc/rfc2268.txt">RC2</a> algorithm.
26 */
27public class RC2ParameterSpec implements AlgorithmParameterSpec {
28
29    private final int effectiveKeyBits;
30    private final byte[] iv;
31
32    /**
33     * Creates a new <code>RC2ParameterSpec</code> instance with the specified
34     * effective key length (in bits),
35     *
36     * @param effectiveKeyBits
37     *            the effective key length (in bits).
38     */
39    public RC2ParameterSpec(int effectiveKeyBits) {
40        this.effectiveKeyBits = effectiveKeyBits;
41        iv = null;
42    }
43
44    /**
45     * Creates a new <code>RC2ParameterSpec</code> instance with the specified
46     * effective key length (in bits) and <i>initialization vector</i>.
47     * <p>
48     * The size of the <i>initialization vector</i> must be at least 8 bytes
49     * which are copied to protect them against modification.
50     *
51     * @param effectiveKeyBits
52     *            the effective key length (in bits).
53     * @param iv
54     *            the initialization vector.
55     * @throws IllegalArgumentException
56     *             if the initialization vector is null or shorter than 8 bytes.
57     */
58    public RC2ParameterSpec(int effectiveKeyBits, byte[] iv) {
59        if (iv == null) {
60            throw new IllegalArgumentException("iv == null");
61        }
62        if (iv.length < 8) {
63            throw new IllegalArgumentException("iv.length < 8");
64        }
65        this.effectiveKeyBits = effectiveKeyBits;
66        this.iv = new byte[8];
67        System.arraycopy(iv, 0, this.iv, 0, 8);
68    }
69
70    /**
71     * Creates a new <code>RC2ParameterSpec</code> instance with the specified
72     * effective key length (in bits) and <i>initialization vector<i>.
73     * <p>
74     * The size of the <i>initialization vector</i> starting at
75     * <code>offset</code> must be at least 8 bytes which are copied to protect
76     * them against modification.
77     *
78     * @param effectiveKeyBits
79     *            the effective key length (in bits).
80     * @param iv
81     *            the initialization vector.
82     * @param offset
83     *            the offset in the initialization vector to start at.
84     * @throws IllegalArgumentException
85     *             if the initialization vector is null or starting at
86     *             <code>offset</code> is shorter than 8 bytes.
87     */
88    public RC2ParameterSpec(int effectiveKeyBits, byte[] iv, int offset) {
89        if (iv == null) {
90            throw new IllegalArgumentException("iv == null");
91        }
92        if (iv.length - offset < 8) {
93            throw new IllegalArgumentException("iv.length - offset < 8");
94        }
95        this.effectiveKeyBits = effectiveKeyBits;
96        this.iv = new byte[8];
97        System.arraycopy(iv, offset, this.iv, 0, 8);
98    }
99
100    /**
101     * Returns the effective key length (in bits).
102     *
103     * @return the effective key length (in bits).
104     */
105    public int getEffectiveKeyBits() {
106        return effectiveKeyBits;
107    }
108
109    /**
110     * Returns a copy of the initialization vector.
111     *
112     * @return a copy of the initialization vector, or null if none specified.
113     */
114    public byte[] getIV() {
115        if (iv == null) {
116            return null;
117        }
118        byte[] result = new byte[iv.length];
119        System.arraycopy(iv, 0, result, 0, iv.length);
120        return result;
121    }
122
123    /**
124     * Compares the specified object to this <code>RC2ParameterSpec</code>
125     * instance.
126     *
127     * @param obj
128     *            the object to compare.
129     * @return true if the effective key length and the initialization vector of
130     *         both objects are equal, otherwise false.
131     */
132    @Override
133    public boolean equals(Object obj) {
134        if (obj == this) {
135            return true;
136        }
137        if (!(obj instanceof RC2ParameterSpec)) {
138            return false;
139        }
140        RC2ParameterSpec ps = (RC2ParameterSpec) obj;
141        return (effectiveKeyBits == ps.effectiveKeyBits)
142            && (Arrays.equals(iv, ps.iv));
143    }
144
145    /**
146     * Returns the hash code of this <code>RC2ParameterSpec</code> instance.
147     *
148     * @return the hash code.
149     */
150    @Override
151    public int hashCode() {
152        int result = effectiveKeyBits;
153        if (iv == null) {
154            return result;
155        }
156        for (byte element : iv) {
157            result += element;
158        }
159        return result;
160    }
161}
162