Java/Security/MD5 String
Содержание
Encode an MD5 digest into a String.
/*
* 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.
*/
/**
* Encode an MD5 digest into a String.
* <p>
* The 128 bit MD5 hash is converted into a 32 character long String.
* Each character of the String is the hexadecimal representation of 4 bits
* of the digest.
*
* @author Remy Maucherat
* @version $Revision: 515 $ $Date: 2008-03-17 22:02:23 +0100 (Mon, 17 Mar 2008) $
*/
public final class MD5Encoder {
// ----------------------------------------------------- Instance Variables
private static final char[] hexadecimal =
{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f"};
// --------------------------------------------------------- Public Methods
/**
* Encodes the 128 bit (16 bytes) MD5 into a 32 character String.
*
* @param binaryData Array containing the digest
* @return Encoded MD5, or null if encoding failed
*/
public String encode( byte[] binaryData ) {
if (binaryData.length != 16)
return null;
char[] buffer = new char[32];
for (int i=0; i<16; i++) {
int low = (int) (binaryData[i] & 0x0f);
int high = (int) ((binaryData[i] & 0xf0) >> 4);
buffer[i*2] = hexadecimal[high];
buffer[i*2 + 1] = hexadecimal[low];
}
return new String(buffer);
}
}
Get MD5 Base64
/*
* $Header: /cvsroot/mvnforum/mvnforum/contrib/phpbb2mvnforum/src/org/mvnforum/util/MD5.java,v 1.6 2007/01/15 10:27:31 dungbtm Exp $
* $Author: dungbtm $
* $Revision: 1.6 $
* $Date: 2007/01/15 10:27:31 $
*
*
*
* Copyright (C) 2002-2007 by MyVietnam.net
*
* All copyright notices regarding mvnForum MUST remain
* intact in the scripts and in the outputted HTML.
* The "powered by" text/logo with a link back to
* http://www.mvnForum.ru and http://www.MyVietnam.net in
* the footer of the pages MUST remain visible when the pages
* are viewed on the internet or intranet.
*
* 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
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Support can be obtained from support forums at:
* http://www.mvnForum.ru/mvnforum/index
*
* Correspondence and Marketing Questions can be sent to:
* info at MyVietnam net
*
* @author:
*/
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;
//
// The JavaReference.ru Software License, Version 1.0
// Copyright (c) 2002-2005 JavaReference.ru. All rights reserved.
//
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. The end-user documentation included with the redistribution, if any, must
// include the following acknowlegement:
//
// "This product includes software developed by the Javareference.ru
// (http://www.javareference.ru/)."
//
// Alternately, this acknowlegement may appear in the software itself, if and
// wherever such third-party acknowlegements normally appear.
//
// 4. The names "JavaReference" and "Javareference.ru", must not be used to
// endorse or promote products derived from this software without prior written
// permission. For written permission, please contact webmaster@javareference.ru.
//
// 5. Products derived from this software may not be called "Javareference" nor may
// "Javareference" appear in their names without prior written permission of
// Javareference.ru.
//
// THIS SOFTWARE IS PROVIDED ``AS IS"" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// JAVAREFERENCE.ru OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//
// Software from this site consists of contributions made by various individuals
// on behalf of Javareference.ru. For more information on Javareference.ru,
// please see http://www.javareference.ru
//
/**
* @author anandh
*/
public class MD5 {
static char[] carr = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
public static String getBase64FromHEX(String input) {
byte barr[] = new byte[16];
int bcnt = 0;
for (int i = 0; i < 32; i += 2) {
char c1 = input.charAt(i);
char c2 = input.charAt(i + 1);
int i1 = intFromChar(c1);
int i2 = intFromChar(c2);
barr[bcnt] = 0;
barr[bcnt] |= (byte) ((i1 & 0x0F) << 4);
barr[bcnt] |= (byte) (i2 & 0x0F);
bcnt++;
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(barr);
}
public static synchronized String getMD5_Base64(String input) {
// please note that we dont use digest, because if we
// cannot get digest, then the second time we have to call it
// again, which will fail again
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("MD5");
} catch (Exception ex) {
ex.printStackTrace();
}
if (digest == null)
return input;
// now everything is ok, go ahead
try {
digest.update(input.getBytes("UTF-8"));
} catch (java.io.UnsupportedEncodingException ex) {
ex.printStackTrace();
}
byte[] rawData = digest.digest();
BASE64Encoder bencoder = new BASE64Encoder();
return bencoder.encode(rawData);
}
private static int intFromChar(char c) {
char clower = Character.toLowerCase(c);
for (int i = 0; i < carr.length; i++) {
if (clower == carr[i]) {
return i;
}
}
return 0;
}
public static void main(String[] args) {
//String password = args[0];
String password = "test";
MessageDigest digest = null;
try {
digest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
try {
digest.update(password.getBytes("UTF-8"));
} catch (UnsupportedEncodingException ex) {
ex.printStackTrace();
}
byte[] rawData = digest.digest();
StringBuffer printable = new StringBuffer();
for (int i = 0; i < rawData.length; i++) {
printable.append(carr[((rawData[i] & 0xF0) >> 4)]);
printable.append(carr[(rawData[i] & 0x0F)]);
}
String phpbbPassword = printable.toString();
System.out.println("PHPBB : " + phpbbPassword);
System.out.println("MVNFORUM : " + getMD5_Base64(password));
System.out.println("PHPBB->MVNFORUM : " + getBase64FromHEX(phpbbPassword));
}
}
Security Utils
/**
* Copyright 2005-2008 Noelios Technologies.
*
* The contents of this file are subject to the terms of the following open
* source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.gnu.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.sun.ru/cddl/cddl.html
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royaltee free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.ru/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
/**
* Security data manipulation utilities.
*
* @author Jerome Louvel
*/
public class SecurityUtils {
/**
* General regex pattern to extract comma separated name-value components.
* This pattern captures one name and value per match(), and is repeatedly
* applied to the input string to extract all components. Must handle both
* quoted and unquoted values as RFC2617 isn"t consistent in this respect.
* Pattern is immutable and thread-safe so reuse one static instance.
*/
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
/**
* Generates a nonce as recommended in section 3.2.1 of RFC-2617, but
* without the ETag field. The format is: <code><pre>
* Base64.encodeBytes(currentTimeMS + ":"
* + md5String(currentTimeMS + ":" + secretKey))
* </pre></code>
*
* @param secretKey
* a secret value known only to the creator of the nonce. It"s
* inserted into the nonce, and can be used later to validate the
* nonce.
*/
public static String makeNonce(String secretKey) {
final long currentTimeMS = System.currentTimeMillis();
return Base64.encode((currentTimeMS + ":" + toMd5(currentTimeMS + ":"
+ secretKey)).getBytes(), true);
}
/**
* Converts a source string to its HMAC/SHA-1 value.
*
* @param source
* The source string to convert.
* @param secretKey
* The secret key to use for conversion.
* @return The HMac value of the source string.
*/
public static byte[] toHMac(String source, String secretKey) {
byte[] result = null;
try {
// Create the HMAC/SHA1 key
final SecretKeySpec signingKey = new SecretKeySpec(secretKey
.getBytes(), "HmacSHA1");
// Create the message authentication code (MAC)
final Mac mac = Mac.getInstance("HmacSHA1");
mac.init(signingKey);
// Compute the HMAC value
result = mac.doFinal(source.getBytes());
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(
"Could not find the SHA-1 algorithm. HMac conversion failed.",
nsae);
} catch (InvalidKeyException ike) {
throw new RuntimeException(
"Invalid key exception detected. HMac conversion failed.",
ike);
}
return result;
}
/**
* Returns the MD5 digest of the target string. Target is decoded to bytes
* using the US-ASCII charset. The returned hexadecimal String always
* contains 32 lowercase alphanumeric characters. For example, if target is
* "HelloWorld", this method returns "68e109f0f40ca72a15e05cc22786f8e6".
*
* @param target
* The string to encode.
* @return The MD5 digest of the target string.
*/
public static String toMd5(String target) {
try {
return toMd5(target, "US-ASCII");
} catch (UnsupportedEncodingException uee) {
// Unlikely, US-ASCII comes with every JVM
throw new RuntimeException(
"US-ASCII is an unsupported encoding, unable to compute MD5");
}
}
/**
* Returns the MD5 digest of target string. Target is decoded to bytes using
* the named charset. The returned hexadecimal String always contains 32
* lowercase alphanumeric characters. For example, if target is
* "HelloWorld", this method returns "68e109f0f40ca72a15e05cc22786f8e6".
*
* @param target
* The string to encode.
* @param charsetName
* The character set.
* @return The MD5 digest of the target string.
*
* @throws UnsupportedEncodingException
*/
public static String toMd5(String target, String charsetName)
throws UnsupportedEncodingException {
try {
final byte[] md5 = MessageDigest.getInstance("MD5").digest(
target.getBytes(charsetName));
final char[] md5Chars = new char[32];
int i = 0;
for (final byte b : md5) {
md5Chars[i++] = HEXDIGITS[(b >> 4) & 0xF];
md5Chars[i++] = HEXDIGITS[b & 0xF];
}
return new String(md5Chars);
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(
"No MD5 algorithm, unable to compute MD5");
}
}
/**
* Returns the SHA1 digest of the target string. Target is decoded to bytes
* using the US-ASCII charset.
*
* @param target
* The string to encode.
* @return The MD5 digest of the target string.
*/
public static String toSha1(String target) {
try {
return toSha1(target, "US-ASCII");
} catch (UnsupportedEncodingException uee) {
// Unlikely, US-ASCII comes with every JVM
throw new RuntimeException(
"US-ASCII is an unsupported encoding, unable to compute SHA1");
}
}
/**
* Returns the SHA1 digest of target string. Target is decoded to bytes
* using the named charset.
*
* @param target
* The string to encode.
* @param charsetName
* The character set.
* @return The SHA1 digest of the target string.
*
* @throws UnsupportedEncodingException
*/
public static String toSha1(String target, String charsetName)
throws UnsupportedEncodingException {
try {
return Base64.encode(MessageDigest.getInstance("SHA1").digest(
target.getBytes(charsetName)), false);
} catch (NoSuchAlgorithmException nsae) {
throw new RuntimeException(
"No SHA1 algorithm, unable to compute SHA1");
}
}
}
/**
* Copyright 2005-2008 Noelios Technologies.
*
* The contents of this file are subject to the terms of the following open
* source licenses: LGPL 3.0 or LGPL 2.1 or CDDL 1.0 (the "Licenses"). You can
* select the license that you prefer but you may not use this file except in
* compliance with one of these Licenses.
*
* You can obtain a copy of the LGPL 3.0 license at
* http://www.gnu.org/licenses/lgpl-3.0.html
*
* You can obtain a copy of the LGPL 2.1 license at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* You can obtain a copy of the CDDL 1.0 license at
* http://www.sun.ru/cddl/cddl.html
*
* See the Licenses for the specific language governing permissions and
* limitations under the Licenses.
*
* Alternatively, you can obtain a royaltee free commercial license with less
* limitations, transferable or non-transferable, directly at
* http://www.noelios.ru/products/restlet-engine
*
* Restlet is a registered trademark of Noelios Technologies.
*/
/**
* Minimal but fast Base64 codec.
*
* @author Ray Waldin (ray@waldin.net)
*/
class Base64 {
/** alphabet used for encoding bytes into base64 */
private static final char[] BASE64_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
.toCharArray();
/**
* decoding involves replacing each character with the character"s value, or
* position, from the above alphabet, and this table makes such lookups
* quick and easy. Couldn"t help myself with the corny name :)
*/
private static final byte[] DECODER_RING = new byte[128];
static {
Arrays.fill(DECODER_RING, (byte) -1);
int i = 0;
for (final char c : BASE64_DIGITS) {
DECODER_RING[c] = (byte) i++;
}
DECODER_RING["="] = 0;
}
private final static int byteAt(byte[] data, int block, int off) {
return unsign(data[(block * 3) + off]);
}
/**
* Decodes a base64 string into bytes. Newline characters found at block
* boundaries will be ignored.
*
* @param encodedString
* The string to decode.
* @return The decoded byte array.
*/
public static byte[] decode(String encodedString) {
final char[] chars = encodedString.toCharArray();
// prepare to ignore newline chars
int newlineCount = 0;
for (final char c : chars) {
switch (c) {
case "\r":
case "\n":
newlineCount++;
break;
default:
}
}
final int len = chars.length - newlineCount;
int numBytes = ((len + 3) / 4) * 3;
// fix up length relative to padding
if (len > 1) {
if (chars[chars.length - 2] == "=") {
numBytes -= 2;
} else if (chars[chars.length - 1] == "=") {
numBytes--;
}
}
final byte[] result = new byte[numBytes];
int newlineOffset = 0;
// decode each block of 4 chars into 3 bytes
for (int i = 0; i < (len + 3) / 4; ++i) {
int charOffset = newlineOffset + (i * 4);
final char c1 = chars[charOffset++];
final char c2 = chars[charOffset++];
final char c3 = chars[charOffset++];
final char c4 = chars[charOffset++];
if (!(validChar(c1) && validChar(c2) && validChar(c3) && validChar(c4))) {
throw new IllegalArgumentException(
"Invalid Base64 character in block: "" + c1 + c2 + c3
+ c4 + """);
}
// pack
final int x = DECODER_RING[c1] << 18 | DECODER_RING[c2] << 12
| (c3 == "=" ? 0 : DECODER_RING[c3] << 6)
| (c4 == "=" ? 0 : DECODER_RING[c4]);
// unpack
int byteOffset = i * 3;
result[byteOffset++] = (byte) (x >> 16);
if (c3 != "=") {
result[byteOffset++] = (byte) ((x >> 8) & 0xFF);
if (c4 != "=") {
result[byteOffset++] = (byte) (x & 0xFF);
}
}
// skip newlines after block
outer: while (chars.length > charOffset) {
switch (chars[charOffset++]) {
case "\r":
case "\n":
newlineOffset++;
break;
default:
break outer;
}
}
}
return result;
}
/**
* Encodes an entire byte array into a Base64 string, with optional newlines
* after every 76 characters.
*
* @param bytes
* The byte array to encode.
* @param newlines
* Indicates whether or not newlines are desired.
* @return The encoded string.
*/
public static String encode(byte[] bytes, boolean newlines) {
return encode(bytes, 0, bytes.length, newlines);
}
/**
* Encodes specified bytes into a Base64 string, with optional newlines
* after every 76 characters.
*
* @param bytes
* The byte array to encode.
* @param off
* The starting offset.
* @param len
* The number of bytes to encode.
* @param newlines
* Indicates whether or not newlines are desired.
*
* @return The encoded string.
*/
public static String encode(byte[] bytes, int off, int len, boolean newlines) {
final char[] output = new char[(((len + 2) / 3) * 4)
+ (newlines ? len / 43 : 0)];
int pos = 0;
// encode each block of 3 bytes into 4 chars
for (int i = 0; i < (len + 2) / 3; ++i) {
int pad = 0;
if (len + 1 < (i + 1) * 3) {
// two trailing "="s
pad = 2;
} else if (len < (i + 1) * 3) {
// one trailing "="
pad = 1;
}
// pack
final int x = (byteAt(bytes, i, off) << 16)
| (pad > 1 ? 0 : (byteAt(bytes, i, off + 1) << 8))
| (pad > 0 ? 0 : (byteAt(bytes, i, off + 2)));
// unpack
output[pos++] = BASE64_DIGITS[x >> 18];
output[pos++] = BASE64_DIGITS[(x >> 12) & 0x3F];
output[pos++] = pad > 1 ? "=" : BASE64_DIGITS[(x >> 6) & 0x3F];
output[pos++] = pad > 0 ? "=" : BASE64_DIGITS[x & 0x3F];
if (newlines && ((i + 1) % 19 == 0)) {
output[pos++] = "\n";
}
}
return new String(output, 0, pos);
}
private final static int unsign(byte b) {
return b < 0 ? b + 256 : b;
}
private final static boolean validChar(char c) {
return (c < 128) && (DECODER_RING[c] != -1);
}
}
Use MD5 to encrypt a string
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
private static MessageDigest digester;
static {
try {
digester = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
public static String crypt(String str) {
if (str == null || str.length() == 0) {
throw new IllegalArgumentException("String to encript cannot be null or zero length");
}
digester.update(str.getBytes());
byte[] hash = digester.digest();
StringBuffer hexString = new StringBuffer();
for (int i = 0; i < hash.length; i++) {
if ((0xff & hash[i]) < 0x10) {
hexString.append("0" + Integer.toHexString((0xFF & hash[i])));
}
else {
hexString.append(Integer.toHexString(0xFF & hash[i]));
}
}
return hexString.toString();
}
}