Last active
May 13, 2021 09:12
-
-
Save masatomix/d384010156b8c16881fcd0dccd315ef5 to your computer and use it in GitHub Desktop.
HS256 / RSA256 を用いたサンプル。共通鍵、公開鍵でハッシュした署名をつけるJWSのサンプルと、公開鍵で署名したJWTを検証するサンプルコード。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nu.mine.kino; | |
import java.text.ParseException; | |
import com.nimbusds.jose.JOSEException; | |
import com.nimbusds.jose.JWSAlgorithm; | |
import com.nimbusds.jose.JWSHeader; | |
import com.nimbusds.jose.JWSObject; | |
import com.nimbusds.jose.JWSVerifier; | |
import com.nimbusds.jose.KeyLengthException; | |
import com.nimbusds.jose.Payload; | |
import com.nimbusds.jose.crypto.MACSigner; | |
import com.nimbusds.jose.crypto.MACVerifier; | |
/** | |
* @author Masatomi KINO | |
* @version $Revision$ | |
*/ | |
public class HS256Main { | |
// https://connect2id.com/products/nimbus-jose-jwt/examples/jws-with-hmac | |
public static void main(String[] args) | |
throws KeyLengthException, JOSEException, ParseException { | |
String data = "Hello, world!"; | |
String key = "aaaaaaaaaabbbbbbaaaaaaaaaabbbbbb"; // <-256bitの共通鍵 | |
byte[] sharedSecret = key.getBytes(); // バイト列に変換 | |
String result = serialize(data, sharedSecret); | |
deserialize(result, sharedSecret); | |
} | |
private static String serialize(String data, byte[] sharedSecret) | |
throws KeyLengthException, JOSEException, ParseException { | |
// Create an HMAC-protected JWS object with some payload | |
JWSObject jwsObject = new JWSObject(new JWSHeader(JWSAlgorithm.HS256), | |
new Payload(data)); | |
// We need a 256-bit key for HS256 which must be pre-shared | |
// byte[] sharedSecret = new byte[32]; | |
// new SecureRandom().nextBytes(sharedSecret); | |
// Apply the HMAC to the JWS object | |
MACSigner signer = new MACSigner(sharedSecret); | |
jwsObject.sign(signer); | |
// Output to URL-safe format | |
String s = jwsObject.serialize(); | |
System.out.println("Result : " + s); | |
return s; | |
} | |
private static void deserialize(String s, byte[] sharedSecret) | |
throws JOSEException, ParseException { | |
JWSObject decodeObject = JWSObject.parse(s); | |
System.out.println("Header : " + decodeObject.getHeader().toString()); | |
System.out.println("Payload: " + decodeObject.getPayload().toString()); | |
System.out.println("Sign : " + decodeObject.getSignature()); | |
JWSVerifier verifier = new MACVerifier(sharedSecret); | |
System.out.println("valid? : " + decodeObject.verify(verifier)); | |
} | |
// 実行結果 | |
// Result : | |
// eyJhbGciOiJIUzI1NiJ9.SGVsbG8sIHdvcmxkIQ.qtL-IPdyPMtVVzgBEsqwjder0hJMWSHnYCAh78uTToc | |
// Header : {"alg":"HS256"} | |
// Payload: Hello, world! | |
// Sign : qtL-IPdyPMtVVzgBEsqwjder0hJMWSHnYCAh78uTToc | |
// valid? : true | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<dependency> | |
<groupId>com.nimbusds</groupId> | |
<artifactId>nimbus-jose-jwt</artifactId> | |
<version>4.23</version> | |
</dependency> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nu.mine.kino; | |
import java.io.IOException; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.security.NoSuchAlgorithmException; | |
import java.text.ParseException; | |
import java.util.Date; | |
import com.nimbusds.jose.JOSEException; | |
import com.nimbusds.jose.JWSVerifier; | |
import com.nimbusds.jose.KeyLengthException; | |
import com.nimbusds.jose.crypto.RSASSAVerifier; | |
import com.nimbusds.jose.jwk.JWK; | |
import com.nimbusds.jose.jwk.JWKSet; | |
import com.nimbusds.jose.jwk.RSAKey; | |
import com.nimbusds.jwt.JWTClaimsSet; | |
import com.nimbusds.jwt.SignedJWT; | |
/** | |
* @author Masatomi KINO | |
* @version $Revision$ | |
*/ | |
public class RSAJWTMain { | |
// https://connect2id.com/products/nimbus-jose-jwt/examples/jws-with-rsa-signature | |
// https://connect2id.com/products/nimbus-jose-jwt/examples/jwk-retrieval | |
public static void main(String[] args) | |
throws KeyLengthException, JOSEException, ParseException, | |
NoSuchAlgorithmException, MalformedURLException, IOException { | |
// Yahoo Connectから得られたID_Token | |
String result = "xxxx.yyyyyyy.zzzzz"; | |
deserialize(result); | |
} | |
private static void deserialize(String s) throws JOSEException, | |
ParseException, MalformedURLException, IOException { | |
// JWTの仕様に基づいて、デコード出来る。 | |
SignedJWT decodeObject = SignedJWT.parse(s); | |
System.out.println("Header : " + decodeObject.getHeader().toString()); | |
System.out.println("Payload: " + decodeObject.getPayload().toString()); | |
System.out.println("Sign : " + decodeObject.getSignature()); | |
JWTClaimsSet set = decodeObject.getJWTClaimsSet(); | |
System.out.println(set.getSubject()); | |
System.out.println(set.getIssuer()); | |
System.out.println(set.getAudience()); | |
System.out.println(set.getClaim("nonce")); | |
System.out.println(new Date().before(set.getExpirationTime())); | |
// Hederから KeyIDを取得して、 | |
String keyID = decodeObject.getHeader().getKeyID(); | |
System.out.println(keyID); | |
// https://developer.yahoo.co.jp/yconnect/v2/hybrid/jwks.html | |
// JWK のエンドポイントから、公開鍵を取得する。 | |
// もしくは Public Keys エンドポイント | |
// https://developer.yahoo.co.jp/yconnect/v2/hybrid/public_keys.html | |
JWKSet publicKeys = JWKSet.load( | |
new URL("https://auth.login.yahoo.co.jp/yconnect/v2/jwks")); | |
// ちなみにGoogleは | |
// http://qiita.com/trysmr/items/e8d4225ff6a603e9e21a によると | |
// https://www.googleapis.com/oauth2/v3/certs | |
// ちなみにAuthleteは | |
// https://[サーバ名]/api/jwks | |
// だがデフォルトだとかえんないっぽい。設定しないとかな。 | |
JWK key = publicKeys.getKeyByKeyId(keyID); | |
RSAKey rsaKey = RSAKey.parse(key.toJSONObject()); | |
JWSVerifier verifier = new RSASSAVerifier(rsaKey); | |
System.out.println("valid? : " + decodeObject.verify(verifier)); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nu.mine.kino; | |
import java.security.KeyPair; | |
import java.security.KeyPairGenerator; | |
import java.security.NoSuchAlgorithmException; | |
import java.security.interfaces.RSAPrivateKey; | |
import java.security.interfaces.RSAPublicKey; | |
import java.text.ParseException; | |
import com.nimbusds.jose.JOSEException; | |
import com.nimbusds.jose.JWSAlgorithm; | |
import com.nimbusds.jose.JWSHeader; | |
import com.nimbusds.jose.JWSObject; | |
import com.nimbusds.jose.JWSSigner; | |
import com.nimbusds.jose.JWSVerifier; | |
import com.nimbusds.jose.KeyLengthException; | |
import com.nimbusds.jose.Payload; | |
import com.nimbusds.jose.crypto.RSASSASigner; | |
import com.nimbusds.jose.crypto.RSASSAVerifier; | |
/** | |
* @author Masatomi KINO | |
* @version $Revision$ | |
*/ | |
public class RSAMain { | |
// https://connect2id.com/products/nimbus-jose-jwt/examples/jws-with-rsa-signature | |
public static void main(String[] args) throws KeyLengthException, | |
JOSEException, ParseException, NoSuchAlgorithmException { | |
String data = "Hello, world!"; | |
KeyPairGenerator keyGenerator = KeyPairGenerator.getInstance("RSA"); | |
keyGenerator.initialize(1024); | |
KeyPair kp = keyGenerator.genKeyPair(); | |
RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic(); | |
RSAPrivateKey privateKey = (RSAPrivateKey) kp.getPrivate(); | |
String result = serialize(data, privateKey); | |
deserialize(result, publicKey); | |
} | |
private static String serialize(String data, RSAPrivateKey privateKey) | |
throws KeyLengthException, JOSEException, ParseException, | |
NoSuchAlgorithmException { | |
JWSObject jwsObject = new JWSObject( | |
new JWSHeader.Builder(JWSAlgorithm.RS256).keyID("123").build(), | |
new Payload(data)); | |
// Create RSA-signer with the private key | |
JWSSigner signer = new RSASSASigner(privateKey); | |
jwsObject.sign(signer); | |
// Output to URL-safe format | |
String s = jwsObject.serialize(); | |
System.out.println("Result : " + s); | |
return s; | |
} | |
private static void deserialize(String s, RSAPublicKey publicKey) | |
throws JOSEException, ParseException { | |
JWSObject decodeObject = JWSObject.parse(s); | |
System.out.println("Header : " + decodeObject.getHeader().toString()); | |
System.out.println("Payload: " + decodeObject.getPayload().toString()); | |
System.out.println("Sign : " + decodeObject.getSignature()); | |
JWSVerifier verifier = new RSASSAVerifier(publicKey); | |
System.out.println("valid? : " + decodeObject.verify(verifier)); | |
} | |
// 実行結果 | |
// Result : | |
// eyJraWQiOiIxMjMiLCJhbGciOiJSUzI1NiJ9. | |
// SGVsbG8sIHdvcmxkIQ. | |
// NK89zHldjv6wv5w5FRkT4lTR-1-i7kJImS8Jngl01tgSCx9N1D0juxdfubvkbJ7Fj4ntls6T25VOoQUH4LbuOW5EBoO9KxV8KPf4pnUigFhhPLANAacZ6wcTavtUEdsnQVsRv_v4FDHSRtZ5pv4KOEXFFLr_vlPtBSKJl7GvHfY | |
// Header : {"kid":"123","alg":"RS256"} | |
// Payload: Hello, world! | |
// Sign : | |
// NK89zHldjv6wv5w5FRkT4lTR-1-i7kJImS8Jngl01tgSCx9N1D0juxdfubvkbJ7Fj4ntls6T25VOoQUH4LbuOW5EBoO9KxV8KPf4pnUigFhhPLANAacZ6wcTavtUEdsnQVsRv_v4FDHSRtZ5pv4KOEXFFLr_vlPtBSKJl7GvHfY | |
// valid? : true | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment