Как SHA1 хэшировать строку в Android? - PullRequest
64 голосов
/ 12 мая 2011

В Objective C я использовал следующий код для хеширования строки:

-(NSString *) sha1:(NSString*)stringToHash {    
    const char *cStr = [stringToHash UTF8String];
    unsigned char result[20];
    CC_SHA1( cStr, strlen(cStr), result );
    return [NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
        result[0], result[1], result[2], result[3], 
        result[4], result[5], result[6], result[7],
        result[8], result[9], result[10], result[11],
        result[12], result[13], result[14], result[15],
        result[16], result[17], result[18], result[19]
        ];  
}

Теперь мне нужно то же самое для Android, но я не могу понять, как это сделать. Например, я искал следующее: Сделать шифрование SHA1 на Android? но это не дает мне такой же результат, как на iPhone. Кто-нибудь может указать мне правильное направление?

Ответы [ 8 ]

152 голосов
/ 12 мая 2011

Вам не нужен andorid для этого. Вы можете просто сделать это в простой Java.

Вы пробовали простой пример Java и посмотрите, вернет ли это правильный sha1.

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class AeSimpleSHA1 {
    private static String convertToHex(byte[] data) {
        StringBuilder buf = new StringBuilder();
        for (byte b : data) {
            int halfbyte = (b >>> 4) & 0x0F;
            int two_halfs = 0;
            do {
                buf.append((0 <= halfbyte) && (halfbyte <= 9) ? (char) ('0' + halfbyte) : (char) ('a' + (halfbyte - 10)));
                halfbyte = b & 0x0F;
            } while (two_halfs++ < 1);
        }
        return buf.toString();
    }

    public static String SHA1(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        MessageDigest md = MessageDigest.getInstance("SHA-1");
        byte[] textBytes = text.getBytes("iso-8859-1");
        md.update(textBytes, 0, textBytes.length);
        byte[] sha1hash = md.digest();
        return convertToHex(sha1hash);
    }
}

Также поделитесь, каким должен быть ваш ожидаемый sha1. Может быть, ObjectC делает это неправильно.

35 голосов
/ 16 августа 2012

Более простой метод SHA-1: ( обновлено по предложениям комментатора, также с использованием гораздо более эффективного алгоритма byte-> string )

String sha1Hash( String toHash )
{
    String hash = null;
    try
    {
        MessageDigest digest = MessageDigest.getInstance( "SHA-1" );
        byte[] bytes = toHash.getBytes("UTF-8");
        digest.update(bytes, 0, bytes.length);
        bytes = digest.digest();

        // This is ~55x faster than looping and String.formating()
        hash = bytesToHex( bytes );
    }
    catch( NoSuchAlgorithmException e )
    {
        e.printStackTrace();
    }
    catch( UnsupportedEncodingException e )
    {
        e.printStackTrace();
    }
    return hash;
}

// /6489417/kak-preobrazovat-baitovyi-massiv-v-shestnadtsaterichnuy-stroku-v-java
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex( byte[] bytes )
{
    char[] hexChars = new char[ bytes.length * 2 ];
    for( int j = 0; j < bytes.length; j++ )
    {
        int v = bytes[ j ] & 0xFF;
        hexChars[ j * 2 ] = hexArray[ v >>> 4 ];
        hexChars[ j * 2 + 1 ] = hexArray[ v & 0x0F ];
    }
    return new String( hexChars );
}
27 голосов
/ 10 октября 2013

Если вы можете обойтись без , используя Гуаву, это, безусловно, самый простой способ сделать это , и вам не нужно изобретать велосипед:

final HashCode hashCode = Hashing.sha1().hashString(yourValue, Charset.defaultCharset());

Вы можетезатем возьмите хэшированное значение и получите его как byte[], как int, или как long.

. Нет переноса в триггере, нет махинаций.И если вы решите, что хотите использовать что-то иное, чем SHA-1, Guava также поддерживает sha256, sha 512 и некоторые из них, о которых я никогда даже не слышал, например, adler32 и murmur3.

15 голосов
/ 20 июня 2012
final MessageDigest digest = MessageDigest.getInstance("SHA-1");
result = digest.digest(stringToHash.getBytes("UTF-8"));

// Another way to construct HEX, my previous post was only the method like your solution
StringBuilder sb = new StringBuilder();

for (byte b : result) // This is your byte[] result..
{
    sb.append(String.format("%02X", b));
}

String messageDigest = sb.toString();
14 голосов
/ 21 октября 2015

Полностью основываясь на ответе @ Whymarrh, это моя реализация, протестирована и работает нормально, без зависимостей:

public static String getSha1Hex(String clearString)
{
    try
    {
        MessageDigest messageDigest = MessageDigest.getInstance("SHA-1");
        messageDigest.update(clearString.getBytes("UTF-8"));
        byte[] bytes = messageDigest.digest();
        StringBuilder buffer = new StringBuilder();
        for (byte b : bytes)
        {
            buffer.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1));
        }
        return buffer.toString();
    }
    catch (Exception ignored)
    {
        ignored.printStackTrace();
        return null;
    }
}
8 голосов
/ 15 марта 2013

Android поставляется с кодеком Apache Commons - или вы добавляете его в качестве зависимости.Затем выполните:

String myHexHash = DigestUtils.shaHex(myFancyInput);

Это старый устаревший метод, который используется в Android 4 по умолчанию.В новых версиях DigestUtils представлены все разновидности методов shaHex (), таких как sha256Hex (), а также перегружены методы различными типами аргументов.

http://commons.apache.org/proper/commons-codec//javadocs/api-release/org/apache/commons/codec/digest/DigestUtils.html

2 голосов
/ 23 января 2013

Метод, который вы ищете, относится не только к Android, но и к Java в целом. Вы ищете MessageDigest (import java.security.MessageDigest).

Реализация метода sha512(String s) может быть замечена здесь , и изменение для хэша SHA-1 изменило бы строку 71 на:

MessageDigest md = MessageDigest.getInstance("SHA-1");
0 голосов
/ 20 июня 2012
String.format("%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", result[0], result[1], result[2], result[3], 
    result[4], result[5], result[6], result[7],
    result[8], result[9], result[10], result[11],
    result[12], result[13], result[14], result[15],
    result[16], result[17], result[18], result[19]);
...