diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java index af677af3401..65b65a5a40d 100644 --- a/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java +++ b/jetty-util/src/main/java/org/eclipse/jetty/util/security/Password.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.util.security; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import org.eclipse.jetty.util.log.Log; @@ -141,39 +142,36 @@ public class Password extends Credential public static String obfuscate(String s) { StringBuilder buf = new StringBuilder(); - byte[] b = s.getBytes(); + byte[] b = s.getBytes(StandardCharsets.UTF_8); buf.append(__OBFUSCATE); for (int i = 0; i < b.length; i++) { byte b1 = b[i]; - byte b2 = b[s.length() - (i + 1)]; - int i1 = 127 + b1 + b2; - int i2 = 127 + b1 - b2; - int i0 = i1 * 256 + i2; - String x = Integer.toString(i0, 36); - - switch (x.length()) + byte b2 = b[b.length - (i + 1)]; + if (b1<0 || b2<0) { - case 1: - buf.append('0'); - buf.append('0'); - buf.append('0'); - buf.append(x); - break; - case 2: - buf.append('0'); - buf.append('0'); - buf.append(x); - break; - case 3: - buf.append('0'); - buf.append(x); - break; - default: - buf.append(x); - break; + int i0 = (0xff&b1)*256 + (0xff&b2); + String x = Integer.toString(i0, 36).toLowerCase(); + buf.append("U0000",0,5-x.length()); + buf.append(x); } + else + { + int i1 = 127 + b1 + b2; + int i2 = 127 + b1 - b2; + int i0 = i1 * 256 + i2; + String x = Integer.toString(i0, 36).toLowerCase(); + + int j0 = Integer.parseInt(x, 36); + int j1 = (i0 / 256); + int j2 = (i0 % 256); + byte bx = (byte) ((j1 + j2 - 254) / 2); + + buf.append("000",0,4-x.length()); + buf.append(x); + } + } return buf.toString(); @@ -188,14 +186,26 @@ public class Password extends Credential int l = 0; for (int i = 0; i < s.length(); i += 4) { - String x = s.substring(i, i + 4); - int i0 = Integer.parseInt(x, 36); - int i1 = (i0 / 256); - int i2 = (i0 % 256); - b[l++] = (byte) ((i1 + i2 - 254) / 2); + if (s.charAt(i)=='U') + { + i++; + String x = s.substring(i, i + 4); + int i0 = Integer.parseInt(x, 36); + byte bx = (byte)(i0>>8); + b[l++] = bx; + } + else + { + String x = s.substring(i, i + 4); + int i0 = Integer.parseInt(x, 36); + int i1 = (i0 / 256); + int i2 = (i0 % 256); + byte bx = (byte) ((i1 + i2 - 254) / 2); + b[l++] = bx; + } } - return new String(b, 0, l); + return new String(b, 0, l,StandardCharsets.UTF_8); } /* ------------------------------------------------------------ */ diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java new file mode 100644 index 00000000000..e27c0aac63f --- /dev/null +++ b/jetty-util/src/test/java/org/eclipse/jetty/util/security/PasswordTest.java @@ -0,0 +1,52 @@ +// +// ======================================================================== +// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util.security; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class PasswordTest +{ + @Test + public void testDeobfuscate() + { + // check any changes do not break already encoded strings + String password = "secret password !# "; + String obfuscate = "OBF:1iaa1g3l1fb51i351sw01ym91hdc1yt41v1p1ym71v2p1yti1hhq1ym51svy1hyl1f7h1fzx1i5o"; + assertEquals(password,Password.deobfuscate(obfuscate)); + } + + @Test + public void testObfuscate() + { + String password = "secret password !# "; + String obfuscate = Password.obfuscate(password); + assertEquals(password,Password.deobfuscate(obfuscate)); + } + + @Test + public void testObfuscateUnicode() + { + String password = "secret password !#\u20ac "; + String obfuscate = Password.obfuscate(password); + assertEquals(password,Password.deobfuscate(obfuscate)); + } + +}