001: package org.bouncycastle.jce.provider;
002:
003: import java.security.spec.AlgorithmParameterSpec;
004:
005: import javax.crypto.spec.PBEKeySpec;
006: import javax.crypto.spec.PBEParameterSpec;
007:
008: import org.bouncycastle.crypto.CipherParameters;
009: import org.bouncycastle.crypto.PBEParametersGenerator;
010: import org.bouncycastle.crypto.digests.MD5Digest;
011: import org.bouncycastle.crypto.digests.RIPEMD160Digest;
012: import org.bouncycastle.crypto.digests.SHA1Digest;
013: import org.bouncycastle.crypto.digests.SHA256Digest;
014: import org.bouncycastle.crypto.digests.TigerDigest;
015: import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator;
016: import org.bouncycastle.crypto.generators.PKCS12ParametersGenerator;
017: import org.bouncycastle.crypto.generators.PKCS5S1ParametersGenerator;
018: import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator;
019: import org.bouncycastle.crypto.params.DESParameters;
020: import org.bouncycastle.crypto.params.KeyParameter;
021: import org.bouncycastle.crypto.params.ParametersWithIV;
022:
023: public interface PBE {
024: //
025: // PBE Based encryption constants - by default we do PKCS12 with SHA-1
026: //
027: static final int MD5 = 0;
028: static final int SHA1 = 1;
029: static final int RIPEMD160 = 2;
030: static final int TIGER = 3;
031: static final int SHA256 = 4;
032:
033: static final int PKCS5S1 = 0;
034: static final int PKCS5S2 = 1;
035: static final int PKCS12 = 2;
036: static final int OPENSSL = 3;
037:
038: /**
039: * uses the appropriate mixer to generate the key and IV if necessary.
040: */
041: static class Util {
042: static private PBEParametersGenerator makePBEGenerator(
043: int type, int hash) {
044: PBEParametersGenerator generator;
045:
046: if (type == PKCS5S1) {
047: switch (hash) {
048: case MD5:
049: generator = new PKCS5S1ParametersGenerator(
050: new MD5Digest());
051: break;
052: case SHA1:
053: generator = new PKCS5S1ParametersGenerator(
054: new SHA1Digest());
055: break;
056: default:
057: throw new IllegalStateException(
058: "PKCS5 scheme 1 only supports only MD5 and SHA1.");
059: }
060: } else if (type == PKCS5S2) {
061: generator = new PKCS5S2ParametersGenerator();
062: } else if (type == PKCS12) {
063: switch (hash) {
064: case MD5:
065: generator = new PKCS12ParametersGenerator(
066: new MD5Digest());
067: break;
068: case SHA1:
069: generator = new PKCS12ParametersGenerator(
070: new SHA1Digest());
071: break;
072: case RIPEMD160:
073: generator = new PKCS12ParametersGenerator(
074: new RIPEMD160Digest());
075: break;
076: case TIGER:
077: generator = new PKCS12ParametersGenerator(
078: new TigerDigest());
079: break;
080: case SHA256:
081: generator = new PKCS12ParametersGenerator(
082: new SHA256Digest());
083: break;
084: default:
085: throw new IllegalStateException(
086: "unknown digest scheme for PBE encryption.");
087: }
088: } else {
089: generator = new OpenSSLPBEParametersGenerator();
090: }
091:
092: return generator;
093: }
094:
095: /**
096: * construct a key and iv (if necessary) suitable for use with a
097: * Cipher.
098: */
099: static CipherParameters makePBEParameters(JCEPBEKey pbeKey,
100: AlgorithmParameterSpec spec, String targetAlgorithm) {
101: if ((spec == null) || !(spec instanceof PBEParameterSpec)) {
102: throw new IllegalArgumentException(
103: "Need a PBEParameter spec with a PBE key.");
104: }
105:
106: PBEParameterSpec pbeParam = (PBEParameterSpec) spec;
107: PBEParametersGenerator generator = makePBEGenerator(pbeKey
108: .getType(), pbeKey.getDigest());
109: byte[] key = pbeKey.getEncoded();
110: CipherParameters param;
111:
112: if (pbeKey.shouldTryWrongPKCS12()) {
113: key = new byte[2];
114: }
115:
116: generator.init(key, pbeParam.getSalt(), pbeParam
117: .getIterationCount());
118:
119: if (pbeKey.getIvSize() != 0) {
120: param = generator.generateDerivedParameters(pbeKey
121: .getKeySize(), pbeKey.getIvSize());
122: } else {
123: param = generator.generateDerivedParameters(pbeKey
124: .getKeySize());
125: }
126:
127: if (targetAlgorithm.startsWith("DES")) {
128: if (param instanceof ParametersWithIV) {
129: KeyParameter kParam = (KeyParameter) ((ParametersWithIV) param)
130: .getParameters();
131:
132: DESParameters.setOddParity(kParam.getKey());
133: } else {
134: KeyParameter kParam = (KeyParameter) param;
135:
136: DESParameters.setOddParity(kParam.getKey());
137: }
138: }
139:
140: for (int i = 0; i != key.length; i++) {
141: key[i] = 0;
142: }
143:
144: return param;
145: }
146:
147: /**
148: * generate a PBE based key suitable for a MAC algorithm, the
149: * key size is chosen according the MAC size, or the hashing algorithm,
150: * whichever is greater.
151: */
152: static CipherParameters makePBEMacParameters(JCEPBEKey pbeKey,
153: AlgorithmParameterSpec spec) {
154: if ((spec == null) || !(spec instanceof PBEParameterSpec)) {
155: throw new IllegalArgumentException(
156: "Need a PBEParameter spec with a PBE key.");
157: }
158:
159: PBEParameterSpec pbeParam = (PBEParameterSpec) spec;
160: PBEParametersGenerator generator = makePBEGenerator(pbeKey
161: .getType(), pbeKey.getDigest());
162: byte[] key = pbeKey.getEncoded();
163: CipherParameters param;
164:
165: if (pbeKey.shouldTryWrongPKCS12()) {
166: key = new byte[2];
167: }
168:
169: generator.init(key, pbeParam.getSalt(), pbeParam
170: .getIterationCount());
171:
172: param = generator.generateDerivedMacParameters(pbeKey
173: .getKeySize());
174:
175: for (int i = 0; i != key.length; i++) {
176: key[i] = 0;
177: }
178:
179: return param;
180: }
181:
182: /**
183: * construct a key and iv (if necessary) suitable for use with a
184: * Cipher.
185: */
186: static CipherParameters makePBEParameters(PBEKeySpec keySpec,
187: int type, int hash, int keySize, int ivSize) {
188: PBEParametersGenerator generator = makePBEGenerator(type,
189: hash);
190: byte[] key;
191: CipherParameters param;
192:
193: if (type == PKCS12) {
194: key = PBEParametersGenerator
195: .PKCS12PasswordToBytes(keySpec.getPassword());
196: } else {
197: key = PBEParametersGenerator
198: .PKCS5PasswordToBytes(keySpec.getPassword());
199: }
200:
201: generator.init(key, keySpec.getSalt(), keySpec
202: .getIterationCount());
203:
204: if (ivSize != 0) {
205: param = generator.generateDerivedParameters(keySize,
206: ivSize);
207: } else {
208: param = generator.generateDerivedParameters(keySize);
209: }
210:
211: for (int i = 0; i != key.length; i++) {
212: key[i] = 0;
213: }
214:
215: return param;
216: }
217:
218: /**
219: * generate a PBE based key suitable for a MAC algorithm, the
220: * key size is chosen according the MAC size, or the hashing algorithm,
221: * whichever is greater.
222: */
223: static CipherParameters makePBEMacParameters(
224: PBEKeySpec keySpec, int type, int hash, int keySize) {
225: PBEParametersGenerator generator = makePBEGenerator(type,
226: hash);
227: byte[] key;
228: CipherParameters param;
229:
230: if (type == PKCS12) {
231: key = PBEParametersGenerator
232: .PKCS12PasswordToBytes(keySpec.getPassword());
233: } else {
234: key = PBEParametersGenerator
235: .PKCS5PasswordToBytes(keySpec.getPassword());
236: }
237:
238: generator.init(key, keySpec.getSalt(), keySpec
239: .getIterationCount());
240:
241: param = generator.generateDerivedMacParameters(keySize);
242:
243: for (int i = 0; i != key.length; i++) {
244: key[i] = 0;
245: }
246:
247: return param;
248: }
249: }
250: }
|