View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.common.crypto;
21  
22  import org.waarp.common.exception.CryptoException;
23  import org.waarp.common.file.FileUtils;
24  
25  import java.io.File;
26  import java.io.FileInputStream;
27  import java.io.FileNotFoundException;
28  import java.io.IOException;
29  import java.security.NoSuchAlgorithmException;
30  import java.util.Enumeration;
31  import java.util.LinkedList;
32  import java.util.List;
33  import java.util.concurrent.ConcurrentHashMap;
34  import java.util.concurrent.atomic.AtomicBoolean;
35  
36  /**
37   * This class implements a simple Key Manager from name
38   */
39  public abstract class KeyManager {
40    final ConcurrentHashMap<String, KeyObject> keysConcurrentHashMap =
41        new ConcurrentHashMap<String, KeyObject>();
42    final AtomicBoolean isInitialized = new AtomicBoolean(false);
43  
44    public abstract KeyObject createKeyObject();
45  
46    /**
47     * Init the Manager from a list of filename Key, the key name is the
48     * basename
49     * minus the extension of the key's
50     * type
51     *
52     * @param keys
53     *
54     * @return the list of wrong keys
55     */
56    public List<String> initFromList(final List<String> keys) {
57      final LinkedList<String> wrong = new LinkedList<String>();
58      for (final String filename : keys) {
59        final File file = new File(filename);
60        if (file.canRead()) {
61          final String basename = file.getName();
62          final int lastpos = basename.lastIndexOf('.');
63          if (lastpos <= 0) {
64            wrong.add(filename);
65            continue;
66          }
67          final String firstname = basename.substring(0, lastpos);
68          int len = (int) file.length();
69          final byte[] key = new byte[len];
70          final FileInputStream inputStream;
71          try {
72            inputStream = new FileInputStream(file);
73          } catch (final FileNotFoundException e) {
74            // should not be
75            wrong.add(filename);
76            continue;
77          }
78          int read = 1;
79          int offset = 0;
80          while (read > 0) {
81            try {
82              read = inputStream.read(key, offset, len);
83            } catch (final IOException e) {
84              wrong.add(filename);
85              read = -2;
86              break;
87            }
88            offset += read;
89            if (offset < len) {
90              len -= read;
91            } else {
92              break;
93            }
94          }
95          FileUtils.close(inputStream);
96          if (read < -1) {
97            // wrong
98            continue;
99          }
100         final KeyObject keyObject = createKeyObject();
101         keyObject.setSecretKey(key);
102         setKey(firstname, keyObject);
103       } else {
104         wrong.add(filename);
105       }
106     }
107     isInitialized.set(true);
108     return wrong;
109   }
110 
111   public void saveToFiles() throws CryptoException, IOException {
112     final Enumeration<String> names = keysConcurrentHashMap.keys();
113     while (names.hasMoreElements()) {
114       final String name = names.nextElement();
115       final KeyObject key = keysConcurrentHashMap.get(name);
116       key.saveSecretKey(new File(name + '.' + key.getFileExtension()));
117     }
118   }
119 
120   /**
121    * Add or set a new key associated to the given name
122    *
123    * @param name
124    * @param keyObject
125    */
126   public final void setKey(final String name, final KeyObject keyObject) {
127     keysConcurrentHashMap.put(name, keyObject);
128   }
129 
130   /**
131    * @param name
132    *
133    * @return the key associated to the given name
134    */
135   public final KeyObject getKey(final String name) {
136     return keysConcurrentHashMap.get(name);
137   }
138 
139   /**
140    * One method to get the crypted String from the given string and key
141    *
142    * @param keyName
143    * @param toBeCrypted
144    *
145    * @return the crypted String
146    *
147    * @throws Exception
148    */
149   public final String crypt(final String keyName, final String toBeCrypted)
150       throws Exception {
151     final KeyObject keyObject = getKey(keyName);
152     if (keyObject == null) {
153       throw new NoSuchAlgorithmException("Key does not exist: " + keyName);
154     }
155     return keyObject.cryptToHex(toBeCrypted);
156   }
157 
158   /**
159    * One method to get the uncrypted String from the given crypted string and
160    * key
161    *
162    * @param keyName
163    * @param toBeDecrypted
164    *
165    * @return the uncrypted String
166    *
167    * @throws Exception
168    */
169   public final String decrypt(final String keyName, final String toBeDecrypted)
170       throws Exception {
171     final KeyObject keyObject = getKey(keyName);
172     if (keyObject == null) {
173       throw new NoSuchAlgorithmException("Key does not exist: " + keyName);
174     }
175     return keyObject.decryptHexInString(toBeDecrypted);
176   }
177 
178 }