2016-10-26 8 views
2

Ich habe begonnen, mit JJWT zu arbeiten, um JWT auf meiner Server-Anwendung zu behandeln.Statisches Geheimnis als Byte [], Key oder String?

Mein JWT-Geheimnis wird bei resources Ordner gespeichert und ich werde das Geheimnis mit Properties Klasse laden.

Die JJWT drei Methoden bietet die JWT zu unterzeichnen, verwendet man byte[], andere Verwendungen String und die anderen Verwendungen Key:

JwtBuilder signWith(SignatureAlgorithm var1, byte[] var2); 

JwtBuilder signWith(SignatureAlgorithm var1, String var2); 

JwtBuilder signWith(SignatureAlgorithm var1, Key var2); 

Die Frage: In Bezug auf Sicherheit, charset und andere Dinge, gibt es irgendwelche Empfehlungen von denen sollte ich verwenden?

Für während ich stehe mit String, seit Properties eine String zurückgeben.

+1

Sicherheit weise (extreme Maßnahmen), sagt diese Antwort Strings sind weniger gesichert (kurz, wegen String-Pool): http://StackOverflow.com/A/8881376/641627 – alexbt

Antwort

4

Die JavaDoc für signWith(SignatureAlgorithm var1, String var2) gibt Erwartungen, und die Methodenparameter intuitiv sogar Namen:

/** 
* Signs the constructed JWT using the specified algorithm with 
* the specified key, producing a JWS. 
* 
* <p> 
* This is a convenience method: the string argument is first 
* BASE64-decoded to a byte array and this resulting byte array is 
* used to invoke {@link #signWith(SignatureAlgorithm, byte[])}. 
* </p> 
* 
* @param alg     the JWS algorithm to use to digitally 
*        sign the JWT, thereby producing a JWS. 
* 
* @param base64EncodedSecretKey the BASE64-encoded algorithm-specific 
*        signing key to use to digitally sign 
*        the JWT. 
* 
* @return the builder for method chaining. 
*/ 
JwtBuilder signWith(SignatureAlgorithm alg, String base64EncodedSecretKey); 

Also, diese Methode der String-Argument erwartet eine Base64-codierte Geheimschlüssel Byte-Array zu sein. Es nicht eine allgemeine Zeichenfolge, wie ein Benutzerkennwort zum Beispiel als Signierschlüssel annehmen. JJWT geht von der Base64-Kodierung aus, da Sie, wenn Sie ein Zeichenfolgenkennwort angeben, das nicht Base64-kodiert ist, wahrscheinlich einen schlecht formatierten oder schwachen Schlüssel verwenden.

Die JWT-JWA-Spezifikation REQUIRES, dass HMAC-Signaturschlüssel Längen gleich oder größer als die Signatur Byte-Array-Länge haben.

Das bedeutet, dass:

| If you're signing with: | your key (byte array) length MUST be: | 
| ----------------------- | ------------------------------------- | 
| HMAC SHA 256   | >= 256 bits (32 bytes)    | 
| HMAC SHA 384   | >= 384 bits (48 bytes)    | 
| HMAC SHA 512   | >= 512 bits (64 bytes)    | 

Viele Online JWT Websites und Tools nur gerade diese Ebene falsch - sie ermöglichen es Ihnen zu denken, dass Sie in oder eine alte Zeichenfolge verwenden geben könnte und du bist gut. Einige gehen sogar so weit, den Schlüssel mit dem Wort secret vorzufüllen (eindeutig eine schlechte Idee und nicht einmal spezifikationskonform, weil es zu kurz ist!).

Damit Sie dies vereinfachen können, bietet JJWT ein Hilfsprogramm, mit dem Sie genügend sichere Zufallsschlüssel generieren können, die für die spezifikationskonforme Signatur über die Klasse io.jsonwebtoken.impl.crypto.MacProvider geeignet sind.

Sehen Sie sich die verschiedenen generateKey Methoden an, um zu sehen, wie Sie einen guten, spezifikationskonformen Schlüssel für HMAC-Signaturen generieren können. Zum Beispiel:

//creates a 256-bit secure-random key: 
MacProvider.generateKey(SignatureAlgorithm.HS256); 

//creates a 384-bit secure-random key: 
MacProvider.generateKey(SignatureAlgorithm.HS384); 

//creates a 512-bit secure-random key (the default): 
MacProvider.generateKey(); 

Wenn Sie diese generierten Schlüssel als String speichern wollten, könnten Sie vermutlich Base64 kodieren sie:

SecretKey key = MacProvider.generateKey(); 
byte[] keyBytes = key.getEncoded(); 

String base64Encoded = TextCodec.BASE64.encode(keyBytes); 

Aber Anmerkung: die resultierende base64Encoded String nicht als sicher jemandem zeigen. Die Base64-Codierung ist keine Verschlüsselung - der Wert muss weiterhin geheim gehalten werden. Wie Sie dies tun, liegt bei Ihnen (verschlüsseln Sie es, usw.).

Nun, wenn es Zeit ist, eine JWS zu erstellen, können Sie in diesem base64Encoded Wert nur passieren, und JJWT wissen zu Base64 dekodieren es zuerst die realen Bytes zu erhalten, die dann dazu verwendet werden, um die Signatur zu berechnen:

Jwts.builder() 
    //... 
    .signWith(SignatureAlgorithm.HS512, base64Encoded) 
    .compact(); 
+0

Diese Antwort ist so nützlich, um zu verstehen, wie wir sollte das 'Geheimnis' schaffen und wie wir es über JJWT handhaben sollten. Ich kannte diese Anforderung über die Länge des "Geheimnisses" nicht. Nochmals vielen Dank dafür. Aber ich denke, diese Antwort ist nicht vollständig. Sie könnten etwas hinzufügen: Die Verwendung von 'Key' ist sicherer, da die 'SecretKey'-Implementierung sicherstellt, dass vertrauliche Schlüsselinformationen aus dem Speicher gelöscht werden, wenn dieses Objekt für die Garbage Collection geeignet ist. – Paulo

+0

@Paulo das ist ein schöner Punkt und sollte im Projekt dokumentiert werden. Würde es Ihnen etwas ausmachen, ein GitHub-Problem zu öffnen, um das hinzuzufügen? Es würde geschätzt werden! –

+1

Ich öffnete dieses Problem dafür: https://github.com/jwtk/jjwt/issues/184 – Paulo

Verwandte Themen