Как 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. Может ли кто-нибудь указать мне в правильном направлении?
8 ответов:
вам не нужен Андроид для этого. Вы можете просто сделать это в простой 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 делает это неправильно.
более простой метод 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 ); }
если вы можете уйти с использование гуавы это, безусловно, самый простой способ сделать это, и вам не нужно изобретать колесо:
final HashCode hashCode = Hashing.sha1().hashString(yourValue, Charset.defaultCharset());
затем вы можете взять хэшированное значение и получить его как
byte[]
, какint
илиlong
.нет обертывания в попытке поймать, никаких махинаций. И если вы решите использовать что-то другое, кроме SHA-1, Guava также поддерживает sha256, sha 512 и некоторые из них, о которых я никогда не слышал, например adler32 и мурмур3.
final MessageDigest digest = MessageDigest.getInstance("SHA-1"); result = digest.digest(stringToHash.getBytes("UTF-8"); // Another way to make 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();
полностью основанный на ответе @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; } }
Android поставляется с общим кодеком Apache - или вы добавляете его как зависимость. Тогда сделайте:
String myHexHash = DigestUtils.shaHex(myFancyInput);
Это старый устаревший метод, который вы получаете с Android 4 по умолчанию. Новые версии DigestUtils приносят все ароматы методов shaHex (), таких как sha256Hex (), а также перегружают методы различными типами аргументов.
метод, который вы ищете, не относится к Android, но к Java в целом. Вы ищете MessageDigest (
import java.security.MessageDigest
).реализация a
sha512(String s)
метод можно увидеть здесь, и изменение для хэша SHA-1 будет изменять строку 71 на:MessageDigest md = MessageDigest.getInstance("SHA-1");
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]);