X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=server%2Fruntime%2Forg.argeo.server.jcr%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fjcr%2Fsecurity%2FJcrKeyring.java;h=a35bbd2724a878f30bc8cdd0a3d15f6b25d67d57;hb=2134dd19734711b05710c1250b665c32fbe7263c;hp=7d9baad956ed9b9481230619ed80b4cafbc6a6cc;hpb=78469faf92044c7ad7b3a829ae2b5e4f943748b7;p=lgpl%2Fargeo-commons.git diff --git a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java index 7d9baad95..a35bbd272 100644 --- a/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java +++ b/server/runtime/org.argeo.server.jcr/src/main/java/org/argeo/jcr/security/JcrKeyring.java @@ -1,7 +1,23 @@ +/* + * Copyright (C) 2007-2012 Mathieu Baudier + * + * 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.jcr.security; import java.io.ByteArrayInputStream; import java.io.InputStream; +import java.security.SecureRandom; import javax.crypto.Cipher; import javax.crypto.CipherInputStream; @@ -18,6 +34,7 @@ import org.argeo.ArgeoException; import org.argeo.jcr.ArgeoNames; import org.argeo.jcr.ArgeoTypes; import org.argeo.jcr.JcrUtils; +import org.argeo.jcr.UserJcrUtils; import org.argeo.util.crypto.AbstractKeyring; import org.argeo.util.crypto.PBEKeySpecCallback; @@ -46,7 +63,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { if (notYetSavedKeyring.get() != null) return true; - Node userHome = JcrUtils.getUserHome(session); + Node userHome = UserJcrUtils.getUserHome(session); return userHome.hasNode(ARGEO_KEYRING); } catch (RepositoryException e) { throw new ArgeoException("Cannot check whether keyring is setup", e); @@ -54,11 +71,11 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { } @Override - protected void setup() { + protected void setup(char[] password) { Binary binary = null; InputStream in = null; try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = UserJcrUtils.getUserHome(session); if (userHome.hasNode(ARGEO_KEYRING)) throw new ArgeoException("Keyring already setup"); Node keyring = userHome.addNode(ARGEO_KEYRING); @@ -78,7 +95,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { binary = session.getValueFactory().createBinary(in); keyring.setProperty(ARGEO_SALT, binary); - Long iterationCount = username.length() * 200l; + Integer iterationCount = username.length() * 200; keyring.setProperty(ARGEO_ITERATION_COUNT, iterationCount); // default algo @@ -88,8 +105,16 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { keyring.setProperty(ARGEO_SECRET_KEY_ENCRYPTION, "AES"); keyring.setProperty(ARGEO_CIPHER, "AES/CBC/PKCS5Padding"); + // encrypted password hash + // IOUtils.closeQuietly(in); + // JcrUtils.closeQuietly(binary); + // byte[] btPass = hash(password, salt, iterationCount); + // in = new ByteArrayInputStream(btPass); + // binary = session.getValueFactory().createBinary(in); + // keyring.setProperty(ARGEO_PASSWORD, binary); + notYetSavedKeyring.set(keyring); - } catch (RepositoryException e) { + } catch (Exception e) { throw new ArgeoException("Cannot setup keyring", e); } finally { JcrUtils.closeQuietly(binary); @@ -101,7 +126,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { @Override protected void handleKeySpecCallback(PBEKeySpecCallback pbeCallback) { try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = UserJcrUtils.getUserHome(session); Node keyring; if (userHome.hasNode(ARGEO_KEYRING)) keyring = userHome.getNode(ARGEO_KEYRING); @@ -109,6 +134,7 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { keyring = notYetSavedKeyring.get(); else throw new ArgeoException("Keyring not setup"); + pbeCallback.set(keyring.getProperty(ARGEO_SECRET_KEY_FACTORY) .getString(), JcrUtils.getBinaryAsBytes(keyring .getProperty(ARGEO_SALT)), @@ -124,40 +150,67 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { } } - /** The node must already exist at this path */ + /** The node must already exist at this path. Session is saved. */ @Override - protected void encrypt(String path, InputStream unencrypted) { + protected synchronized void encrypt(String path, InputStream unencrypted) { // should be called first for lazy initialization SecretKey secretKey = getSecretKey(); Binary binary = null; InputStream in = null; + // ByteArrayOutputStream out = null; + // OutputStream encrypted = null; try { Cipher cipher = createCipher(); if (!session.nodeExists(path)) throw new ArgeoException("No node at " + path); + if (session.hasPendingChanges()) + session.save(); Node node = session.getNode(path); node.addMixin(ArgeoTypes.ARGEO_ENCRYPTED); - cipher.init(Cipher.ENCRYPT_MODE, secretKey); - byte[] iv = cipher.getIV(); - if (iv != null) { - JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); - } + SecureRandom random = new SecureRandom(); + byte[] iv = new byte[16]; + random.nextBytes(iv); + cipher.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(iv)); + // AlgorithmParameters params = cipher.getParameters(); + // byte[] iv = + // params.getParameterSpec(IvParameterSpec.class).getIV(); + // if (iv != null) + JcrUtils.setBinaryAsBytes(node, ARGEO_IV, iv); + + // out = new ByteArrayOutputStream(); + // // encrypted = new CipherOutputStream(out, cipher); + // IOUtils.copy(unencrypted, out); + // byte[] unenc = out.toByteArray(); + // byte[] crypted = cipher.doFinal(unenc); + + // Cipher decipher = createCipher(); + // decipher.init(Cipher.DECRYPT_MODE, secretKey, new + // IvParameterSpec( + // iv)); + // byte[] decrypted = decipher.doFinal(crypted); + // System.out.println("Password :'" + new String(decrypted) + "'"); + + // JcrUtils.setBinaryAsBytes(node, Property.JCR_DATA, crypted); + in = new CipherInputStream(unencrypted, cipher); binary = session.getValueFactory().createBinary(in); node.setProperty(Property.JCR_DATA, binary); + session.save(); } catch (Exception e) { throw new ArgeoException("Cannot encrypt", e); } finally { - IOUtils.closeQuietly(in); + // IOUtils.closeQuietly(out); + // IOUtils.closeQuietly(encrypted); IOUtils.closeQuietly(unencrypted); + IOUtils.closeQuietly(in); JcrUtils.closeQuietly(binary); } } @Override - protected InputStream decrypt(String path) { + protected synchronized InputStream decrypt(String path) { // should be called first for lazy initialization SecretKey secretKey = getSecretKey(); @@ -177,20 +230,27 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { } else { cipher.init(Cipher.DECRYPT_MODE, secretKey); } + + // byte[] arr = JcrUtils.getBinaryAsBytes(node + // .getProperty(Property.JCR_DATA)); + // byte[] arr2 = cipher.doFinal(arr); + // + // return new ByteArrayInputStream(arr2); + binary = node.getProperty(Property.JCR_DATA).getBinary(); encrypted = binary.getStream(); return new CipherInputStream(encrypted, cipher); } catch (Exception e) { throw new ArgeoException("Cannot decrypt", e); } finally { - // IOUtils.closeQuietly(encrypted); + IOUtils.closeQuietly(encrypted); JcrUtils.closeQuietly(binary); } } protected Cipher createCipher() { try { - Node userHome = JcrUtils.getUserHome(session); + Node userHome = UserJcrUtils.getUserHome(session); if (!userHome.hasNode(ARGEO_KEYRING)) throw new ArgeoException("Keyring not setup"); Node keyring = userHome.getNode(ARGEO_KEYRING); @@ -202,16 +262,16 @@ public class JcrKeyring extends AbstractKeyring implements ArgeoNames { } } - public void changePassword(char[] oldPassword, char[] newPassword) { - // TODO Auto-generated method stub - + public synchronized void changePassword(char[] oldPassword, + char[] newPassword) { + // TODO decrypt with old pw / encrypt with new pw all argeo:encrypted } - public Session getSession() { + public synchronized Session getSession() { return session; } - public void setSession(Session session) { + public synchronized void setSession(Session session) { this.session = session; }