Cryptographic decryption Fundamentals: byte arrays and (16) string conversions

Source: Internet
Author: User

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)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.