Skip to content

Instantly share code, notes, and snippets.

@masatomix
Last active May 13, 2021 09:12
Show Gist options
  • Save masatomix/d384010156b8c16881fcd0dccd315ef5 to your computer and use it in GitHub Desktop.
Save masatomix/d384010156b8c16881fcd0dccd315ef5 to your computer and use it in GitHub Desktop.
HS256 / RSA256 を用いたサンプル。共通鍵、公開鍵でハッシュした署名をつけるJWSのサンプルと、公開鍵で署名したJWTを検証するサンプルコード。
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
}
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>4.23</version>
</dependency>
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));
}
}
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