webForumDet fria alternativet

JPasswordField till SHA1-sträng.

10 svar · 906 visningar · startad av erciz

ercizMedlem sedan maj 20011 826 inlägg
#1

Jag vill låta användaren logga in till mitt program. För lösenordsinmatningen tänkte jag använda JPasswordField, vars metod getPassword() returnerar en char[], hur gör jag för att hasha detta lösenord till en SHA1-sträng på 40 tecken (SHA-1 160 bitar)? Har tittat lite på MessageDigest-paketet men får inte fram nåt vettigt.

SPiNMedlem sedan mars 20007 896 inlägg
#2

Räcker det inte med SHA, som finns färdigt i Suns paket? Jag vet inte riktigt om det är någon skillnad mot SHA-1?

Helt otestat med SHA;

import java.security.MessageDigest;

...
    MessageDigest md = MessageDigest.getInstance("SHA");
    md.update(new String(jPasswordField.getPassword()).getBytes());
    byte[] hash = md.digest();
...
ercizMedlem sedan maj 20011 826 inlägg
#3

Tack SPiN, testade lite:

MessageDigest sha1 = null;
try {
	sha1 = MessageDigest.getInstance("SHA-1");
} catch (NoSuchAlgorithmException e1) {
	e1.printStackTrace();
}
char[] data = passwordFld.getPassword();

sha1.update(new String(data).getBytes());
System.out.println("Password: " + new String(data));
System.out.println("Algorithm: " + sha1);
System.out.println("Digest: " + sha1.digest());

vilket resulterade i dessa utskrifter:

Password: Hej
Algorithm: SHA-1 Message Digest from SUN, <in progress>
Digest: [B@1e6e305

Jag antar att Digest är den binära hash-summan. Går det att få det i en sträng? så jag enklare kan spara den i XML och databaser, den ska ju vara 40 tecken då. Har bara gjort detta i PHP förut.

SPiNMedlem sedan mars 20007 896 inlägg
#4

Konstruktorn till String tar en array av bytes, vilket du får ut av MessageDigest.digest().

ercizMedlem sedan maj 20011 826 inlägg
#5

SPiN skrev:

Konstruktorn till String tar en array av bytes, vilket du får ut av MessageDigest.digest().

Då får jag

Digest: {Ï‚ù\ùf*™X·k€

Kom på att i PHP kanke SHA1-hashen är base64-kodad, ska testa med det. Finns det nån base64-funktion i Java:s standardbibliotek?

SPiNMedlem sedan mars 20007 896 inlägg
#6

Ja, det är i rå-format du får ut informationen. Du borde kunna göra någon konverterare relativt enkelt (hittade något på nätet);

public String byteArrayToHexString(byte[] bytes) {
    String hex = "";
    for (byte b : bytes)
        hex += Integer.toString((b & 0xFF) + 0x100, 16).substring(1);

    return hex;
}

Du borde även kunna läsa med en java.io.ByteArrayInputStream, om det känns bättre.

PHPs motsvarigheter har hex-värdet som default returvärde, men man kan ange om man vill ha det i råformat eller inte.

ercizMedlem sedan maj 20011 826 inlägg
#7

Tack SPiN, jag kommer närmare ;)

PHP:  7bcf82f95cf9662a995805b76b80006c65a79718
Java: da39a3ee5e6b4b0d3255bfef95601890afd80709
Klartext: Hej

Det var med hexfunktionen du angav, så nu får jag bara leta på en kompatibel. Men är på rätt spår!

Raw-värdena för PHP och Java ser ut att bli likadana.

SPiNMedlem sedan mars 20007 896 inlägg
#8

Ett alternativt sätt som tydligen ska vara effektivt;

String hex = new java.math.BigInteger(1, sha.digest()).toString(16);
ercizMedlem sedan maj 20011 826 inlägg
#9

SPiN skrev:

Ett alternativt sätt som tydligen ska vara effektivt;

String hex = new java.math.BigInteger(1, sha.digest()).toString(16);

Ja, det var ju klart snyggare än de andra jag testat, har googlat lite, men alla metoder verkar ge samma resultat som jag redan skrivit för Java. Testade nu i MySQL och det gav samma svar som PHP, så det verkar som de använder nån annan algorithm för att göra om SHA-1 till Hex-sträng.

SELECT SHA1('Hej');
7bcf82f95cf9662a995805b76b80006c65a79718
ercizMedlem sedan maj 20011 826 inlägg
#10

Fick lite tips på denna sida: http://forums.sun.com/thread.jspa?threadID=5349070
Laddade ner "Jakarta Commons Codec", från Apache: http://commons.apache.org/codec/

Sen använde jag

DigestUtils.shaHex("Hej");
7bcf82f95cf9662a995805b76b80006c65a79718

Så nu funkar det, vet egentligen inte vad det var för fel innan, men vi gjorde väl inte hex-omvandlingen på "rätt sätt".

SPiNMedlem sedan mars 20007 896 inlägg
#11

Jag letade runt lite, och har uppfattat det som att problemet beror på att Java "kastar bort" inledande 0. Så 0x01 resulterar i 1 och inte 01, t.ex.

Åtgärden verkar i de flesta fall (alla?) ha varit att göra precis som du gjort, använda sig av tredjeparts-biblioteket DigestUtils från Apache Commons. :)

135 ms totalt · 3 externa anrop · v20260731065814-full.fb544a5a
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
132 ms — hämta tråd, inlägg och bilagor (db)