summaryrefslogtreecommitdiffstats
blob: 1353225570b5e85f9c22b4fd25c2874fb097cd36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*
 * Copyright (c) 2011-2015 Isode Limited, London, England.
 * All rights reserved.
 */
/*
 * Copyright (c) 2015 Tarun Gupta.
 * Licensed under the simplified BSD license.
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 */

package com.isode.stroke.crypto;

import com.isode.stroke.crypto.CryptoProvider;
import com.isode.stroke.crypto.Hash;
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.base.SafeByteArray;
import com.isode.stroke.base.NotNull;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.InvalidKeyException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.lang.IllegalStateException;

public class JavaCryptoProvider extends CryptoProvider {

	private static class HashProvider implements Hash {

		private final MessageDigest digest;

		/**
		* Constructor, MessageDigest object that implements MD5 / SHA1.
		*/
		public HashProvider(String algorithm) {
			try {
				digest = MessageDigest.getInstance(algorithm);
			}
			catch (NoSuchAlgorithmException e) {
				throw new RuntimeException(e.getMessage());
			}
		}

		/**
		* Updates the digest using the ByteArray.
		* @param data, NotNull.
		* @return Hash updated with data.
		*/
		@Override
		public Hash update(ByteArray data) {
			NotNull.exceptIfNull(data, "data");
			digest.update(data.getData());
			return this;
		}

		/**
		* Updates the digest using the SafeByteArray.
		* @param data, NotNull.
		* @return Hash updated with data.
		*/
		@Override
		public Hash update(SafeByteArray data) {
			NotNull.exceptIfNull(data, "data");
			digest.update(data.getData());
			return this;
		}

		/**
		* Completes the MD5/SHA1 hash computation.
		* @return ByteArray containing the MD5/SHA1 Hash.
		*/
		@Override
		public ByteArray getHash() {
			return new ByteArray(digest.digest());
		}

	}

	/**
	* Computes the HMACSHA1 hash computation.
	* @param key NotNull. Key is used for initializing MAC object.
	* @param data NotNull.
	* @return ByteArray containing the HMACSHA1 Hash.
	*/
	public ByteArray getHMACSHA1Internal(final ByteArray key, final ByteArray data) {
		NotNull.exceptIfNull(key, "key");
		NotNull.exceptIfNull(data, "data");
		try {
			SecretKeySpec signingKey = new SecretKeySpec(key.getData(), "HmacSHA1");
			Mac mac = Mac.getInstance("HmacSHA1");
			mac.init(signingKey);
			mac.update(data.getData());
			byte[] Hmac = mac.doFinal();
			return (new ByteArray(Hmac));
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e.getMessage());
		} catch (InvalidKeyException e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	/**
	* Creates the SHA1Hash object for performing hash computations.
	* @return SHA1Hash object.
	*/
	@Override
	public Hash createSHA1() {
		return new HashProvider("SHA-1");
	}

	/**
	* Creates the SHA1Hash object for performing hash computations.
	* @return MD5Hash object.
	*/
	@Override
	public Hash createMD5() {
		return new HashProvider("MD5");
	}

	/**
	* @param key, NotNull.
	* @param data, NotNull.
	* @return ByteArray containing the HMACSHA1 Hash.
	*/
	@Override
	public ByteArray getHMACSHA1(final SafeByteArray key, final ByteArray data) {
		return getHMACSHA1Internal(key, data);
	}

	/**
	* @param key, NotNull.
	* @param data, NotNull.
	* @return ByteArray containing the HMACSHA1 Hash.
	*/
	@Override
	public ByteArray getHMACSHA1(final ByteArray key, final ByteArray data) {
		return getHMACSHA1Internal(key, data);
	}

	@Override
	public boolean isMD5AllowedForCrypto() {
		return false;
	}
}