2

MEID (長さ 14 の 16 進数) を疑似 ESN (長さ 8 の 16 進数) に変換できるプログラムを作成しようとしています。MEID から pESN を取得する方法は、理論的にはかなり単純です。たとえば、MEID 0xA0000000002329 の場合、pESN を作成するには、MEID に SHA-1 を適用する必要があります。A0000000002329 の SHA-1 は、e3be267a2cd5c861f3c7ea4224df829a3551f1ab を提供します。この結果の最後の 6 つの 16 進数を取得し、それを 0x80 に追加します。結果は 0x8051F1AB です。

今ここに私がこれまでに持っているコードがあります:

public void sha1() throws NoSuchAlgorithmException {

    String hexMEID = "A0000000002329";

    MessageDigest mDigest = MessageDigest.getInstance("SHA1");      
    byte[] b = new BigInteger(hexMEID,16).toByteArray();    

    byte[] result = mDigest.digest(b);
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < result.length; i++) {
        sb.append(Integer.toString((result[i] & 0xff) + 0x100, 16).substring(1));
    }

    System.out.println(sb.toString());
}

問題は、この方法を使用すると、A0000000002329 の SHA-1 が e3be267a2cd5c861f3c7ea4224df829a3551f1ab の代わりに 6ad447f040941bf43c0693d2b391c6c79fa58320 を与えることです。ここで何が間違っていますか??

誰かがヒントをくれた

トリックは、MEID を表す文字列ではなく、MEID を表す数値に SHA-1 を適用することです。バイト単位で処理する必要があるため、一度に 2 つの 16 進数を指定し (2 つの 16 進数で 1 バイトを構成するため)、それらが ASCII 文字ではなく数値として解釈されるようにする必要があります

これらの指示が正しい場合、SHA-1 を 16 進数にバイト単位で適用するにはどうすればよいですか??

4

2 に答える 2

4

BigIntegerを使用してバイト配列を取得した結果、小さな問題があります。MEID の長さはわずか 7 バイトであるため、BigInteger を介してポンピングすると、BigInteger が符号を保持するエクスタ バイトを出力するため、長さ 8 のバイト配列が得られます。もちろん、この余分なバイトにより、入力の SHA-1 ハッシュが完全に異なります。剥がす必要があります。

HEX MEID から ESN へのコードは次のようになります。

String hexMEID = "A0000000002329";
MessageDigest mDigest = MessageDigest.getInstance( "SHA1" );

byte[] input = new byte[ 7 ]; // MEIDs are only 7 bytes

// Now copy the bytes from BigInteger skipping the extra byte added by it
System.arraycopy( new BigInteger( hexMEID, 16 ).toByteArray(), 1, input, 0, 7 );

// Get the SHA-1 bytes
byte[] result = mDigest.digest( input );

// Build the SHA-1 String
StringBuilder sb = new StringBuilder();
for ( int i = 0; i < result.length; i++ )
{
    String hex = Integer.toHexString( 0xFF & result[ i ] );
    if ( hex.length() == 1 )
    {
        sb.append( '0' );
    }
    sb.append( hex );
}

String sha1 = sb.toString();
// Grab the last 6 characters of the SHA-1 hash
String lastSix = sha1.substring( sha1.length() - 6 );
// And prepend '80', now you have the ESN
System.out.println( "80" + lastSix );
// Will print 8051f1ab which is exactly what you want
于 2012-08-07T05:48:31.193 に答える
2

Strelok はBigInteger、返された配列に余分なバイトを追加することに関する問題を発見しました。このより単純なバージョンでも、期待される結果が得られます。

String hexMEID = "A0000000002329";

MessageDigest mDigest = MessageDigest.getInstance("SHA1");

byte[] b = new BigInteger(hexMEID,16).toByteArray();

// skip the first byte set by BigInteger and retain only 7 bytes (length of MEID)
byte[] result = mDigest.digest(Arrays.copyOfRange(b, 1, 8));

StringBuilder sb = new StringBuilder("80");

// need only the last 3 bytes
for (int i=17; i<20; i++) {
    sb.append(Integer.toHexString((result[i] & 0xff) | 0x100).substring(1));
}

String pESN = sb.toString();
System.out.println(pESN);
// -> 8051f1ab
于 2012-08-07T15:55:07.117 に答える