Cómo SHA1 hash una cadena en Android?
En Objective C he estado usando el siguiente código para hash una cadena:
-(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] ]; }
Ahora necesito lo mismo para Android, pero no puedo averiguar cómo hacerlo. He estado buscando por ejemplo en esto: ¿ Hacer cifrado SHA1 en Android? Pero eso no me da el mismo resultado que en iPhone. ¿Puede alguien señalarme en la dirección correcta?
- Problemas con la implementación hash SHA1 en Android
- ¿Cómo puedo obtener la huella dactilar MD5 del keytool de Java, no sólo SHA-1?
- Google maps api para android, obteniendo cert SHA1 en lugar de MD5
- Signin de Google Firebase dando estado 12501 (no funciona), en la versión de creación de la versión y jks SHA
- Android HMAC-SHA1 Diferente de Java estándar HMAC-SHA1
- SHA1 en Java y PHP con resultados diferentes
- Cómo obtener la huella digital SHA1 de Mavericks
- Obtenga el certificado de huella digital SHA1 en Android Studio para Google Maps
- Android SHA1 liberación keystore no funciona con Google Maps
- SHA1 Tecla para DEBUG & RELEASE ANDROID STUDIO MAC
- Propósito del certificado de firma de depuración de Android / Firebase SHA-1
- Cómo agregar SHA-1 a la aplicación Android
- Android: Google Map v2 no muestra mapa para la versión apk
Usted no necesita andorid para esto. Sólo puede hacerlo en java simple.
¿Has probado un ejemplo java simple y ver si esto devuelve el sha1 correcto.
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); } }
También comparta lo que su sha1 esperado debe ser. Tal vez ObjectC está haciendo mal.
Un método SHA-1 más simple: ( actualizado a partir de las sugerencias del comentarista, también usando un algoritmo de byte-> cadena masivamente más eficiente )
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 ); }
Si usted puede conseguir lejos con el uso de guayaba es por lejos la manera más simple de hacerlo , y usted no tiene que reinventar la rueda:
final HashCode hashCode = Hashing.sha1().hashString(yourValue, Charset.defaultCharset());
A continuación, puede tomar el valor hash y obtenerlo como un byte[]
, como un int
, o como un long
.
No envolver en un try catch, sin travesuras. Y si decides que quieres usar algo distinto de SHA-1, Guava también es compatible con sha256, sha 512, y unos cuantos yo nunca había oído hablar como adler32 y murmur3.
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();
Android viene con el Codec de Commons de Apache o lo agregas como dependencia. Entonces hazlo:
String myHexHash = DigestUtils.shaHex(myFancyInput);
Este es el antiguo método obsoleto que obtienes con Android 4 de forma predeterminada. Las nuevas versiones de DigestUtils traen todos los sabores de los métodos de shaHex () como sha256Hex () y también sobrecarga los métodos con diversos tipos del argumento.
Totalmente basado en la respuesta de @ Whymarrh, esta es mi implementación, probada y funcionando bien, sin dependencias:
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; } }
El método que buscas no es específico de Android, sino de Java en general. Está buscando el MessageDigest ( import java.security.MessageDigest
).
Se puede ver una implementación de un sha512(String s)
aquí , y el cambio para un hash SHA-1 cambiaría la línea 71 a:
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]);
- ¿Por qué estoy recibiendo un error? El canal está irreparablemente roto y se eliminará.
- ScrollView Layout no llena toda la pantalla