Added spring simple web app for testing, encryption and decryption classes for rsa and hmac, still WIP
parent
1f68c835c0
commit
33cc3fa899
|
@ -726,7 +726,4 @@ public class AbstractOIDCAuthenticationFilter extends
|
|||
Map<OIDCServerConfiguration, JwtSigningAndValidationService> validationServices) {
|
||||
this.validationServices = validationServices;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,207 @@
|
|||
package org.mitre.jwe.model;
|
||||
/*******************************************************************************
|
||||
* Copyright 2012 The MITRE Corporation
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
******************************************************************************/
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
/**
|
||||
* Generic container for JSON-based claims. Backed with a {@link Map} that preserves
|
||||
* insertion order. Several convenience methods for getting and setting claims in different
|
||||
* formats.
|
||||
* @author jricher
|
||||
*
|
||||
*/
|
||||
public class ClaimSet {
|
||||
|
||||
// the LinkedHashMap preserves insertion order
|
||||
private Map<String, Object> claims = new LinkedHashMap<String, Object>();
|
||||
|
||||
public ClaimSet() {
|
||||
|
||||
}
|
||||
|
||||
public ClaimSet(JsonObject json) {
|
||||
loadFromJsonObject(json);
|
||||
}
|
||||
|
||||
public ClaimSet(String b64) {
|
||||
loadFromBase64JsonObjectString(b64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an extension claim
|
||||
*/
|
||||
public Object getClaim(String key) {
|
||||
return claims.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a claim as a string
|
||||
*/
|
||||
public String getClaimAsString(String key) {
|
||||
Object v = claims.get(key);
|
||||
if (v != null) {
|
||||
return v.toString();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a claim as a Date
|
||||
*/
|
||||
public Date getClaimAsDate(String key) {
|
||||
Object v = claims.get(key);
|
||||
if (v != null) {
|
||||
if (v instanceof Date) {
|
||||
return (Date) v;
|
||||
} else if (v instanceof Long) {
|
||||
return new Date((Long) v);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an extension claim
|
||||
*/
|
||||
public void setClaim(String key, Object value) {
|
||||
claims.put(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a primitive claim
|
||||
*/
|
||||
public void setClaim(String key, JsonPrimitive prim) {
|
||||
if (prim == null) {
|
||||
// in case we get here with a primitive null
|
||||
claims.put(key, prim);
|
||||
} else if (prim.isBoolean()) {
|
||||
claims.put(key, prim.getAsBoolean());
|
||||
} else if (prim.isNumber()) {
|
||||
claims.put(key, prim.getAsNumber());
|
||||
} else if (prim.isString()) {
|
||||
claims.put(key, prim.getAsString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an extension claim
|
||||
*/
|
||||
public Object removeClaim(String key) {
|
||||
return claims.remove(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear all claims from this ClaimSet
|
||||
* @see java.util.Map#clear()
|
||||
*/
|
||||
public void clear() {
|
||||
claims.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a copy of this claim set as a JsonObject. The JsonObject is not
|
||||
* backed by a live copy of this ClaimSet.
|
||||
* @return a copy of the data in this header in a JsonObject
|
||||
*/
|
||||
public JsonObject getAsJsonObject() {
|
||||
JsonObject o = new JsonObject();
|
||||
|
||||
|
||||
/*
|
||||
* We step through the claims object and serialize the internal values as
|
||||
* appropriate to JsonElements.
|
||||
*/
|
||||
|
||||
if (this.claims != null) {
|
||||
for (Map.Entry<String, Object> claim : this.claims.entrySet()) {
|
||||
if (claim.getValue() instanceof JsonElement) {
|
||||
// raw JSON elements get passed through directly
|
||||
o.add(claim.getKey(), (JsonElement)claim.getValue());
|
||||
} else if (claim.getValue() instanceof String) {
|
||||
o.addProperty(claim.getKey(), (String)claim.getValue());
|
||||
} else if (claim.getValue() instanceof Number) {
|
||||
o.addProperty(claim.getKey(), (Number)claim.getValue());
|
||||
} else if (claim.getValue() instanceof Boolean) {
|
||||
o.addProperty(claim.getKey(), (Boolean)claim.getValue());
|
||||
} else if (claim.getValue() instanceof Character) {
|
||||
o.addProperty(claim.getKey(), (Character)claim.getValue());
|
||||
} else if (claim.getValue() instanceof Date) {
|
||||
// dates get serialized out as integers
|
||||
o.addProperty(claim.getKey(), ((Date)claim.getValue()).getTime() / 1000L);
|
||||
} else if (claim.getValue() != null) {
|
||||
// try to put it in as a string
|
||||
o.addProperty(claim.getKey(), claim.getValue().toString());
|
||||
} else {
|
||||
// otherwise add in as a null
|
||||
o.add(claim.getKey(), null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load new claims from the given json object. Will replace any existing claims, but does not clear claim set.
|
||||
* @param json
|
||||
*/
|
||||
public void loadFromJsonObject(JsonObject json) {
|
||||
for (Entry<String, JsonElement> element : json.entrySet()) {
|
||||
if (element.getValue().isJsonNull()) {
|
||||
// nulls get stored as java nulls
|
||||
setClaim(element.getKey(), null);
|
||||
} else if (element.getValue().isJsonPrimitive()){
|
||||
// we handle all primitives in here
|
||||
JsonPrimitive prim = element.getValue().getAsJsonPrimitive();
|
||||
setClaim(element.getKey(), prim);
|
||||
} else {
|
||||
setClaim(element.getKey(), element.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a new claims set from a Base64 encoded JSON Object string
|
||||
*/
|
||||
public void loadFromBase64JsonObjectString(String b64) {
|
||||
byte[] b64decoded = Base64.decodeBase64(b64);
|
||||
|
||||
JsonParser parser = new JsonParser();
|
||||
JsonObject json = parser.parse(new InputStreamReader(new ByteArrayInputStream(b64decoded))).getAsJsonObject();
|
||||
|
||||
loadFromJsonObject(json);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package org.mitre.jwe.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class Jwe {
|
||||
|
||||
private JweHeader header;
|
||||
|
||||
private String encryptedKey;
|
||||
|
||||
private String ciphertext;
|
||||
|
||||
private String integrityValue;
|
||||
|
||||
public Jwe() {
|
||||
this.header = new JweHeader();
|
||||
this.encryptedKey = null;
|
||||
this.ciphertext = null;
|
||||
this.integrityValue = null;
|
||||
}
|
||||
|
||||
public Jwe(JweHeader header, String encryptedKey, String ciphertext, String integrityValue) {
|
||||
this.header = header;
|
||||
this.encryptedKey = encryptedKey;
|
||||
this.ciphertext = ciphertext;
|
||||
this.integrityValue = integrityValue;
|
||||
}
|
||||
|
||||
public JweHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(JweHeader header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public String getEncryptedKey() {
|
||||
return encryptedKey;
|
||||
}
|
||||
|
||||
public void setEncryptedKey(String encryptedKey) {
|
||||
this.encryptedKey = encryptedKey;
|
||||
}
|
||||
|
||||
public String getCiphertext() {
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
public void setCiphertext(String ciphertext) {
|
||||
this.ciphertext = ciphertext;
|
||||
}
|
||||
|
||||
public String getIntegrityValue() {
|
||||
return integrityValue;
|
||||
}
|
||||
|
||||
public void setIntegrityValue(String integrityValue) {
|
||||
this.integrityValue = integrityValue;
|
||||
}
|
||||
|
||||
public static Jwe parse(String s) {
|
||||
|
||||
// null string is a null token
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// split on the dots
|
||||
List<String> parts = Lists.newArrayList(Splitter.on(".").split(s));
|
||||
|
||||
if (parts.size() != 3) {
|
||||
throw new IllegalArgumentException("Invalid JWE format.");
|
||||
}
|
||||
|
||||
String h64 = parts.get(0);
|
||||
String e64 = parts.get(1);
|
||||
String c64 = parts.get(2);
|
||||
String i64 = parts.get(3);
|
||||
|
||||
Jwe jwe = new Jwe(new JweHeader(h64), e64, c64, i64);
|
||||
|
||||
return jwe;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.mitre.jwe.model;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.mitre.jwt.model.JwtHeader;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
public class JweHeader extends JwtHeader{
|
||||
|
||||
public static final String INTEGRITY = "int";
|
||||
public static final String INITIALIZATION_VECTOR = "iv";
|
||||
public static final String EPHEMERAL_PUBLIC_KEY = "epk";
|
||||
public static final String COMPRESSION_ALGORITHM = "zip";
|
||||
public static final String JSON_SET_URL = "jku";
|
||||
public static final String JSON_WEB_KEY = "jwk";
|
||||
public static final String X509_URL = "x5u";
|
||||
public static final String X509_CERTIFICATE_THUMBPRINT = "x5t";
|
||||
public static final String X509_CERTIFICATE_CHAIN = "x5c";
|
||||
public static final String KEY_ID = "kid";
|
||||
|
||||
public JweHeader(){
|
||||
super();
|
||||
}
|
||||
|
||||
public JweHeader(JsonObject object){
|
||||
super(object);
|
||||
}
|
||||
|
||||
public JweHeader(String b64) {
|
||||
super(b64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load all claims from the given json object into this object
|
||||
*/
|
||||
@Override
|
||||
public void loadFromJsonObject(JsonObject json) {
|
||||
|
||||
JsonObject pass = new JsonObject();
|
||||
|
||||
for (Entry<String, JsonElement> element : json.entrySet()) {
|
||||
if (element.getValue().isJsonNull()) {
|
||||
pass.add(element.getKey(), element.getValue());
|
||||
} else if (element.getKey().equals(INTEGRITY)) {
|
||||
this.setIntegrity(json.get(INTEGRITY).getAsString());
|
||||
} else if (element.getKey().equals(INITIALIZATION_VECTOR)) {
|
||||
this.setIv(json.get(INITIALIZATION_VECTOR).getAsString());
|
||||
} else if (element.getKey().equals(EPHEMERAL_PUBLIC_KEY)) {
|
||||
this.setEphemeralPublicKey(json.get(EPHEMERAL_PUBLIC_KEY).getAsString());
|
||||
} else if (element.getKey().equals(COMPRESSION_ALGORITHM)) {
|
||||
this.setCompressionAlgorithm(json.get(COMPRESSION_ALGORITHM).getAsString());
|
||||
} else if (element.getKey().equals(JSON_SET_URL)) {
|
||||
this.setJku(json.get(JSON_SET_URL).getAsString());
|
||||
} else if (element.getKey().equals(JSON_WEB_KEY)) {
|
||||
this.setJsonWebKey(json.get(JSON_WEB_KEY).getAsString());
|
||||
} else if (element.getKey().equals(X509_URL)) {
|
||||
this.setX509Url(json.get(X509_URL).getAsString());
|
||||
} else if (element.getKey().equals(X509_CERTIFICATE_THUMBPRINT)) {
|
||||
this.setX509CertThumbprint(json.get(X509_CERTIFICATE_THUMBPRINT).getAsString());
|
||||
} else if (element.getKey().equals(X509_CERTIFICATE_CHAIN)) {
|
||||
this.setX509CertChain(json.get(X509_CERTIFICATE_CHAIN).getAsString());
|
||||
} else if (element.getKey().equals(KEY_ID)) {
|
||||
this.setKeyId(json.get(KEY_ID).getAsString());
|
||||
} else {
|
||||
pass.add(element.getKey(), element.getValue());
|
||||
}
|
||||
}
|
||||
super.loadFromJsonObject(pass);
|
||||
}
|
||||
|
||||
public void setIv(String iv) {
|
||||
setClaim(INITIALIZATION_VECTOR, iv);
|
||||
}
|
||||
|
||||
public void setJku(String jku) {
|
||||
setClaim(JSON_SET_URL, jku);
|
||||
}
|
||||
|
||||
public void setIntegrity(String integrity) {
|
||||
setClaim(INTEGRITY, integrity);
|
||||
}
|
||||
|
||||
public void setEphemeralPublicKey(String epk) {
|
||||
setClaim(EPHEMERAL_PUBLIC_KEY, epk);
|
||||
}
|
||||
|
||||
public void setCompressionAlgorithm(String zip) {
|
||||
setClaim(COMPRESSION_ALGORITHM, zip);
|
||||
}
|
||||
|
||||
public void setJsonWebKey(String jwk) {
|
||||
setClaim(JSON_WEB_KEY, jwk);
|
||||
}
|
||||
|
||||
public void setX509Url(String x5u) {
|
||||
setClaim(X509_URL, x5u);
|
||||
}
|
||||
|
||||
public void setX509CertThumbprint(String x5t) {
|
||||
setClaim(X509_CERTIFICATE_THUMBPRINT, x5t);
|
||||
}
|
||||
|
||||
public void setX509CertChain(String x5c) {
|
||||
setClaim(X509_CERTIFICATE_CHAIN, x5c);
|
||||
}
|
||||
|
||||
public void setKeyId(String kid) {
|
||||
setClaim(KEY_ID, kid);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.mitre.jwt.encryption;
|
||||
|
||||
public class IntegrityProtection {
|
||||
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package org.mitre.jwt.encryption;
|
||||
|
||||
import org.mitre.jwt.model.Jwt;
|
||||
|
||||
public class JwtDecrypter {
|
||||
|
||||
public JwtDecrypter(Jwt jwt) {
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package org.mitre.jwt.encryption;
|
||||
|
||||
import java.security.Key;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
|
||||
import org.mitre.jwt.encryption.impl.HmacJwtEncrypter;
|
||||
import org.mitre.jwt.encryption.impl.RsaJwtEncrypter;
|
||||
import org.mitre.jwt.model.EncryptedJwt;
|
||||
import org.mitre.jwt.model.Jwt;
|
||||
import org.mitre.jwt.model.JwtClaims;
|
||||
import org.mitre.jwt.model.JwtHeader;
|
||||
|
||||
public class JwtEncrypter {
|
||||
|
||||
private Jwt jwt;
|
||||
|
||||
private JwtHeader header;
|
||||
|
||||
private JwtClaims claims;
|
||||
|
||||
private String signature;
|
||||
|
||||
private Key encryptedKey;
|
||||
|
||||
public JwtEncrypter(Jwt jwt) {
|
||||
setJwt(jwt);
|
||||
header = jwt.getHeader();
|
||||
claims = jwt.getClaims();
|
||||
signature = jwt.getSignature();
|
||||
}
|
||||
|
||||
public Jwt getJwt() {
|
||||
return jwt;
|
||||
}
|
||||
|
||||
public void setJwt(Jwt jwt) {
|
||||
this.jwt = jwt;
|
||||
}
|
||||
|
||||
public Key getEncryptecKey() {
|
||||
return encryptedKey;
|
||||
}
|
||||
|
||||
public void setEncryptedKey(Key encryptedKey) {
|
||||
this.encryptedKey = encryptedKey;
|
||||
}
|
||||
|
||||
public JwtHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(JwtHeader header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public JwtClaims getClaims() {
|
||||
return claims;
|
||||
}
|
||||
|
||||
public void setClaims(JwtClaims claims) {
|
||||
this.claims = claims;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public Key getEncryptedKey(Jwt jwt){
|
||||
String alg = jwt.getHeader().getAlgorithm();
|
||||
RSAPublicKey pubKey = null;
|
||||
RSAPrivateKey privateKey = null;
|
||||
String passphrase = null;
|
||||
|
||||
if(alg.equals("RS256") || alg.equals("RS384") || alg.equals("RS512")) {
|
||||
RsaJwtEncrypter rsaEncrypter = new RsaJwtEncrypter(alg, pubKey, privateKey);
|
||||
encryptedKey = rsaEncrypter.createEncryptedKey();
|
||||
} else if (alg.equals("HS256") || alg.equals("HS384") || alg.equals("HS512")){
|
||||
HmacJwtEncrypter hmacEncrypter = new HmacJwtEncrypter(alg, passphrase.getBytes());
|
||||
encryptedKey = hmacEncrypter.createEncryptedKey();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Not a valid signing method");
|
||||
}
|
||||
|
||||
return encryptedKey;
|
||||
|
||||
}
|
||||
|
||||
public EncryptedJwt encryptJwt(Jwt jwt) {
|
||||
|
||||
//EncryptedJwt jwe = new EncryptedJwt(header, encryptedKey, claims, signature);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package org.mitre.jwt.encryption.impl;
|
||||
|
||||
public class HmacJwtDecrypter {
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package org.mitre.jwt.encryption.impl;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class HmacJwtEncrypter {
|
||||
|
||||
private byte[] passphrase;
|
||||
private String algorithm;
|
||||
private byte[] wrappedKey;
|
||||
private PrivateKey privateKey;
|
||||
private PublicKey publicKey;
|
||||
|
||||
public HmacJwtEncrypter(String algorithm, byte[] passphraseAsBytes){
|
||||
setPassphrase(passphraseAsBytes);
|
||||
}
|
||||
|
||||
public byte[] getPassphrase() {
|
||||
return passphrase;
|
||||
}
|
||||
|
||||
public void setPassphrase(byte[] passphrase) {
|
||||
this.passphrase = passphrase;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public byte[] getWrappedKey() {
|
||||
return wrappedKey;
|
||||
}
|
||||
|
||||
public void setWrappedKey(byte[] wrappedKey) {
|
||||
this.wrappedKey = wrappedKey;
|
||||
}
|
||||
|
||||
public Key createEncryptedKey() {
|
||||
try {
|
||||
Cipher cipher = Cipher.getInstance(algorithm);
|
||||
|
||||
SecretKeySpec keySpec = new SecretKeySpec(passphrase, algorithm);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
privateKey = keyFactory.generatePrivate(keySpec);
|
||||
publicKey = keyFactory.generatePublic(keySpec);
|
||||
|
||||
cipher.init(Cipher.WRAP_MODE, publicKey);
|
||||
byte[] wrappedKey = cipher.wrap(privateKey);
|
||||
|
||||
SecretKeySpec wrappedKeySpec = new SecretKeySpec(wrappedKey, algorithm);
|
||||
privateKey = keyFactory.generatePrivate(wrappedKeySpec);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeySpecException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.mitre.jwt.encryption.impl;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
|
||||
public class RsaJwtDecrypter {
|
||||
|
||||
PublicKey publicKey;
|
||||
byte[] wrappedKey;
|
||||
String algorithm;
|
||||
|
||||
public RsaJwtDecrypter(String algorithm, PublicKey publicKey, byte[] wrappedKey){
|
||||
setPublicKey(publicKey);
|
||||
setWrappedKey(wrappedKey);
|
||||
setAlgorithm(algorithm);
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(PublicKey publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
public byte[] getWrappedKey() {
|
||||
return wrappedKey;
|
||||
}
|
||||
|
||||
public void setWrappedKey(byte[] wrappedKey) {
|
||||
this.wrappedKey = wrappedKey;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public Key keyDecrypter() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException {
|
||||
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.UNWRAP_MODE, publicKey);
|
||||
Key unwrappedKey = cipher.unwrap(wrappedKey, algorithm, Cipher.PRIVATE_KEY);
|
||||
|
||||
return unwrappedKey;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package org.mitre.jwt.encryption.impl;
|
||||
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivateKey;
|
||||
import java.security.PublicKey;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
public class RsaJwtEncrypter {
|
||||
|
||||
private PublicKey publicKey;
|
||||
private PrivateKey privateKey;
|
||||
private String algorithm;
|
||||
|
||||
public RsaJwtEncrypter(String algorithm, RSAPublicKey pubKey, RSAPrivateKey privateKey){
|
||||
setAlgorithm(algorithm);
|
||||
setPublicKey(pubKey);
|
||||
setPrivateKey(privateKey);
|
||||
}
|
||||
|
||||
public PublicKey getPublicKey() {
|
||||
return publicKey;
|
||||
}
|
||||
|
||||
public void setPublicKey(PublicKey pubKey) {
|
||||
this.publicKey = pubKey;
|
||||
}
|
||||
|
||||
public PrivateKey getPrivateKey() {
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
public void setPrivateKey(PrivateKey privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
public String getAlgorithm() {
|
||||
return algorithm;
|
||||
}
|
||||
|
||||
public void setAlgorithm(String algorithm) {
|
||||
this.algorithm = algorithm;
|
||||
}
|
||||
|
||||
public Key createEncryptedKey() {
|
||||
Cipher cipher;
|
||||
try {
|
||||
cipher = Cipher.getInstance(algorithm);
|
||||
cipher.init(Cipher.WRAP_MODE, publicKey);
|
||||
byte[] wrappedKey = cipher.wrap(privateKey);
|
||||
|
||||
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
|
||||
SecretKeySpec keySpec = new SecretKeySpec(wrappedKey, algorithm);
|
||||
privateKey = keyFactory.generatePrivate(keySpec);
|
||||
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchPaddingException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeyException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IllegalBlockSizeException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InvalidKeySpecException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return privateKey;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package org.mitre.jwt.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mitre.jwt.model.JwtClaims;
|
||||
import org.mitre.jwt.model.JwtHeader;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
public class EncryptedJwt {
|
||||
|
||||
JwtHeader header;
|
||||
|
||||
String encryptedKey;
|
||||
|
||||
JwtClaims claims;
|
||||
|
||||
String signature;
|
||||
|
||||
public EncryptedJwt() {
|
||||
this.header = new JwtHeader();
|
||||
this.encryptedKey = null;
|
||||
this.claims = new JwtClaims();
|
||||
this.signature = null;
|
||||
}
|
||||
|
||||
public EncryptedJwt (JwtHeader header, String encryptedKey, JwtClaims claims, String signature){
|
||||
setHeader(header);
|
||||
setEncryptedKey(encryptedKey);
|
||||
setClaims(claims);
|
||||
setSignature(signature);
|
||||
}
|
||||
|
||||
public String toString(EncryptedJwt jwe) {
|
||||
return getHeader() + "." + getEncryptedKey() + "." + getClaims() + "." + getSignature();
|
||||
}
|
||||
|
||||
public JwtHeader getHeader() {
|
||||
return header;
|
||||
}
|
||||
|
||||
public void setHeader(JwtHeader header) {
|
||||
this.header = header;
|
||||
}
|
||||
|
||||
public String getEncryptedKey() {
|
||||
return encryptedKey;
|
||||
}
|
||||
|
||||
public void setEncryptedKey(String encryptedKey) {
|
||||
this.encryptedKey = encryptedKey;
|
||||
}
|
||||
|
||||
public JwtClaims getClaims() {
|
||||
return claims;
|
||||
}
|
||||
|
||||
public void setClaims(JwtClaims claims) {
|
||||
this.claims = claims;
|
||||
}
|
||||
|
||||
public String getSignature() {
|
||||
return signature;
|
||||
}
|
||||
|
||||
public void setSignature(String signature) {
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public static EncryptedJwt parse(String s) {
|
||||
|
||||
// null string is a null token
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// split on the dots
|
||||
List<String> parts = Lists.newArrayList(Splitter.on(".").split(s));
|
||||
|
||||
if (parts.size() != 4) {
|
||||
throw new IllegalArgumentException("Invalid Encrypted JWT format.");
|
||||
}
|
||||
|
||||
String h64 = parts.get(0);
|
||||
String e64 = parts.get(1);
|
||||
String c64 = parts.get(2);
|
||||
String i64 = parts.get(3);
|
||||
|
||||
EncryptedJwt jwt = new EncryptedJwt(new JwtHeader(h64), e64, new JwtClaims(c64), i64);
|
||||
|
||||
return jwt;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -33,6 +33,7 @@ public class JwtClaims extends ClaimSet {
|
|||
public static final String EXPIRATION = "exp";
|
||||
public static final String NONCE = "nonce";
|
||||
|
||||
|
||||
/**
|
||||
* ISO8601 / RFC3339 Date Format
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,6 @@ import java.math.BigInteger;
|
|||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.CertificateFactory;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
|
Loading…
Reference in New Issue