X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=org.argeo.security.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fcrypto%2FKeyringLoginModule.java;fp=org.argeo.security.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fsecurity%2Fcrypto%2FKeyringLoginModule.java;h=34b7d40155d212e0e4793224aac104a6fc7dc90a;hb=1df1bf64759d35d3d72b9d96b26b71118fdbe031;hp=0000000000000000000000000000000000000000;hpb=3a3d316af102ba410d1d9e6de349d0c8f7ac044f;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java new file mode 100644 index 000000000..34b7d4015 --- /dev/null +++ b/org.argeo.security.core/src/main/java/org/argeo/security/crypto/KeyringLoginModule.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.security.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 sharedState, Map options) { + this.subject = subject; + if (subject == null) { + subject = Subject.getSubject(AccessController.getContext()); + } + this.callbackHandler = callbackHandler; + } + + public boolean login() throws LoginException { + Set 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 pbes = subject + .getPrivateCredentials(PasswordBasedEncryption.class); + pbes.clear(); + return true; + } + +}