source: trunk/src/org/expeditee/auth/account/Create.java@ 1356

Last change on this file since 1356 was 1356, checked in by bln4, 5 years ago

Added pwcolleagues.inf file

File size: 13.2 KB
Line 
1package org.expeditee.auth.account;
2
3import java.io.File;
4import java.io.FileWriter;
5import java.io.IOException;
6import java.nio.file.Path;
7import java.nio.file.Paths;
8import java.security.KeyPair;
9import java.security.KeyPairGenerator;
10import java.security.KeyStoreException;
11import java.security.NoSuchAlgorithmException;
12import java.security.SecureRandom;
13import java.security.cert.CertificateException;
14import java.sql.SQLException;
15import java.util.Base64;
16import java.util.Collection;
17import java.util.HashMap;
18import java.util.Map;
19import java.util.Random;
20import java.util.function.Consumer;
21
22import javax.crypto.SecretKey;
23import javax.crypto.spec.SecretKeySpec;
24
25import org.apollo.io.AudioPathManager;
26import org.expeditee.agents.ExistingFramesetException;
27import org.expeditee.agents.InvalidFramesetNameException;
28import org.expeditee.auth.Actions;
29import org.expeditee.auth.AuthenticatorBrowser;
30import org.expeditee.auth.tags.AuthenticationTag;
31import org.expeditee.core.Colour;
32import org.expeditee.gui.DisplayController;
33import org.expeditee.gui.Frame;
34import org.expeditee.gui.FrameIO;
35import org.expeditee.gui.MessageBay;
36import org.expeditee.gui.MessageBay.Progress;
37import org.expeditee.io.ExpReader;
38import org.expeditee.items.Item;
39import org.expeditee.items.PermissionPair;
40import org.expeditee.items.Text;
41import org.expeditee.items.UserAppliedPermission;
42import org.expeditee.setting.GenericSetting;
43import org.expeditee.setting.Setting;
44import org.expeditee.setting.TextSetting;
45import org.expeditee.settings.UserSettings;
46import org.expeditee.settings.folders.FolderSettings;
47import org.expeditee.settings.identity.secrets.KeyList;
48import org.ngikm.cryptography.CryptographyConstants;
49
50public class Create implements CryptographyConstants {
51
52 /**
53 * Create a user account using the specified information in userdata. Creates and stores user keys.
54 * @param userdata Should contain username, password and email.
55 */
56 public static CreateResult createAccount(Map<AuthenticationTag, String> userdata) {
57 // Track progress
58 String message = "Creating new user account...";
59 int progress = 0;
60 int step = 16;
61
62 // Extract user details
63 String username = userdata.get(AuthenticationTag.Username);
64 String password = userdata.get(AuthenticationTag.Password);
65 String email = userdata.get(AuthenticationTag.Email);
66
67 Progress progressBar = MessageBay.displayProgress(message);
68 progress = progress(message + "Generating Keys.", progress, step, progressBar);
69
70 // Generate keys
71 // Personal key
72 String personalKey = generatePersonalKey(username, password);
73 if (personalKey == null) {
74 return CreateResult.ErrorSymmetricKey;
75 }
76 // Public and private keys
77 String[] keys = generateAsymmetricKeys();
78 if (keys == null) {
79 return CreateResult.ErrorAsymmetricKeys;
80 }
81 String privateKey = keys[0];
82 String publicKey = keys[1];
83
84 progress = progress(message + "Creating Profile Frameset.", progress, step, progressBar);
85
86 // Update in memory settings
87 System.setProperty("user.name", username);
88 UserSettings.UserName.set(username);
89 UserSettings.ProfileName.set(username);
90 UserSettings.setupDefaultFolders();
91
92 Frame profile;
93 try {
94 profile = createNewProfile(username, email, personalKey, privateKey, publicKey);
95 } catch (InvalidFramesetNameException | ExistingFramesetException e) {
96 return CreateResult.ErrorNewProfile;
97 }
98
99 if (AuthenticatorBrowser.CREDENTIALS_FRAME == -1) {
100 return CreateResult.ErrorCredentialsFrame;
101 }
102
103 progress = progress(message + "Establishing user credentials.", progress, step, progressBar);
104
105 // Create credentials
106 boolean success = setupCredentialsFrameAndINFs(username, profile);
107 if (!success) {
108 return CreateResult.ErrorIODuringCredentialsFrameSetup;
109 }
110
111 progress = progress(message + "Creating Individual Space.", progress, step, progressBar);
112
113 // Copy private resources to personal area
114 Path personalResources = createPersonalArea(username);
115
116 progress = progress(message + "Creating Space For Dead Drops.", progress, step, progressBar);
117
118 createDeaddropsArea(personalResources);
119
120 System.err.println("**** Hardwired call in Apollo's AuthioPathManager");
121 AudioPathManager.activateAndScanAudioDir(); // ****
122
123 progress = progress(message + "Done.", progress, step, progressBar);
124
125 return CreateResult.SuccessCreateAccount;
126 }
127
128 public static CreateResult createAlternativeAccess(Map<AuthenticationTag, String> userdata) {
129 String username = userdata.get(AuthenticationTag.Username);
130 FrameIO.CreateFrame(username, null, "default1");
131 return null;
132 }
133
134 public enum CreateResult {
135 SuccessCreateAccount ("Account created."),
136 SuccessAlternativeAccount ("Alternative access to account established."),
137 ErrorSymmetricKey ("An error occured while trying to generate your personal key."),
138 ErrorAsymmetricKeys ("An error occured while trying to generate asymmetric keys."),
139 ErrorNewProfile ("An error occured while creating the profile frames."),
140 ErrorCredentialsFrame ("Unable to establish credentials frame for new profile frame."),
141 ErrorIODuringCredentialsFrameSetup ("An error occured during the setup of the new users credentials frame.");
142
143 private String message = null;
144
145 private CreateResult(String message) {
146 this.message = message;
147 }
148
149 public String toString() {
150 return message;
151 }
152 }
153
154 private static int progress(String message, int progress, int step, Progress progressBar) {
155 try {
156 progressBar.UpdateMessage(message, progress += step);
157 } catch (Exception e) {
158 e.printStackTrace();
159 }
160 DisplayController.refreshBayArea();
161 return progress;
162 }
163
164 private static void createDeaddropsArea(Path personalResources) {
165 File deadDropsDir = new File(personalResources.resolve("deaddrops").toAbsolutePath().toString());
166 deadDropsDir.mkdir();
167 }
168
169 private static Path createPersonalArea(String username) {
170 Path personalResources = UserSettings.PublicAndPrivateResources ? FrameIO.setupPersonalResources(username) : Paths.get(FrameIO.PARENT_FOLDER);
171
172 File contactsDir = new File(personalResources.resolve("contacts").toAbsolutePath().toString());
173 contactsDir.mkdir();
174 return personalResources;
175 }
176
177 private static boolean setupCredentialsFrameAndINFs(String username, Frame profile) {
178 try {
179 File credentialsDir = new File(profile.getFramesetPath() + username + "-credentials");
180 credentialsDir.mkdir();
181 // credentials.inf file.
182 String credentialsPath = credentialsDir.getAbsolutePath() + File.separator + "credentials.inf";
183 File credentialsFile = new File(credentialsPath);
184 credentialsFile.createNewFile();
185 FileWriter out = new FileWriter(credentialsFile);
186 out.write(AuthenticatorBrowser.CREDENTIALS_FRAME + ".exp");
187 out.flush();
188 out.close();
189 // migrate credentials frame
190 Frame credentialsFrame = FrameIO.LoadFrame(username + AuthenticatorBrowser.CREDENTIALS_FRAME);
191 Path destinationDirectory = Paths.get(credentialsDir.getAbsolutePath());
192 Path destinationFile = destinationDirectory.resolve(AuthenticatorBrowser.CREDENTIALS_FRAME + ExpReader.EXTENTION);
193 FrameIO.migrateFrame(credentialsFrame, destinationFile);
194 // pwcolleagues.inf file.
195 String pwColleaguesPath = credentialsDir.getAbsolutePath() + File.separator + "pwcolleagues.inf";
196 File pwColleaguesFile = new File(pwColleaguesPath);
197 pwColleaguesFile.createNewFile();
198 out = new FileWriter(pwColleaguesFile);
199 out.write(AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME + ".exp");
200 out.flush();
201 out.close();
202 return true;
203 } catch (IOException e) {
204 return false;
205 }
206 }
207
208 private static Frame createNewProfile(String username, String email, String personalKey, String privateKey,
209 String publicKey) throws InvalidFramesetNameException, ExistingFramesetException {
210 // Establish the initial settings for the created user.
211 Map<String, Setting> initialSettings = new HashMap<String, Setting>();
212 initialSettings.put("settings.identity.secrets.PersonalKey", constructTextSetting("The AES key used to secure your profile frame - do not share with anyone!", "PersonalKey", personalKey));
213 initialSettings.put("settings.identity.secrets.PrivateKey", constructTextSetting("The RSA key used to decrypt things encrypted with your RSA public key - do not share with anyone!", "PrivateKey", privateKey));
214 initialSettings.put("settings.identity.PublicKey", constructTextSetting("The RSA key used to decrypt things encrypted with your RSA public key.", "PublicKey", publicKey));
215 initialSettings.put("settings.identity.Email", constructGenericSetting(String.class, "Your public-facing email address.", "Email", email, username));
216 initialSettings.put("settings.UserSettings.UserName", constructGenericSetting(String.class, "Username", "Username", username, username));
217 initialSettings.put("settings.UserSettings.ProfileName", constructGenericSetting(String.class, "Profilename", "Profilename", username, username));
218 initialSettings.put("settings.UserSettings.HomeFrame", constructGenericSetting(String.class, "The home frame", "HomeFrame", username + 1, username));
219 initialSettings.put("org.expeditee.gui.folders.FolderSettings.FrameDirs", FolderSettings.FrameDirs);
220 initialSettings.put("org.expeditee.gui.folders.FolderSettings.ImageDirs", FolderSettings.ImageDirs);
221 initialSettings.put("org.expeditee.gui.folders.FolderSettings.AudioDirs", FolderSettings.AudioDirs);
222
223 // Record the credentials frame number and password colleagues frame
224 Map<String, Consumer<Frame>> notifiers = new HashMap<String, Consumer<Frame>>();
225 notifiers.put("settings.identity", frame -> {
226 AuthenticatorBrowser.CREDENTIALS_FRAME = frame.getNumber();
227 frame.addToData("MultiuserCredentials");
228 Collection<Text> textItems = frame.getTextItems();
229 for (Text t: textItems) {
230 if (t.getText().equals("Secrets")) {
231 t.setPermission(new PermissionPair(UserAppliedPermission.followLinks, UserAppliedPermission.denied));
232 break;
233 }
234 }
235 });
236 notifiers.put("settings.identity.passwordrecovery", frame -> {
237 AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME = frame.getNumber();
238 });
239
240
241 // Create users profile
242 Frame profile = FrameIO.CreateNewProfile(username, initialSettings, notifiers);
243 int lastNumber = FrameIO.getLastNumber(profile.getFramesetName());
244 for (int i = 1; i <= lastNumber; i++) {
245 Frame f = FrameIO.LoadFrame(profile.getFramesetName() + i);
246 Text titleItem = f.getTitleItem();
247 if (i == 1 && titleItem != null) {
248 titleItem.delete();
249 f.setBackgroundColor(new Colour(1, 1, 0.39f));
250 }
251 f.setOwner(username);
252 f.getAllItems().stream().forEach(item -> item.setOwner(username));
253 f.setChanged(true);
254 if (f.getNumber() != AuthenticatorBrowser.CREDENTIALS_FRAME &&
255 f.getNumber() != AuthenticatorBrowser.PASSWORD_RECOVERY_FRAME) {
256 f.setEncryptionLabel(AuthenticatorBrowser.PROFILEENCRYPTIONLABEL);
257 }
258 Collection<Item> secretsLink = Actions.getByContent(f, "Secrets");
259 Collection<Item> publicKeyItem = Actions.getByContent(f, "PublicKey");
260 if (!secretsLink.isEmpty() && !publicKeyItem.isEmpty()) {
261 //Then we are on credentials frame
262 f.addToData("MultiuserCredentials");
263 }
264 Text backupPersonalKey = KeyList.PersonalKey.get();
265 Text tempPersonalKey = KeyList.PersonalKey.generateText();
266 tempPersonalKey.setData(personalKey);
267 KeyList.PersonalKey.setSetting(tempPersonalKey);
268 FrameIO.SaveFrame(f);
269 KeyList.PersonalKey.setSetting(backupPersonalKey);
270 }
271 return profile;
272 }
273
274 private static String generatePersonalKey(String username, String password) {
275 try {
276 Random rand = new SecureRandom();
277 byte[] keyBytes = new byte[16];
278 rand.nextBytes(keyBytes);
279 SecretKey key = new SecretKeySpec(keyBytes, SymmetricAlgorithm);
280 AuthenticatorBrowser.getInstance().putKey(username, password, key);
281 String personalKey = Base64.getEncoder().encodeToString(key.getEncoded());
282 return personalKey;
283 } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | ClassNotFoundException
284 | IOException | SQLException e) {
285 return null;
286 }
287 }
288
289 private static String[] generateAsymmetricKeys() {
290 try {
291 KeyPairGenerator keyGen = KeyPairGenerator.getInstance(AsymmetricAlgorithm);
292 keyGen.initialize(1024);
293 KeyPair keyPair = keyGen.generateKeyPair();
294 String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
295 String privateKey = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());
296 return new String[] { privateKey, publicKey };
297 } catch (NoSuchAlgorithmException e) {
298 return null;
299 }
300 }
301
302 private static TextSetting constructTextSetting(String tooltip, String text, String data) {
303 return new TextSetting(tooltip, text) {
304 @Override
305 public Text generateText() {
306 Text t = new Text(text);
307 t.setData(data);
308 return t;
309 }
310 };
311 }
312
313 private static <T> GenericSetting<T> constructGenericSetting(Class<T> type, String tooltip, String name, T value, String frameset) {
314 return new GenericSetting<T>(type, tooltip, name, value) {
315 @Override
316 public Text generateRepresentation(String name, String frameset) {
317 Text t = new Text(name + ": " + value);
318 return t;
319 }
320 };
321 }
322}
Note: See TracBrowser for help on using the repository browser.