Как SHA1 хэш строку в Android?
В 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. Может ли кто-нибудь указать мне в правильном направлении?
Ответы
Ответ 1
Для этого вам не нужен 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 делает это неправильно.
Ответ 2
Более простой метод 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;
}
// 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 );
}
Ответ 3
Если вы можете уйти с с помощью Guava, это самый простой способ сделать это, и вам не нужно изобретать колесо:
final HashCode hashCode = Hashing.sha1().hashString(yourValue, Charset.defaultCharset());
Затем вы можете взять хешированное значение и получить его как byte[]
, как int
, или как long
.
Нет обертывания в try catch, no shenanigans. И если вы решите, что хотите использовать что-то другое, кроме SHA-1, Guava также поддерживает sha256, sha 512 и несколько, о которых я даже не слышал, как adler32 и murmur3.
Ответ 4
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();
Ответ 5
Полностью основанный на ответе @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;
}
}
Ответ 6
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
Ответ 7
Метод, который вы ищете, не специфичен для Android, а для Java в целом. Вы ищете MessageDigest (import java.security.MessageDigest
).
Реализация метода sha512(String s)
можно увидеть здесь, а изменение для хэша SHA-1 изменит линию 71 на
MessageDigest md = MessageDigest.getInstance("SHA-1");
Ответ 8
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]);