]> git.argeo.org Git - lgpl/argeo-commons.git/blobdiff - basic/runtime/org.argeo.basic.nodeps/src/main/java/org/argeo/util/crypto/KeyringLoginModule.java
Introduce Keyring
[lgpl/argeo-commons.git] / basic / runtime / org.argeo.basic.nodeps / src / main / java / org / argeo / util / crypto / KeyringLoginModule.java
diff --git a/basic/runtime/org.argeo.basic.nodeps/src/main/java/org/argeo/util/crypto/KeyringLoginModule.java b/basic/runtime/org.argeo.basic.nodeps/src/main/java/org/argeo/util/crypto/KeyringLoginModule.java
new file mode 100644 (file)
index 0000000..a53295c
--- /dev/null
@@ -0,0 +1,87 @@
+package org.argeo.util.crypto;
+
+import java.security.AccessController;
+import java.util.Map;
+import java.util.Set;
+
+import javax.crypto.SecretKey;
+import javax.crypto.SecretKeyFactory;
+import javax.crypto.spec.PBEKeySpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.login.LoginException;
+import javax.security.auth.spi.LoginModule;
+
+/** Adds a secret key to the private credentials */
+public class KeyringLoginModule implements LoginModule {
+       private Subject subject;
+       private CallbackHandler callbackHandler;
+       private SecretKey secretKey;
+
+       public void initialize(Subject subject, CallbackHandler callbackHandler,
+                       Map<String, ?> sharedState, Map<String, ?> options) {
+               this.subject = subject;
+               if (subject == null) {
+                       subject = Subject.getSubject(AccessController.getContext());
+               }
+               this.callbackHandler = callbackHandler;
+       }
+
+       public boolean login() throws LoginException {
+               Set<SecretKey> pbes = subject.getPrivateCredentials(SecretKey.class);
+               if (pbes.size() > 0)
+                       return true;
+               PasswordCallback pc = new PasswordCallback("Master password", false);
+               PBEKeySpecCallback pbeCb = new PBEKeySpecCallback();
+               Callback[] callbacks = { pc, pbeCb };
+               try {
+                       callbackHandler.handle(callbacks);
+                       char[] password = pc.getPassword();
+
+                       SecretKeyFactory keyFac = SecretKeyFactory.getInstance(pbeCb
+                                       .getSecretKeyFactory());
+                       PBEKeySpec keySpec;
+                       if (pbeCb.getKeyLength() != null)
+                               keySpec = new PBEKeySpec(password, pbeCb.getSalt(),
+                                               pbeCb.getIterationCount(), pbeCb.getKeyLength());
+                       else
+                               keySpec = new PBEKeySpec(password, pbeCb.getSalt(),
+                                               pbeCb.getIterationCount());
+
+                       String secKeyEncryption = pbeCb.getSecretKeyEncryption();
+                       if (secKeyEncryption != null) {
+                               SecretKey tmp = keyFac.generateSecret(keySpec);
+                               secretKey = new SecretKeySpec(tmp.getEncoded(),
+                                               secKeyEncryption);
+                       } else {
+                               secretKey = keyFac.generateSecret(keySpec);
+                       }
+               } catch (Exception e) {
+                       LoginException le = new LoginException("Cannot login keyring");
+                       le.initCause(e);
+                       throw le;
+               }
+               return true;
+       }
+
+       public boolean commit() throws LoginException {
+               if (secretKey != null)
+                       subject.getPrivateCredentials().add(secretKey);
+               return true;
+       }
+
+       public boolean abort() throws LoginException {
+               return true;
+       }
+
+       public boolean logout() throws LoginException {
+               Set<PasswordBasedEncryption> pbes = subject
+                               .getPrivateCredentials(PasswordBasedEncryption.class);
+               pbes.clear();
+               return true;
+       }
+
+}