如何在Android中对字符串进行SHA1哈希处理?

Mar*_*tin 65 hash android sha1

在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]
        ];  
}
Run Code Online (Sandbox Code Playgroud)

现在我需要相同的Android,但无法找到如何做到这一点.我一直在寻找这样的例子:在Android上进行SHA1加密? 但这并没有给我与iPhone相同的结果.谁能指出我正确的方向?

Ami*_*far 154

你不需要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);
    }
}
Run Code Online (Sandbox Code Playgroud)

同时分享你期望的sha1应该是什么.也许ObjectC做错了.

  • 为什么iso-8559-1编码而不是UTF-8?除非您需要与某些现有应用程序兼容,否则这些是使用此类遗留编码的理由. (23认同)
  • 正如下面提到的那样,text.length()不正确,因为它不会返回字节数.您需要使用getBytes返回的数组的长度.而且,是的,它可能不应该是iso-8859. (8认同)

Ada*_*dam 35

一个更简单的SHA-1方法:( 根据评论者的建议更新,也使用更高效的字节 - >字符串算法)

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;
}

// http://stackoverflow.com/questions/9655181/convert-from-byte-array-to-hex-string-in-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 );
}
Run Code Online (Sandbox Code Playgroud)

  • 使用默认编码(`somestring.GetBytes()`)将为您提供依赖于平台的哈希.不太好.使用固定编码,最好是UTF-8. (4认同)
  • 如果sha1字符串应该以0开头,则忽略0.因此,在某些情况下,此方法返回错误的sha-1编码字符串. (2认同)
  • 警告:如果要哈希'1122'则不起作用,它从0开始 (2认同)

yar*_*ian 28

如果你可以使用番石榴,它是迄今为止最简单的方法,你不必重新发明轮子:

final HashCode hashCode = Hashing.sha1().hashString(yourValue, Charset.defaultCharset());
Run Code Online (Sandbox Code Playgroud)

然后,您可以获取散列值并将其作为a byte[],as int或a long.

没有包裹在尝试捕获,没有shenanigans.如果你决定要使用除SHA-1以外的东西,Guava还支持sha256,sha 512,以及一些我从未听说过像adler32和murmur3那样的东西.

  • 我真的很喜欢这个答案,因为它很适合Android,并且不需要我仔细检查SO代码的安全漏洞:p (3认同)

小智 17

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();
Run Code Online (Sandbox Code Playgroud)

  • 注意:如果要避免大小写,请使用"%02x". (3认同)

cpr*_*ack 16

完全基于@ 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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Ris*_*nha 8

Android附带Apache的Commons Codec - 或者您将其添加为依赖项.然后做:

String myHexHash = DigestUtils.shaHex(myFancyInput);
Run Code Online (Sandbox Code Playgroud)

这是默认使用Android 4时旧的弃用方法.新版本的DigestUtils带来了所有类型的shaHex()方法,如sha256Hex(),并且还使用不同的参数类型重载方法.

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


Ben*_*ela 7

使用 Kotlin 可以将其缩短并放入一行:

MessageDigest.getInstance("SHA-1").digest(theString.toByteArray()).joinToString("") { "%02x".format(it) }
Run Code Online (Sandbox Code Playgroud)


Mak*_*kiX 7

要使用 kotlin 上的扩展函数来简化它:

/**
 * Encrypt String to SHA1 format
 */
fun String.toSha1(): String {
    return MessageDigest
        .getInstance("SHA-1")
        .digest(this.toByteArray())
        .joinToString(separator = "", transform = { "%02x".format(it) })
}
Run Code Online (Sandbox Code Playgroud)