Repository: openmeetings Updated Branches: refs/heads/master 8e63647cd -> 297726b74
no jira: SCrypt should be used for password hashing Project: http://git-wip-us.apache.org/repos/asf/openmeetings/repo Commit: http://git-wip-us.apache.org/repos/asf/openmeetings/commit/297726b7 Tree: http://git-wip-us.apache.org/repos/asf/openmeetings/tree/297726b7 Diff: http://git-wip-us.apache.org/repos/asf/openmeetings/diff/297726b7 Branch: refs/heads/master Commit: 297726b74bbc14b2f7c45501e098364e6a7e3d08 Parents: 8e63647 Author: Maxim Solodovnik <[email protected]> Authored: Thu May 18 23:07:52 2017 +0700 Committer: Maxim Solodovnik <[email protected]> Committed: Thu May 18 23:09:26 2017 +0700 ---------------------------------------------------------------------- .../openmeetings/db/entity/user/User.java | 36 +- .../apache/openmeetings/db/util/UserHelper.java | 4 +- .../openmeetings/backup/BackupImport.java | 4 +- .../installation/InstallationConfig.java | 4 +- .../src/site/xdoc/CustomCryptMechanism.xml | 69 +--- .../openmeetings/util/crypt/MD5Crypt.java | 381 ------------------- .../util/crypt/MD5CryptImplementation.java | 62 --- .../util/crypt/MD5Implementation.java | 54 --- .../util/crypt/SCryptImplementation.java | 87 +++++ .../apache/openmeetings/util/crypt/SHA256.java | 35 -- .../util/crypt/SHA256Implementation.java | 101 ----- .../openmeetings/util/crypt/TestSCrypt.java | 28 ++ .../apache/openmeetings/util/crypt/TestSHA.java | 28 -- 13 files changed, 152 insertions(+), 741 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/user/User.java ---------------------------------------------------------------------- diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/user/User.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/user/User.java index 4d09d69..3417837 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/user/User.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/entity/user/User.java @@ -67,9 +67,9 @@ import org.simpleframework.xml.Root; /** * Entity to store user data, password field is {@link FetchType#LAZY}, so that * is why there is an extra udpate statement at this moment - * + * * @author sebawagner, solomax - * + * */ @Entity @FetchGroups({ @@ -82,7 +82,7 @@ import org.simpleframework.xml.Root; @NamedQuery(name = "getUserByLogin", query = "SELECT u FROM User u WHERE u.deleted = false AND u.type = :type AND u.login = :login AND ((:domainId = 0 AND u.domainId IS NULL) OR (:domainId > 0 AND u.domainId = :domainId))"), @NamedQuery(name = "getUserByEmail", query = "SELECT u FROM User u WHERE u.deleted = false AND u.type = :type AND u.address.email = :email AND ((:domainId = 0 AND u.domainId IS NULL) OR (:domainId > 0 AND u.domainId = :domainId))"), @NamedQuery(name = "getUserByHash", query = "SELECT u FROM User u WHERE u.deleted = false AND u.type = :type AND u.resethash = :resethash"), - @NamedQuery(name = "getContactByEmailAndUser", query = "SELECT u FROM User u WHERE u.deleted = false AND u.address.email = :email AND u.type = :type AND u.ownerId = :ownerId"), + @NamedQuery(name = "getContactByEmailAndUser", query = "SELECT u FROM User u WHERE u.deleted = false AND u.address.email = :email AND u.type = :type AND u.ownerId = :ownerId"), @NamedQuery(name = "selectMaxFromUsersWithSearch", query = "select count(c.id) from User c " + "where c.deleted = false " + "AND (" + "lower(c.login) LIKE :search " @@ -93,7 +93,7 @@ import org.simpleframework.xml.Root; @NamedQuery(name = "updatePassword", query = "UPDATE User u SET u.password = :password WHERE u.id = :userId"), // @NamedQuery(name = "getNondeletedUsers", query = "SELECT u FROM User u WHERE u.deleted = false"), @NamedQuery(name = "countNondeletedUsers", query = "SELECT COUNT(u) FROM User u WHERE u.deleted = false"), - @NamedQuery(name = "getUsersByGroupId", query = "SELECT u FROM User u WHERE u.deleted = false AND u.groupUsers.group.id = :groupId"), + @NamedQuery(name = "getUsersByGroupId", query = "SELECT u FROM User u WHERE u.deleted = false AND u.groupUsers.group.id = :groupId"), @NamedQuery(name = "getExternalUser", query = "SELECT u FROM User u WHERE u.deleted = false AND u.externalId LIKE :externalId AND u.externalType LIKE :externalType"), @NamedQuery(name = "getUserByLoginOrEmail", query = "SELECT u from User u WHERE u.deleted = false AND u.type = :type AND (u.login = :userOrEmail OR u.address.email = :userOrEmail)") }) @@ -106,7 +106,7 @@ public class User implements IDataProviderEntity { public static final int SALUTATION_MRS_ID = 3; public static final int SALUTATION_DR_ID = 4; public static final int SALUTATION_PROF_ID = 5; - + @XmlType(namespace="org.apache.openmeetings.user.user.right") public enum Right { Admin // access to Admin module @@ -116,7 +116,7 @@ public class User implements IDataProviderEntity { , Login // login to Om internal DB , Soap // use rest/soap calls } - + @XmlType(namespace="org.apache.openmeetings.user.user.type") public enum Type { user @@ -132,24 +132,24 @@ public class User implements IDataProviderEntity { , dr(SALUTATION_DR_ID) , prof(SALUTATION_PROF_ID); private int id; - + Salutation() {} //default; Salutation(int id) { this.id = id; } - + public int getId() { return id; } - + public static Salutation get(Long type) { return get(type == null ? 1 : type.intValue()); } - + public static Salutation get(Integer type) { return get(type == null ? 1 : type.intValue()); } - + public static Salutation get(int type) { Salutation rt = Salutation.mr; switch (type) { @@ -310,18 +310,18 @@ public class User implements IDataProviderEntity { @Column(name = "owner_id") @Element(data = true, required = false) private Long ownerId; - + @ElementCollection(fetch = FetchType.EAGER) @Column(name = "om_right") @CollectionTable(name = "om_user_right", joinColumns = @JoinColumn(name = "user_id")) @Enumerated(EnumType.STRING) @ElementList(name="rights", data = true, required = false) private Set<Right> rights = new HashSet<>(); - + @Column(name = "domain_id") @Element(data = true, required = false) private Long domainId; // LDAP config id for LDAP, OAuth server id for OAuth - + @Override public Long getId() { return id; @@ -391,7 +391,7 @@ public class User implements IDataProviderEntity { public void updatePassword(ConfigurationDao configDao, String pass) throws NoSuchAlgorithmException { updatePassword(configDao, pass, false); } - + public void updatePassword(ConfigurationDao configDao, String pass, boolean empty) throws NoSuchAlgorithmException { if (!empty) { if (invalidPassword(pass, configDao)) { @@ -414,7 +414,7 @@ public class User implements IDataProviderEntity { } password = CryptProvider.get().hash(pass); } - + public String getPassword() { return password; } @@ -604,11 +604,11 @@ public class User implements IDataProviderEntity { public void setType(Type type) { this.type = type; } - + public Long getOwnerId(){ return ownerId; } - + public void setOwnerId(Long ownerId){ this.ownerId = ownerId; } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/UserHelper.java ---------------------------------------------------------------------- diff --git a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/UserHelper.java b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/UserHelper.java index 9983b7f..232db04 100644 --- a/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/UserHelper.java +++ b/openmeetings-db/src/main/java/org/apache/openmeetings/db/util/UserHelper.java @@ -29,11 +29,11 @@ public class UserHelper { public static int getMinLoginLength(ConfigurationDao cfgDao) { return cfgDao.getConfValue(CONFIG_LOGIN_MIN_LENGTH_KEY, Integer.class, "" + USER_LOGIN_MINIMUM_LENGTH); } - + public static int getMinPasswdLength(ConfigurationDao cfgDao) { return cfgDao.getConfValue(CONFIG_PASS_MIN_LENGTH_KEY, Integer.class, "" + USER_PASSWORD_MINIMUM_LENGTH); } - + public static boolean invalidPassword(String pass, ConfigurationDao cfgDao) { return (pass == null || pass.length() < getMinPasswdLength(cfgDao)); } http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java ---------------------------------------------------------------------- diff --git a/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java b/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java index b9d6332..c92eb40 100644 --- a/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java +++ b/openmeetings-install/src/main/java/org/apache/openmeetings/backup/BackupImport.java @@ -117,7 +117,7 @@ import org.apache.openmeetings.db.entity.user.UserContact; import org.apache.openmeetings.db.util.TimezoneUtil; import org.apache.openmeetings.util.CalendarPatterns; import org.apache.openmeetings.util.OmFileHelper; -import org.apache.openmeetings.util.crypt.SHA256Implementation; +import org.apache.openmeetings.util.crypt.SCryptImplementation; import org.apache.wicket.util.string.Strings; import org.red5.logging.Red5LoggerFactory; import org.simpleframework.xml.Serializer; @@ -281,7 +281,7 @@ public class BackupImport { try { Class.forName(c.getValue()); } catch (ClassNotFoundException e) { - c.setValue(SHA256Implementation.class.getCanonicalName()); + c.setValue(SCryptImplementation.class.getCanonicalName()); } } configurationDao.update(c, null); http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-install/src/main/java/org/apache/openmeetings/installation/InstallationConfig.java ---------------------------------------------------------------------- diff --git a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/InstallationConfig.java b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/InstallationConfig.java index d4f6da1..d023802 100644 --- a/openmeetings-install/src/main/java/org/apache/openmeetings/installation/InstallationConfig.java +++ b/openmeetings-install/src/main/java/org/apache/openmeetings/installation/InstallationConfig.java @@ -23,7 +23,7 @@ import static org.apache.openmeetings.util.OpenmeetingsVariables.DEFAULT_BASE_UR import java.io.Serializable; import org.apache.openmeetings.db.dao.basic.ConfigurationDao; -import org.apache.openmeetings.util.crypt.SHA256Implementation; +import org.apache.openmeetings.util.crypt.SCryptImplementation; public class InstallationConfig implements Serializable { private static final long serialVersionUID = 1L; @@ -37,7 +37,7 @@ public class InstallationConfig implements Serializable { public String createDefaultRooms = "1"; public String ical_timeZone = "Europe/Berlin"; - public String cryptClassName = SHA256Implementation.class.getCanonicalName(); + public String cryptClassName = SCryptImplementation.class.getCanonicalName(); //email public Integer smtpPort = 25; public String smtpServer = "localhost"; http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-server/src/site/xdoc/CustomCryptMechanism.xml ---------------------------------------------------------------------- diff --git a/openmeetings-server/src/site/xdoc/CustomCryptMechanism.xml b/openmeetings-server/src/site/xdoc/CustomCryptMechanism.xml index fcf97ef..b3de07b 100644 --- a/openmeetings-server/src/site/xdoc/CustomCryptMechanism.xml +++ b/openmeetings-server/src/site/xdoc/CustomCryptMechanism.xml @@ -13,8 +13,8 @@ limitations under the License. --> <document xmlns="http://maven.apache.org/XDOC/2.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/XDOC/2.0 http://maven.apache.org/xsd/xdoc-2.0.xsd"> <properties> <title>Howto create a Custom Crypt styles</title> <author email="[email protected]">Apache OpenMeetings Team</author> @@ -23,22 +23,16 @@ <section name="Configuration of Custom Crypt-Style"> <p> You can use custom Crypt-Types, but you should decide during - installation which Type of encryption you want to use. By default - two type are available: + installation which Type of encryption you want to use. By default SCryptImplementation is used: </p> - <ul> - <li>org.apache.openmeetings.util.crypt.MD5Implementation - this uses common MD5 - Crypt like PHP does, this is the default one (results in something - like: fe01ce2a7fbac8fafaed7c982a04e229)</li> - <li>org.apache.openmeetings.util.crypt.MD5CryptImplementation - does use - BSD-Style of encryption using a salt (results in something like: - $1$GMsj7F2I$5S3r9CeukXGXNwf6b4sph1)</li> + <li>org.apache.openmeetings.util.crypt.SCryptImplementation - does use + SCrypt for password hashing with salt</li> </ul> <p> You can edit the config-key during Installation or later in the Administration Panel. But if you change it using the - Administration-Panel previous passwords might be not working anymore + Administration-Panel previous passwords will not work anymore as they are encrypted with another algorithm. </p> </section> @@ -47,57 +41,20 @@ To add your own crypt style you need to write a class which implements the interface: org.apache.openmeetings.util.crypt.ICrypt <br /> - Example of an Implementation: + Example of an Implementation: <br /> + <a href="https://github.com/apache/openmeetings/blob/256e5cd11e5af8f422688dfc1d01ac66b370d7a0/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java">SHA256Implementation.java</a> + <br /> + <a href="https://github.com/apache/openmeetings/blob/256e5cd11e5af8f422688dfc1d01ac66b370d7a0/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java">MD5Implementation.java</a> + <br /> </p> - <source> -<![CDATA[ -package org.apache.openmeetings.util.crypt; - -import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; - -import java.security.NoSuchAlgorithmException; - -import org.red5.logging.Red5LoggerFactory; -import org.slf4j.Logger; - -public class MD5Implementation implements ICrypt { - private static final Logger log = Red5LoggerFactory.getLogger(MD5Implementation.class, webAppRootKey); - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#hash(java.lang.String) - */ - @Override - public String hash(String str) { - String passPhrase = null; - try { - passPhrase = MD5.checksum(str); - } catch (NoSuchAlgorithmException e) { - log.error("Error", e); - } - return passPhrase; - } - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#verify(java.lang.String, java.lang.String) - */ - @Override - public boolean verify(String str, String hash) { - return hash != null && hash.equals(hash(str)); - } -} -]]> - </source> <p>To add your own Encryption-Class you need to add your class to the OpenMeetings-Webapp (make it available to the webapp-classpath) and use your custom-class-name instead of - org.apache.openmeetings.util.crypt.MD5Implementation during the Installation or + org.apache.openmeetings.util.crypt.SCryptImplementation during the Installation or at runtime by editing the config-key crypt_ClassName</p> </section> <section name="Configuration of Custom Crypt-Style"> - <p>credits goto Mika for sharing his Implementation of the - MD5Crypt-Style</p> + <p>credits goto Mika for sharing his Implementation of the MD5Crypt-Style</p> </section> </body> </document> http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Crypt.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Crypt.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Crypt.java deleted file mode 100644 index 19c250b..0000000 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Crypt.java +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/* - - Based on the work of Jonathan Abbey - Adopted for Director by Thomas Aeby, 2004 - - MD5Crypt.java - - Created: 3 November 1999 - Release: $Name: $ - Version: $Revision: 1.1 $ - Last Mod Date: $Date: 2004/02/04 08:10:35 $ - Java Code By: Jonathan Abbey, [email protected] - Original C Version: - ---------------------------------------------------------------------------- - "THE BEER-WARE LICENSE" (Revision 42): - <[email protected]> wrote this file. As long as you retain this notice you - can do whatever you want with this stuff. If we meet some day, and you think - this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - ---------------------------------------------------------------------------- - - ----------------------------------------------------------------------- - - Ganymede Directory Management System - - Copyright (C) 1996, 1997, 1998, 1999 The University of Texas at Austin. - - Contact information - - Author Email: [email protected] - Email mailing list: [email protected] - - US Mail: - - Computer Science Division - Applied Research Laboratories - The University of Texas at Austin - PO Box 8029, Austin TX 78713-8029 - - Telephone: (512) 835-3200 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - */ - -/*------------------------------------------------------------------------------ - class - MD5Crypt - - ------------------------------------------------------------------------------*/ - -/** - * <p> - * This class defines a method, - * {@link MD5Crypt#crypt(java.lang.String, java.lang.String) crypt()}, which - * takes a password and a salt string and generates an - * OpenBSD/FreeBSD/Linux-compatible md5-encoded password entry. - * </p> - * - * <p> - * Created: 3 November 1999 - * </p> - * <p> - * Release: $Name: $ - * </p> - * <p> - * Version: $Revision: 1.1 $ - * </p> - * <p> - * Last Mod Date: $Date: 2004/02/04 08:10:35 $ - * </p> - * <p> - * Java Code By: Jonathan Abbey, [email protected] - * </p> - * <p> - * Original C Version: - * - * <pre> - * ---------------------------------------------------------------------------- - * "THE BEER-WARE LICENSE" (Revision 42): - * <[email protected]> wrote this file. As long as you retain this notice you - * can do whatever you want with this stuff. If we meet some day, and you think - * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp - * ---------------------------------------------------------------------------- - * </pre> - * - * </p> - */ - -public final class MD5Crypt { - - /** - * - * Command line test rig. - * - * @throws NoSuchAlgorithmException - * - */ - - static public void main(String argv[]) throws NoSuchAlgorithmException { - if ((argv.length < 1) || (argv.length > 2)) { - System.err.println("Usage: MD5Crypt password salt"); - System.exit(1); - } - - if (argv.length == 2) { - System.err.println(MD5Crypt.crypt(argv[0], argv[1])); - } else { - System.err.println(MD5Crypt.crypt(argv[0])); - } - - System.exit(0); - } - - static private final String SALTCHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; - - static private final String itoa64 = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - - static private final String to64(long v, int size) { - StringBuffer result = new StringBuffer(); - - while (--size >= 0) { - result.append(itoa64.charAt((int) (v & 0x3f))); - v >>>= 6; - } - - return result.toString(); - } - - static private final void clearbits(byte bits[]) { - for (int i = 0; i < bits.length; i++) { - bits[i] = 0; - } - } - - /** - * convert an encoded unsigned byte value into a int with the unsigned - * value. - */ - - @SuppressWarnings("cast") - static private final int bytes2u(byte inp) { - return ((int) inp) & 0xff; - } - - /** - * <p> - * This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible - * md5-encoded password hash from a plaintext password and a salt. - * </p> - * - * <p> - * The resulting string will be in the form '$1$<salt>$<hashed - * mess> - * </p> - * - * @param password - * Plaintext password - * - * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. - * @throws NoSuchAlgorithmException - */ - - static public final String crypt(String password) - throws NoSuchAlgorithmException { - StringBuffer salt = new StringBuffer(); - java.util.Random randgen = new java.util.Random(); - - /* -- */ - - while (salt.length() < 8) { - int index = (int) (randgen.nextFloat() * SALTCHARS.length()); - salt.append(SALTCHARS.substring(index, index + 1)); - } - - return MD5Crypt.crypt(password, salt.toString()); - } - - /** - * <p> - * This method actually generates a OpenBSD/FreeBSD/Linux PAM compatible - * md5-encoded password hash from a plaintext password and a salt. - * </p> - * - * <p> - * The resulting string will be in the form '$1$<salt>$<hashed - * mess> - * </p> - * - * @param password - * Plaintext password - * @param salt - * A short string to use to randomize md5. May start with $1$, - * which will be ignored. It is explicitly permitted to pass a - * pre-existing MD5Crypt'ed password entry as the salt. crypt() - * will strip the salt chars out properly. - * - * @return An OpenBSD/FreeBSD/Linux-compatible md5-hashed password field. - * @throws NoSuchAlgorithmException - */ - - static public final String crypt(String password, String salt) - throws NoSuchAlgorithmException { - /* - * This string is magic for this algorithm. Having it this way, we can - * get get better later on - */ - - String magic = "$1$"; - byte finalState[]; - MessageDigest ctx, ctx1; - long l; - - /* -- */ - - /* Refine the Salt first */ - - /* If it starts with the magic string, then skip that */ - - if (salt.startsWith(magic)) { - salt = salt.substring(magic.length()); - } - - /* It stops at the first '$', max 8 chars */ - - if (salt.indexOf('$') != -1) { - salt = salt.substring(0, salt.indexOf('$')); - } - - if (salt.length() > 8) { - salt = salt.substring(0, 8); - } - - ctx = MessageDigest.getInstance("MD5"); - - ctx.update(password.getBytes(UTF_8)); // The password first, since that is what is most unknown - ctx.update(magic.getBytes(UTF_8)); // Then our magic string - ctx.update(salt.getBytes(UTF_8)); // Then the raw salt - - /* Then just as many characters of the MD5(pw,salt,pw) */ - - ctx1 = MessageDigest.getInstance("MD5"); - ctx1.update(password.getBytes(UTF_8)); - ctx1.update(salt.getBytes(UTF_8)); - ctx1.update(password.getBytes(UTF_8)); - finalState = ctx1.digest(); - - for (int pl = password.length(); pl > 0; pl -= 16) { - for (int i = 0; i < (pl > 16 ? 16 : pl); i++) - ctx.update(finalState[i]); - } - - /* - * the original code claimed that finalState was being cleared to keep - * dangerous bits out of memory, but doing this is also required in - * order to get the right output. - */ - - clearbits(finalState); - - /* Then something really weird... */ - - for (int i = password.length(); i != 0; i >>>= 1) { - if ((i & 1) != 0) { - ctx.update(finalState[0]); - } else { - ctx.update(password.getBytes(UTF_8)[0]); - } - } - - finalState = ctx.digest(); - - /* - * and now, just to make sure things don't run too fast On a 60 Mhz - * Pentium this takes 34 msec, so you would need 30 seconds to build a - * 1000 entry dictionary... - * - * (The above timings from the C version) - */ - - for (int i = 0; i < 1000; i++) { - ctx1 = MessageDigest.getInstance("MD5"); - - if ((i & 1) != 0) { - ctx1.update(password.getBytes(UTF_8)); - } else { - for (int c = 0; c < 16; c++) - ctx1.update(finalState[c]); - } - - if ((i % 3) != 0) { - ctx1.update(salt.getBytes(UTF_8)); - } - - if ((i % 7) != 0) { - ctx1.update(password.getBytes(UTF_8)); - } - - if ((i & 1) != 0) { - for (int c = 0; c < 16; c++) - ctx1.update(finalState[c]); - } else { - ctx1.update(password.getBytes(UTF_8)); - } - - finalState = ctx1.digest(); - } - - /* Now make the output string */ - - StringBuffer result = new StringBuffer(); - - result.append(magic); - result.append(salt); - result.append("$"); - - l = (bytes2u(finalState[0]) << 16) | (bytes2u(finalState[6]) << 8) - | bytes2u(finalState[12]); - result.append(to64(l, 4)); - - l = (bytes2u(finalState[1]) << 16) | (bytes2u(finalState[7]) << 8) - | bytes2u(finalState[13]); - result.append(to64(l, 4)); - - l = (bytes2u(finalState[2]) << 16) | (bytes2u(finalState[8]) << 8) - | bytes2u(finalState[14]); - result.append(to64(l, 4)); - - l = (bytes2u(finalState[3]) << 16) | (bytes2u(finalState[9]) << 8) - | bytes2u(finalState[15]); - result.append(to64(l, 4)); - - l = (bytes2u(finalState[4]) << 16) | (bytes2u(finalState[10]) << 8) - | bytes2u(finalState[5]); - result.append(to64(l, 4)); - - l = bytes2u(finalState[11]); - result.append(to64(l, 2)); - - /* Don't leave anything around in vm they could use. */ - clearbits(finalState); - - return result.toString(); - } -} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5CryptImplementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5CryptImplementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5CryptImplementation.java deleted file mode 100644 index 4aaf68e..0000000 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5CryptImplementation.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; - -import java.security.NoSuchAlgorithmException; - -import org.red5.logging.Red5LoggerFactory; -import org.slf4j.Logger; - -public class MD5CryptImplementation implements ICrypt { - private static final Logger log = Red5LoggerFactory.getLogger(MD5CryptImplementation.class, webAppRootKey); - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#hash(java.lang.String) - */ - @Override - public String hash(String str) { - String passPhrase = null; - try { - passPhrase = MD5Crypt.crypt(str); - } catch (NoSuchAlgorithmException e) { - log.error("Error", e); - } - return passPhrase; - } - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#verify(java.lang.String, java.lang.String) - */ - @Override - public boolean verify(String str, String hash) { - boolean validPassword = false; - String salt = hash.split("\\$")[2]; - - try { - validPassword = hash.equals(MD5Crypt.crypt(str, salt)); - } catch (NoSuchAlgorithmException e) { - log.error("Error", e); - } - return validPassword; - } -} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java deleted file mode 100644 index 786532e..0000000 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/MD5Implementation.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; - -import java.security.NoSuchAlgorithmException; - -import org.red5.logging.Red5LoggerFactory; -import org.slf4j.Logger; - -public class MD5Implementation implements ICrypt { - private static final Logger log = Red5LoggerFactory.getLogger(MD5Implementation.class, webAppRootKey); - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#hash(java.lang.String) - */ - @Override - public String hash(String str) { - String passPhrase = null; - try { - passPhrase = MD5.checksum(str); - } catch (NoSuchAlgorithmException e) { - log.error("Error", e); - } - return passPhrase; - } - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#verify(java.lang.String, java.lang.String) - */ - @Override - public boolean verify(String str, String hash) { - return hash != null && hash.equals(hash(str)); - } -} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java new file mode 100644 index 0000000..f356bd0 --- /dev/null +++ b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SCryptImplementation.java @@ -0,0 +1,87 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openmeetings.util.crypt; + +import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; + +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +import org.apache.commons.codec.binary.Base64; +import org.bouncycastle.crypto.generators.SCrypt; +import org.red5.logging.Red5LoggerFactory; +import org.slf4j.Logger; + +public class SCryptImplementation implements ICrypt { + private static final Logger log = Red5LoggerFactory.getLogger(SCryptImplementation.class, webAppRootKey); + private static final String SECURE_RND_ALG = "SHA1PRNG"; + private static final int COST = 1024 * 16; + private static final int KEY_LENGTH = 512; + private static final int SALT_LENGTH = 200; + + private static byte[] getSalt() throws NoSuchAlgorithmException { + SecureRandom sr = SecureRandom.getInstance(SECURE_RND_ALG); + byte[] salt = new byte[SALT_LENGTH]; + sr.nextBytes(salt); + return salt; + } + + private static String hash(String str, byte[] salt) { + byte[] dk = SCrypt.generate(str.getBytes(), salt, COST, 8, 8, KEY_LENGTH); + return Base64.encodeBase64String(dk); + } + + @Override + public String hash(String str) { + if (str == null) { + return null; + } + String hash = null; + try { + byte[] salt = getSalt(); + String h = hash(str, salt); + hash = String.format("%s:%s", h, Base64.encodeBase64String(salt)); + } catch (NoSuchAlgorithmException e) { + log.error("Error", e); + } + return hash; + } + + @Override + public boolean verify(String str, String hash) { + if (str == null) { + return hash == null; + } + if (hash == null) { + return false; + } + String[] ss = hash.split(":"); + if (ss.length != 2) { + return false; + } + try { + String h1 = ss[0]; + byte[] salt = Base64.decodeBase64(ss[1]); + String h2 = hash(str, salt); + return h2.equals(h1); + } catch (Exception e) { + return false; + } + } +} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256.java deleted file mode 100644 index 5b072bf..0000000 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import static java.nio.charset.StandardCharsets.UTF_8; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import org.apache.commons.codec.binary.Hex; - -public class SHA256 { - public static String checksum(String data) throws NoSuchAlgorithmException { - MessageDigest md = MessageDigest.getInstance("SHA-256"); - byte[] b = data == null ? new byte[0] : data.getBytes(UTF_8); - md.update(b); - return Hex.encodeHexString(md.digest()); - } -} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java b/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java deleted file mode 100644 index c934ecb..0000000 --- a/openmeetings-util/src/main/java/org/apache/openmeetings/util/crypt/SHA256Implementation.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.apache.openmeetings.util.OpenmeetingsVariables.webAppRootKey; - -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; - -import org.apache.commons.codec.binary.Base64; -import org.bouncycastle.crypto.digests.SHA256Digest; -import org.bouncycastle.crypto.generators.PKCS5S2ParametersGenerator; -import org.bouncycastle.crypto.params.KeyParameter; -import org.red5.logging.Red5LoggerFactory; -import org.slf4j.Logger; - -public class SHA256Implementation implements ICrypt { - private static final Logger log = Red5LoggerFactory.getLogger(SHA256Implementation.class, webAppRootKey); - private static final String SECURE_RND_ALG = "SHA1PRNG"; - private static final int ITERATIONS = 1000; - private static final int KEY_LENGTH = 128 * 8; - private static final int SALT_LENGTH = 256; - - private static byte[] getSalt() throws NoSuchAlgorithmException { - SecureRandom sr = SecureRandom.getInstance(SECURE_RND_ALG); - byte[] salt = new byte[SALT_LENGTH]; - sr.nextBytes(salt); - return salt; - } - - private static String hash(String str, byte[] salt, int iter) { - PKCS5S2ParametersGenerator gen = new PKCS5S2ParametersGenerator(new SHA256Digest()); - gen.init(str.getBytes(UTF_8), salt, iter); - byte[] dk = ((KeyParameter) gen.generateDerivedParameters(KEY_LENGTH)).getKey(); - return Base64.encodeBase64String(dk); - } - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#hash(java.lang.String) - */ - @Override - public String hash(String str) { - if (str == null) { - return null; - } - String hash = null; - try { - byte[] salt = getSalt(); - String h = hash(str, salt, ITERATIONS); - hash = String.format("%s:%s:%s", ITERATIONS, h, Base64.encodeBase64String(salt)); - } catch (NoSuchAlgorithmException e) { - log.error("Error", e); - } - return hash; - } - - /* - * (non-Javadoc) - * @see org.apache.openmeetings.utils.crypt.ICrypt#verify(java.lang.String, java.lang.String) - */ - @Override - public boolean verify(String str, String hash) { - if (str == null) { - return hash == null; - } - if (hash == null) { - return false; - } - String[] ss = hash.split(":"); - if (ss.length != 3) { - return false; - } - try { - int iter = Integer.parseInt(ss[0]); - String h1 = ss[1]; - byte[] salt = Base64.decodeBase64(ss[2]); - String h2 = hash(str, salt, iter); - return h2.equals(h1); - } catch (Exception e) { - return false; - } - } -} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java b/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java new file mode 100644 index 0000000..41d1e7c --- /dev/null +++ b/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSCrypt.java @@ -0,0 +1,28 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.apache.openmeetings.util.crypt; + +import org.junit.BeforeClass; + +public class TestSCrypt extends AbstractCryptTest { + @BeforeClass + public static void setup() { + crypt = new SCryptImplementation(); + } +} http://git-wip-us.apache.org/repos/asf/openmeetings/blob/297726b7/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSHA.java ---------------------------------------------------------------------- diff --git a/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSHA.java b/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSHA.java deleted file mode 100644 index d44b371..0000000 --- a/openmeetings-util/src/test/java/org/apache/openmeetings/util/crypt/TestSHA.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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.apache.openmeetings.util.crypt; - -import org.junit.BeforeClass; - -public class TestSHA extends AbstractCryptTest { - @BeforeClass - public static void setup() { - crypt = new SHA256Implementation(); - } -}
