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 package fr.paris.lutece.portal.service.util;
35
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.UnsupportedEncodingException;
39 import java.nio.charset.StandardCharsets;
40 import java.security.InvalidKeyException;
41 import java.security.MessageDigest;
42 import java.security.NoSuchAlgorithmException;
43 import java.util.Random;
44
45 import fr.paris.lutece.portal.service.datastore.DatastoreService;
46 import java.security.SecureRandom;
47
48 import javax.crypto.Mac;
49 import javax.crypto.spec.SecretKeySpec;
50
51
52
53
54 public final class CryptoService
55 {
56 private static final int CONSTANT_CRYPTOKEY_LENGTH_BYTES = 32;
57
58 private static final String PROPERTY_ENCODING = "lutece.encoding";
59 static final String PROPERTY_CRYPTO_KEY = "crypto.key";
60 static final String DSKEY_CRYPTO_KEY = "core." + PROPERTY_CRYPTO_KEY;
61
62
63
64
65 private CryptoService( )
66 {
67 }
68
69
70
71
72
73
74
75
76
77
78 public static String encrypt( String strDataToEncrypt, String strAlgorithm )
79 {
80 String hash = null;
81 MessageDigest md = null;
82
83 try
84 {
85 md = MessageDigest.getInstance( strAlgorithm );
86 }
87 catch( NoSuchAlgorithmException e )
88 {
89 AppLogService.error( e.getMessage( ), e );
90 }
91
92 if ( md != null )
93 {
94 try
95 {
96 hash = byteToHex( md.digest( strDataToEncrypt.getBytes( AppPropertiesService.getProperty( PROPERTY_ENCODING ) ) ) );
97 }
98 catch( UnsupportedEncodingException e )
99 {
100 AppLogService.error( e.getMessage( ), e );
101 }
102 }
103 return hash;
104 }
105
106
107
108
109
110
111
112
113
114
115
116
117 public static String digest( InputStream stream, String strAlgorithm )
118 {
119 MessageDigest digest;
120 try
121 {
122 digest = MessageDigest.getInstance( strAlgorithm );
123 }
124 catch( NoSuchAlgorithmException e )
125 {
126 AppLogService.error( "{} not found", strAlgorithm, e );
127 return null;
128 }
129 byte [ ] buffer = new byte [ 1024];
130 try
131 {
132 int nNumBytesRead = stream.read( buffer );
133 while ( nNumBytesRead != -1 )
134 {
135 digest.update( buffer, 0, nNumBytesRead );
136 nNumBytesRead = stream.read( buffer );
137 }
138 }
139 catch( IOException e )
140 {
141 AppLogService.error( "Error reading stream", e );
142 return null;
143 }
144 return byteToHex( digest.digest( ) );
145 }
146
147
148
149
150
151
152 public static String getCryptoKey( )
153 {
154 String strKey = DatastoreService.getDataValue( DSKEY_CRYPTO_KEY, null );
155 if ( strKey == null )
156 {
157
158 strKey = AppPropertiesService.getProperty( PROPERTY_CRYPTO_KEY );
159 if ( strKey == null )
160 {
161
162 Random random = new SecureRandom( );
163 byte [ ] bytes = new byte [ CONSTANT_CRYPTOKEY_LENGTH_BYTES];
164 random.nextBytes( bytes );
165 strKey = byteToHex( bytes );
166 }
167 DatastoreService.setDataValue( DSKEY_CRYPTO_KEY, strKey );
168 }
169 return strKey;
170 }
171
172
173
174
175
176
177
178
179
180 public static String hmacSHA256( String message )
181 {
182 byte [ ] keyBytes = getCryptoKey( ).getBytes( StandardCharsets.UTF_8 );
183 final String strAlg = "HmacSHA256";
184 SecretKeySpec key = new SecretKeySpec( keyBytes, strAlg );
185
186 try
187 {
188 Mac mac = Mac.getInstance( strAlg );
189 mac.init( key );
190
191 return byteToHex( mac.doFinal( message.getBytes( StandardCharsets.UTF_8 ) ) );
192 }
193 catch( NoSuchAlgorithmException e )
194 {
195 throw new AppException( "Could not find " + strAlg + " algorithm which is supposed to be supported by Java", e );
196 }
197 catch( InvalidKeyException e )
198 {
199 throw new AppException( "The key should be valid", e );
200 }
201 catch( IllegalStateException e )
202 {
203 throw new AppException( e.getMessage( ), e );
204 }
205 }
206
207
208
209
210
211
212
213
214 private static String byteToHex( byte [ ] bits )
215 {
216 if ( bits == null )
217 {
218 return null;
219 }
220
221
222 StringBuilder hex = new StringBuilder( bits.length * 2 );
223
224 for ( int i = 0; i < bits.length; i++ )
225 {
226 if ( ( (int) bits [i] & 0xff ) < 0x10 )
227 {
228
229 hex.append( "0" );
230 }
231
232
233 hex.append( Integer.toString( (int) bits [i] & 0xff, 16 ) );
234 }
235
236 return hex.toString( );
237 }
238 }