MessageDigest的更新方法做什么以及BASE64Encoder的用途是什么?

时间:2012-02-22 17:01:35

标签: java encryption cryptography

以下是将加密用户字符串的代码:

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import sun.misc.BASE64Encoder;
import java.io.*;

class Encrypter {
public synchronized String encrypt(String plainText) throws Exception {
    MessageDigest md = null;
    try {
        md = MessageDigest.getInstance("SHA");
    }catch(Exception exc) {
        throw new Exception(exc.getMessage());
     }

     try {
        md.update(plainText.getBytes("UTF-8"));
     }catch(Exception exc) {
        throw new Exception(exc.getMessage());
      }

      byte raw[] = md.digest();
      String hash = (new BASE64Encoder()).encode(raw);
      return hash;
}
public static void main(String args[]) {
    try {
        Encrypter encrypter = new Encrypter();
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String userInput = br.readLine();
        String encryptedPassword = encrypter.encrypt(userInput);
        System.out.println(encryptedPassword);
    } catch(Exception exc) {
        System.out.println(exc);
      }
}
}

当我编译代码时,我得到了这些警告:

Encrypter.java:4: warning: BASE64Encoder is internal proprietary API and may be removed in a future release
import sun.misc.BASE64Encoder;
           ^
Encrypter.java:23: warning: BASE64Encoder is internal proprietary API and may be removed in a future release
              String hash = (new BASE64Encoder()).encode(raw);
                                 ^
2 warnings

是否还有其他方法可以加密java中的字符串?

update的方法MessageDigest有什么作用?那句话md.update(plainText.getBytes("UTF-8"));做了什么?

什么是BASE64Encoder课程?我找不到它的DOC

5 个答案:

答案 0 :(得分:12)

  1. 首先,您没有执行任何加密。您正在计算输入的单向散列或摘要。此哈希稍后可用于验证消息的完整性。请参阅HashingSHA1MessageDigest

  2. Base64 encoding是一种用ASCII表示二进制数据的方法。这通常是可取的,因为并非所有数据存储和传输机制都支持原始二进制。例如,如果要通过http查询字符串参数传输计算摘要,则需要将其编码为Base64。另外,将原始二进制文件保存或打印到控制台会产生一系列时髦字符,这些字符可能超出可打印范围,并且还可能会从PC扬声器发出蜂鸣声!

  3. 您使用的Base64Encoder来自sun.misc包,不应使用。这是内部Sun JVM代码,将来可能会或可能不会提供。这也解释了为什么你无法找到任何javadoc。

  4. 幸运的是,存在一些免费且开放的Base64编码器和解码器。 Apache Commons Codec是一个广泛使用且稳定的库,其中包含多个包含Base64的编解码器。

  5. md.update(plainText.getBytes("UTF-8"))更新摘要的输入。调用digest执行最终更新并计算输入的摘要。请参阅md.digestmd.update

  6. 的javadoc

答案 1 :(得分:2)

答案 2 :(得分:2)

虽然这里的旧帖子是更新的答案。 Java 8的Base64。

Java 8 Base64 Documents

答案 3 :(得分:1)

对于Base64加密和解密,这个警告清楚地表明它不鼓励使用Sun实现的Base64Encoder并发出警告,可能会在将来的版本中删除实现,我们可以做的是切换到Base64的其他实现编码器。我们可以将Commons Codec library用于Base64编码器。以下是一个例子:

1. Add Commons Codec library in classpath of your project
2. Add import statement for Base64 Class.

import org.apache.commons.codec.binary.Base64;

3. Encrypt your data

String testString = "Hello World";
byte[] encodedBytes = Base64.encodeBase64(testString.getBytes());
// Get encoded string
String encodedString = new String(encodedBytes);
// Get decoded string back
String decodedString = new String(Base64.decodeBase64(encodedBytes));

使用Commons编解码器库后,您不应再次看到上述警告。

答案 4 :(得分:0)

要以bullet 5 from Sahil Muthoo's excellent answer为基础,下面是对源代码的更深入研究。

默认情况下,update方法只是将输入字节数组附加到tempArray抽象类的当前MessageDigestSpi

MessageDigest类扩展了MessageDigestSpi类。然后,MessageDigest.update被称为方法MessageDigestSpi.engineUpdate,这可以通过研究源代码来找到:

MessageDigest.java(source code

196:   /**
197:    * Updates the digest with the byte.
...
200:    */
201:   public void update(byte input)
202:   {
203:     engineUpdate(input);
204:   }
205: 
206:   /**
207:    * Updates the digest with the bytes from the array starting from the
208:    * specified offset and using the specified length of bytes.
209:    * 
210:    * @param input
211:    *          bytes to update the digest with.
212:    * @param offset
213:    *          the offset to start at.
214:    * @param len
215:    *          length of the data to update with.
216:    */
217:   public void update(byte[] input, int offset, int len)
218:   {
219:     engineUpdate(input, offset, len);
220:   }
...
227:   public void update(byte[] input)
228:   {
229:     engineUpdate(input, 0, input.length);
230:   }
...
238:   public void update (ByteBuffer input)
239:   {
240:     engineUpdate (input);
241:   }

MessageDigestSpi.engineUpdate是一种抽象方法,必须通过扩展类来实现,如下所示:

MessageDigestSpi.java(source code

42:    /**
43:     * Updates this {@code MessageDigestSpi} using the given {@code byte}.
44:     *
45:     * @param input
46:     *            the {@code byte} to update this {@code MessageDigestSpi} with.
47:     * @see #engineReset()
48:     */
49:    protected abstract void engineUpdate(byte input);
50:    /**
51:     * Updates this {@code MessageDigestSpi} using the given {@code byte[]}.
52:     *
53:     * @param input
54:     *            the {@code byte} array.
55:     * @param offset
56:     *            the index of the first byte in {@code input} to update from.
57:     * @param len
58:     *            the number of bytes in {@code input} to update from.
59:     * @throws IllegalArgumentException
60:     *             if {@code offset} or {@code len} are not valid in respect to
61:     *             {@code input}.
62:     */
63:    protected abstract void engineUpdate(byte[] input, int offset, int len);
64:    /**
65:     * Updates this {@code MessageDigestSpi} using the given {@code input}.
66:     *
67:     * @param input
68:     *            the {@code ByteBuffer}.
69:     */
70:    protected void engineUpdate(ByteBuffer input) {
71:        if (!input.hasRemaining()) {
72:            return;
73:        }
74:        byte[] tmp;
75:        if (input.hasArray()) {
76:            tmp = input.array();
77:            int offset = input.arrayOffset();
78:            int position = input.position();
79:            int limit = input.limit();
80:            engineUpdate(tmp, offset+position, limit - position);
81:            input.position(limit);
82:        } else {
83:            tmp = new byte[input.limit() - input.position()];
84:            input.get(tmp);
85:            engineUpdate(tmp, 0, tmp.length);
86:        }
87:    }