In the encryption, the general encryption algorithm and hash algorithm, they operate is a byte array, the byte array according to the encryption algorithm for various transformations, operations, resulting in a byte array. And we generally require that strings be encrypted, so it involves the conversion of string strings to byte[], which is very simple. At the same time, the conversion of the byte array byte[] to String is also involved in the decryption. In addition, after the user's password is hashed, the end is to be saved in the database, so the encryption will be byte[] also to be converted to String.
1. the conversion of string to byte[] is simple because the string class has a direct function:
Public byte[] GetBytes (Charset Charset) { if (Charset = = null) throw new NullPointerException (); Return Stringcoding.encode (charset, value, 0, value.length); } /** * Encodes this {@code String} into a sequence of bytes using the * platform ' s default charset, storing the Res Ult into a new byte array. * * @return The resultant byte array * * @since JDK1.1 * /public byte[] GetBytes () { return Stringcoding.encode (value, 0, value.length); }
2. However, the conversion of byte[] to string is not so simple
The reason for this is that we cannot simply use a function that uses string:
/** * Constructs a new {@code String} by decoding the specified array of bytes * Using the platform ' s default CharSet. The length of the new {@code * String} is a function of the charset, and hence if not being equal to the * length of The byte array. * * <p> the behavior of the constructor when the given bytes was not valid * in the default charset is UNSP Ecified. The {@link * Java.nio.charset.CharsetDecoder} class should is used when more control * over the decoding process I s required.*/public String (byte bytes[]) {This (bytes, 0, bytes.length); }/** * Constructs a new {@code String} by decoding the specified array of * bytes using the specified {@linkpla In Java.nio.charset.Charset charset}. * The length of the new {@code String} is a function of the charset, and * hence may isn't equal to the length of the A byte array. * * <p> This method always replaces Malformed-input and Unmappable-chaRacter * Sequences with this charset ' s default replacement string. The {@link * Java.nio.charset.CharsetDecoder} class should is used when more control * over the decoding process I s required.*/public String (byte bytes[], Charset Charset) {This (bytes, 0, bytes.length, Charset); }
That is, you cannot use the new String (byte); You cannot also use the new String (Byte, CharSet).
Why is it?
Very simple because, MD5, SHA-256, SHA-512 and so on algorithm, they are through the byte[] to perform various transformations and operations, get encrypted byte[], then this encrypted byte[] results will obviously not conform to any one of the coding scheme, such as Utf-8, GBK, because the process of encrypting is arbitrary to byte[]. So you use any encoding scheme to decode the encrypted byte[] results, the resulting will be garbled .
So, how do we convert the encrypted result byte[] to a string?
First, let's ask, why convert the encrypted byte[] to a String?
The answer is because one is to store the results of the encryption, such as in the database, the second is the one-way irreversible hash encryption algorithm for password encryption, we need to determine whether the user login password is correct, then involves two encryption after the byte[] to compare, see whether they are consistent. Two byte[] For comparison, you can compare one single byte at a time, or you can compare multiple bytes at a time. You can also convert to a string and then compare two strings. Because the encryption results are stored, they are actually chosen to be converted to strings for comparison.
Encryption and decryption, the use of byte[] to a String conversion method is the byte[] binary using 16 char[] to represent, each byte is 8 bit, each 4 bit corresponds to a 16 character. So a byte corresponds to two 16 binary characters:
public class Hexutil { private static final char[] DIGITS = { ' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9 ' , ' A ', ' B ', ' C ', ' d ', ' e ', ' F ' }; public static String encodetostring (byte[] bytes) { char[] encodedchars = encode (bytes); return new String (encodedchars); } public static char[] Encode (byte[] data) { int l = data.length; Char[] out = new char[l << 1]; The characters form the hex value. for (int i = 0, j = 0; i < L; i++) { out[j++] = digits[(0xF0 & Data[i]) >>> 4]; Out[j++] = digits[0x0f & Data[i]; } return out; }
We know that the 16 binary expression is using the 0-9 abcdef 16 numbers and letters to represent 0-15 of these 16 numbers. And obviously we can use the character ' 0 ' to represent the number 0 in string conversion, we can use ' 1 ' to represent 1, and we can use ' F ' to represent 15.
So above we see 16 binary using "0-9abcdef ' 16 characters to represent 0-15 of this 16 number. The main conversion process is the public static char[] Encode (byte[] data) function:
int L = data.length; Char[] out = new char[l << 1]; The two sentences are initialized with a char[] array whose size is twice times the size of the byte[] parameter, because each byte[] is converted to 2-bit 16 binary char[].
(0xF0 & Data[i]) >>> 4 means first using 0xF0 & Data[i], removing the value on the low 4 bit (this step is superfluous), then right-moving 4-bit, getting byte[] the high 4 bits of byte in the array, and then by digits[] Array, get high 4 for the corresponding character;
DIGITS[0X0F & Data[i]] means first using 0x0F & Data[i], removing the value on the high 4 bits, and then getting the lower 4 to represent the size, and then through the digits[] array, get the lower 4 for the corresponding character;
In this way, you can speak byte[] array to convert to a 16-character representation of char[]. Last New String (Encodedchars); Gets the result of the string type.
So the last string is made up of: ' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9 ', ' A ', ' B ', ' C ', ' d ', ' e ', ' F ' These 16 characters are composed of a string that does not contain any of its letters. such as not g,h,jklmn ..... Wait a minute.
3. Reverse conversion: String to byte[]
Above we implemented the conversion of byte[] to String, the encoding scheme uses 16 binary encoding. So how do you reverse decode it? That is, converting a 16-encoded string into the original byte[]?
/** * Converts the specified hex-encoded String into a raw byte array. This is a * convenience method, merely delegates to {@link #decode (char[])} using the * argument ' s Hex.tochara Rray () value. * * @param hex a hex-encoded String. * @return A byte array containing binary data decoded from the supplied String ' s char array. */public static byte[] Decode (String hex) {return decode (Hex.tochararray ()); }/** * Converts an array of characters representing hexidecimal values to an * array of bytes of those same Values. The returned array would be half the * length of the passed array, as it takes and the characters to represent any * gi Ven byte. An exception is thrown if the passed Char array have an odd * number of elements. * * @param data An array of characters containing hexidecimal digits * @return A byte array containing binary data Decoded from * the supplied char array. * @throws IllegaLargumentexception If an odd number or illegal of characters * is supplied */ public static byte[] Decode (char[] data) throws illegalargumentexception {int len = data.length; if (len & 0x01)! = 0) {throw new IllegalArgumentException ("ODD number of characters."); } byte[] out = new Byte[len >> 1]; The characters form the hex value. for (int i = 0, j = 0; j < Len; i++) {int f = todigit (Data[j], J) << 4; j + +; f = f | Todigit (Data[j], J); j + +; Out[i] = (byte) (F & 0xFF); } return out; }
protected static int todigit (char ch, int index) throws IllegalArgumentException {
int digit = CHARACTER.DIGIT (CH, 16);
if (digit = =-1) {
throw new IllegalArgumentException ("illegal hexadecimal charcter" + ch + "at index" + index);
}
return digit;
}
To convert a 16-encoded string into the original byte[], the first step is to convert the string type to the char[] array, which is to convert "10ae4f" to [' 1 ', ' 0 ', ' a ', ' e ', ' 4 ', ' F '], and then no two connected Char into a byte. Obviously the size of the char[] array must be an even number.
Byte[] out = new Byte[len >> 1]; Byte[] The result is half the size of char[].
Todigit (Data[j], j) << 4 means: todigit () converts a character to a 16-decimal int size, which translates ' 0 ' to a number 0, ' f ' to a number F, then 4 bits to the left, and a high 4-bit for byte[];
f = f | Todigit (Data[j], J); Indicates that the number corresponding to the character is first obtained, then the lower 4 bits, and the high 4 for the merge (using the | operator) as a full 8-bit byte.
Out[i] = (byte) (F & 0xFF); Keep only 8 bits and remove the extra high.
is actually the reverse process above.
4. Example
public class Encodetest {public static void Main (string[] args) { String str = "??? Hello/sasewredfdd>>>. Hello World! "; System.out.println ("str.getbytes () =" + str.getbytes ()); System.out.println ("base64=" + base64.encodetostring (Str.getbytes ())); String hexstr = hexutil.encodetostring (Str.getbytes ()); Str.getbytes (Charset.forname ("Utf-8")); System.out.println ("hexstr=" + hexstr); String orignalstr = new String (Str.getbytes ()); New String (Str.getbytes (), Charset.forname ("Utf-8")); System.out.println ("orignalstr=" + orignalstr); String str2 = new String (Hexutil.decode (HEXSTR)); System.out.println ("str2=" + str2); System.out.println (Str.equals (str2)); String sha = new Simplehash ("sha-256", str, "11d23ccf28fc1e8cbab8fea97f101fc1d", 2). toString (); System.out.println ("sha=" + sha);} }
Results:
Str.getbytes () =[[email protected]base64=pz8/agvsbg8vc2fzzxdyzwrmzgq+pj4uiehlbgxvios4luevjo+8gq==hexstr= 3f3f3f68656c6c6f2f73617365777265646664643e3e3e2e2048656c6c6f20e4b896e7958cefbc81orignalstr=??? Hello/sasewredfdd>>>. Hello World! Str2=??? Hello/sasewredfdd>>>. Hello World! truesha=37a9715fecb5e2f9812d4a02570636e3d5fe476fc67ac34bc824d6a8f835635d
The last New Simplehash ("sha-256", str, "11d23ccf28fc1e8cbab8fea97f101fc1d", 2). ToString (), whose. ToString () method is used by the The 16 binary encoding converts the byte[after the hash encryption to a 16-binary string.
We can see the result: 37a9715fecb5e2f9812d4a02570636e3d5fe476fc67ac34bc824d6a8f835635d
All consists of ' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9 ', ' A ', ' B ', ' C ', ' d ', ' e ', ' f ', which are 16 characters. Does not contain any other characters.
We also have the BASE64 coding scheme:
Base64.encodetostring (Str.getbytes ())
It actually uses a-Z, A-Z, 0-9,/, + 64 characters to encode, 0-63 to apply the preceding 64 characters.
The result of the coding is characterized by: there may be 1 or 2 at the end =:
Pz8/agvsbg8vc2fzzxdyzwrmzgq+pj4uiehlbgxvios4luevjo+8gq= =
The reason for this is that the BASE64 encoding algorithm is each processing the byte[] array of three consecutive byte, then it is possible byte[] array is not an integer multiple of 3, then the remainder may be 1, or 2, so the use of one = and two = to fill.
So:
The BASE64 encoding is characterized by the possibility that there is at the end of one or two =, which may contain/and + characters.
The 16 encoding feature is all by ' 0 ', ' 1 ', ' 2 ', ' 3 ', ' 4 ', ' 5 ', ' 6 ', ' 7 ', ' 8 ', ' 9 ', ' A ', ' B ', ' C ', ' d ', ' e ', ' F ' are composed of 16 characters, with no other letters.
The encryption algorithm is the transformation and operation of byte[].
Byte[] With a string conversion must be converted to the original string using the original encoding scheme,
But the result of the encryption byte[] can not be used in any character encoding scheme to get a string, generally using 16 binary encoding into a string, and then stored or compared.
Transferred from: http://www.cnblogs.com/digdeep/p/4627813.html
Cryptographic decryption Fundamentals: byte arrays and (16) string conversions (RPM)