Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/origin/master' into release-0.2.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	pom.xml
  • Loading branch information
Mohamed Sameem Ahamed Azeem committed Apr 7, 2020
2 parents a94a573 + 6825a0c commit 4ccb6da
Show file tree
Hide file tree
Showing 48 changed files with 1,063 additions and 300 deletions.
70 changes: 32 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ Originally built during [Rebooting Web-of-Trust](http://www.weboftrust.info/) in

### Information

This is a work-in-progress implementation of the [2018 RSA Signature Suite](https://w3c-dvcg.github.io/lds-rsa2018/) for the Linked Data Signatures specification.
This is a work-in-progress implementation of the following cryptographic suites for [Linked Data Proofs](https://w3c-ccg.github.io/ld-proofs/):

- [Ed25519Signature2018](https://w3c-ccg.github.io/lds-ed25519-2018/)
- [EcdsaSecp256k1Signature2019](https://w3c-dvcg.github.io/lds-ecdsa-secp256k1-2019/)
- [RsaSignature2018](https://w3c-ccg.github.io/lds-rsa2018/)

Highly experimental, incomplete, and not ready for production use! Use at your own risk! Pull requests welcome.

Expand All @@ -19,7 +23,7 @@ Dependency:
<dependency>
<groupId>info.weboftrust</groupId>
<artifactId>ld-signatures-java</artifactId>
<version>0.2-SNAPSHOT</version>
<version>0.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>

Expand All @@ -41,45 +45,35 @@ Example JSON-LD document:

Example code:

LinkedHashMap<String, Object> jsonLdObject = (LinkedHashMap<String, Object>) JsonUtils.fromString(TestUtil.read(JsonLdSignTest.class.getResourceAsStream("sign.test.jsonld")));
URI creator = URI.create("https://example.com/jdoe/keys/1");
String created = "2017-10-24T05:33:31Z";
String domain = "example.com";
String nonce = null;
RsaSignature2018LdSigner signer = new RsaSignature2018LdSigner(creator, created, domain, nonce, TestUtil.testRSAPrivateKey);
LdSignature ldSignature = signer.sign(jsonLdObject);
LinkedHashMap<String, Object> jsonLdSignatureObject = ldSignature.getJsonLdSignatureObject();
byte[] testEd25519PrivateKey = Hex.decodeHex("984b589e121040156838303f107e13150be4a80fc5088ccba0b0bdc9b1d89090de8777a28f8da1a74e7a13090ed974d879bf692d001cddee16e4cc9f84b60580".toCharArray());

LinkedHashMap<String, Object> jsonLdObject = (LinkedHashMap<String, Object>) JsonUtils.fromReader(new FileReader("sign.test.jsonld"));
String verificationMethod = "https://example.com/jdoe/keys/1";
String domain = "example.com";
String nonce = null;

Ed25519Signature2018LdSigner signer = new Ed25519Signature2018LdSigner(testEd25519PrivateKey);
signer.setCreated(new Date());
signer.setProofPurpose(LdSignature.JSONLD_TERM_ASSERTIONMETHOD);
signer.setVerificationMethod(verificationMethod);
signer.setDomain(domain);
signer.setNonce(nonce);
LdSignature ldSignature = signer.sign(jsonLdObject);

LinkedHashMap<String, Object> jsonLdSignatureObject = ldSignature.getJsonLdSignatureObject();

System.out.println(JsonUtils.toPrettyString(jsonLdSignatureObject));

Example Linked Data Signature:

"signature" : {
"type" : "https://w3id.org/security#RsaSignature2018",
"creator" : "https://example.com/jdoe/keys/1",
"created" : "2017-10-24T05:33:31Z",
"domain" : "example.com",
"signatureValue" : "eyJhbGciOiJSUzI1NiIsImI2NCI6ZmFsc2UsImNyaXQiOlsiYjY0Il19..d8wWxUJTpxAbYHLgFfaYYJJHdWido6wDMBeUhPL7e0m4vuj7xUePbnorf-YqlGZwaGI0zVI_-qJmGbqSB0bm8x20Z9nvawZS8lTk_4uLIPwSPeH8Cyu5bdUP1OIImBhm0gpUmAZfnDVhCgC81lJOaa4tqCjSr940cRUQ9agYjcOyhUBdBOwQgjd8jgkI7vmXqs2m7TmOVY7aAr-6X3AhJqX_a-iD5sdBsoTNulfTyPjEZcFXMvs6gx2078ftwYiUNQzV4qKwkhmUSAINWomKe_fUh4BpdPbsZax7iKYG1hSWRkmrd9R8FllotKQ_nMWZv0urn02F83US62F6ORRT0w"
}

Example Usage of `PrivateKeySignerFactory`:

// keytype must be one of the following
String keyType = "RSA";
String keyType = "P-256K";
String keyType = "Ed25519";
// algorithm must be one of the following
String algorithm = "RS256";
String algorithm = "ES256K";
String algorithm = "EdDSA";
// privateKey must be one of the following
Object privateKey = rsaPrivateKey; // implementation of java.security.interfaces.RSAPrivateKey
Object privateKey = ecPrivateKey; // implementation of org.bitcoinj.core.ECKey
Object privateKey = privateKeyAsByteArray; // an Ed25519 key as a byte[]
PrivateKeySigner<?> privateKeySigner = PrivateKeySignerFactory.privateKeySignerForKey(keyType, algorithm, privateKey);
signature = privateKeySigner.sign(body, algorithm);
{
"type" : "Ed25519Signature2018",
"created" : "2020-04-06T11:31:27Z",
"domain" : "example.com",
"proofPurpose" : "assertionMethod",
"verificationMethod" : "https://example.com/jdoe/keys/1",
"jws" : "eyJjcml0IjpbImI2NCJdLCJiNjQiOmZhbHNlLCJhbGciOiJFZERTQSJ9..0DsZDTVnGwMypMH33__VCOYXoKvEumBlty-vuqib9YtkCms9bVSap4PWxzFg26B_U04hWoV6qcZnfaBXMSFZAg"
}

### About

Expand Down
40 changes: 34 additions & 6 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.7</source>
<target>1.7</target>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
Expand Down Expand Up @@ -108,12 +108,40 @@

</build>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.0.1-jre</version>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.10</version>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.2.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>3.2.4</version>
<scope>test</scope>
</dependency>
<dependency>
Expand All @@ -125,7 +153,7 @@
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>8.2.1</version>
<version>8.11</version>
<scope>compile</scope>
</dependency>
<dependency>
Expand Down
90 changes: 81 additions & 9 deletions src/main/java/info/weboftrust/ldsignatures/LdSignature.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
package info.weboftrust.ldsignatures;

import java.net.URI;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.TimeZone;

import com.github.jsonldjava.core.JsonLdConsts;

public class LdSignature {

public static final String JSONLD_CONTEXT_SECURITY = "https://w3id.org/security/v1";
public static final String JSONLD_CONTEXT_SECURITY_V1 = "https://w3id.org/security/v1";
public static final String JSONLD_CONTEXT_SECURITY_V2 = "https://w3id.org/security/v2";

public static final URI URI_SIGNATURE = URI.create("https://w3id.org/security#signature");

Expand All @@ -26,10 +31,27 @@ public class LdSignature {
public static final String JSONLD_TERM_CREATED = "created";
public static final String JSONLD_TERM_DOMAIN = "domain";
public static final String JSONLD_TERM_NONCE = "nonce";
public static final String JSONLD_TERM_PROOFPURPOSE = "proofPurpose";
public static final String JSONLD_TERM_VERIFICATIONMETHOD = "verificationMethod";
public static final String JSONLD_TERM_SIGNATUREVALUE = "signatureValue";
public static final String JSONLD_TERM_JWS = "jws";

public static final String JSONLD_TERM_ASSERTIONMETHOD = "assertionMethod";

public static final SimpleDateFormat DATE_FORMAT;
public static final SimpleDateFormat DATE_FORMAT_MILLIS;

private final LinkedHashMap<String, Object> jsonLdSignatureObject;

static {

DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));

DATE_FORMAT_MILLIS = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'");
DATE_FORMAT_MILLIS.setTimeZone(TimeZone.getTimeZone("UTC"));
}

private LdSignature(LinkedHashMap<String, Object> jsonLdSignatureObject) {

this.jsonLdSignatureObject = jsonLdSignatureObject;
Expand Down Expand Up @@ -66,19 +88,29 @@ public static void addSecurityContextToJsonLdObject(LinkedHashMap<String, Object
jsonLdObject.put(JsonLdConsts.CONTEXT, contexts);
}

if (! contexts.contains(JSONLD_CONTEXT_SECURITY)) {
if (! contexts.contains(JSONLD_CONTEXT_SECURITY_V2)) {

contexts.add(JSONLD_CONTEXT_SECURITY);
contexts.add(JSONLD_CONTEXT_SECURITY_V2);
}
}

public static void addToJsonLdObject(LinkedHashMap<String, Object> jsonLdObject, LinkedHashMap<String, Object> jsonLdSignatureObject) {
public static void addToJsonLdObject(LinkedHashMap<String, Object> jsonLdObject, LinkedHashMap<String, Object> jsonLdSignatureObject, boolean addSecurityContext) {

addSecurityContextToJsonLdObject(jsonLdObject);
if (addSecurityContext) addSecurityContextToJsonLdObject(jsonLdObject);

jsonLdObject.put(JSONLD_TERM_PROOF, jsonLdSignatureObject);
}

public static void addToJsonLdObject(LinkedHashMap<String, Object> jsonLdObject, LinkedHashMap<String, Object> jsonLdSignatureObject) {

addToJsonLdObject(jsonLdObject, jsonLdSignatureObject, false);
}

public void addToJsonLdObject(LinkedHashMap<String, Object> jsonLdObject, boolean addSecurityContext) {

addToJsonLdObject(jsonLdObject, this.getJsonLdSignatureObject(), addSecurityContext);
}

public void addToJsonLdObject(LinkedHashMap<String, Object> jsonLdObject) {

addToJsonLdObject(jsonLdObject, this.getJsonLdSignatureObject());
Expand All @@ -89,6 +121,12 @@ public static void removeFromJsonLdObject(LinkedHashMap<String, Object> jsonLdOb
jsonLdObject.remove(JSONLD_TERM_PROOF);
}

public static void removeLdSignatureValues(LinkedHashMap<String, Object> jsonLdObject) {

jsonLdObject.remove(JSONLD_TERM_SIGNATUREVALUE);
jsonLdObject.remove(JSONLD_TERM_JWS);
}

@SuppressWarnings("unchecked")
public static LdSignature getFromJsonLdObject(LinkedHashMap<String, Object> jsonLdObject) {

Expand Down Expand Up @@ -117,12 +155,22 @@ public void setCreator(URI creator) {
this.jsonLdSignatureObject.put(JSONLD_TERM_CREATOR, creator);
}

public String getCreated() {
return (String) this.jsonLdSignatureObject.get(JSONLD_TERM_CREATED);
public Date getCreated() {
String createdString = (String) this.jsonLdSignatureObject.get(JSONLD_TERM_CREATED);
if (createdString == null) return null;
try {
return DATE_FORMAT.parse(createdString);
} catch (ParseException ex) {
try {
return DATE_FORMAT_MILLIS.parse(createdString);
} catch (ParseException ex2) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
}

public void setCreated(String created) {
this.jsonLdSignatureObject.put(JSONLD_TERM_CREATED, created);
public void setCreated(Date created) {
this.jsonLdSignatureObject.put(JSONLD_TERM_CREATED, DATE_FORMAT.format(created));
}

public String getDomain() {
Expand All @@ -141,6 +189,22 @@ public void setNonce(String nonce) {
this.jsonLdSignatureObject.put(JSONLD_TERM_NONCE, nonce);
}

public String getProofPurpose() {
return (String) this.jsonLdSignatureObject.get(JSONLD_TERM_PROOFPURPOSE);
}

public void setProofPurpose(String proofPurpose) {
this.jsonLdSignatureObject.put(JSONLD_TERM_PROOFPURPOSE, proofPurpose);
}

public String getVerificationMethod() {
return (String) this.jsonLdSignatureObject.get(JSONLD_TERM_VERIFICATIONMETHOD);
}

public void setVerificationMethod(String verificationMethod) {
this.jsonLdSignatureObject.put(JSONLD_TERM_VERIFICATIONMETHOD, verificationMethod);
}

public String getSignatureValue() {
return (String) this.jsonLdSignatureObject.get(JSONLD_TERM_SIGNATUREVALUE);
}
Expand All @@ -149,6 +213,14 @@ public void setSignatureValue(String signatureValue) {
this.jsonLdSignatureObject.put(JSONLD_TERM_SIGNATUREVALUE, signatureValue);
}

public String getJws() {
return (String) this.jsonLdSignatureObject.get(JSONLD_TERM_JWS);
}

public void setJws(String jws) {
this.jsonLdSignatureObject.put(JSONLD_TERM_JWS, jws);
}

@Override
public int hashCode() {
final int prime = 31;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import com.nimbusds.jose.jwk.KeyType;

import info.weboftrust.ldsignatures.crypto.impl.Ed25519_EdDSA_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.P256K_ES256K_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.secp256k1_ES256K_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.RSA_PS256_PrivateKeySigner;
import info.weboftrust.ldsignatures.crypto.impl.RSA_RS256_PrivateKeySigner;

Expand All @@ -26,9 +26,9 @@ public static PrivateKeySigner<?> privateKeySignerForKey(String keyType, String

if (JWSAlgorithm.RS256.getName().equals(algorithm)) return new RSA_RS256_PrivateKeySigner((RSAPrivateKey) privateKey);
if (JWSAlgorithm.PS256.getName().equals(algorithm)) return new RSA_PS256_PrivateKeySigner((RSAPrivateKey) privateKey);
} else if (Curve.P_256K.getName().equals(keyType)) {
} else if (Curve.SECP256K1.getName().equals(keyType)) {

if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new P256K_ES256K_PrivateKeySigner((ECKey) privateKey);
if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new secp256k1_ES256K_PrivateKeySigner((ECKey) privateKey);
} else if (Curve.Ed25519.getName().equals(keyType)) {

if (JWSAlgorithm.EdDSA.getName().equals(algorithm)) return new Ed25519_EdDSA_PrivateKeySigner((byte[]) privateKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import com.nimbusds.jose.jwk.KeyType;

import info.weboftrust.ldsignatures.crypto.impl.Ed25519_EdDSA_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.P256K_ES256K_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.secp256k1_ES256K_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.RSA_PS256_PublicKeyVerifier;
import info.weboftrust.ldsignatures.crypto.impl.RSA_RS256_PublicKeyVerifier;

Expand All @@ -26,9 +26,9 @@ public static PublicKeyVerifier<?> publicKeyVerifierForKey(String keyType, Strin

if (JWSAlgorithm.RS256.getName().equals(algorithm)) return new RSA_RS256_PublicKeyVerifier((RSAPublicKey) publicKey);
if (JWSAlgorithm.PS256.getName().equals(algorithm)) return new RSA_PS256_PublicKeyVerifier((RSAPublicKey) publicKey);
} else if (Curve.P_256K.getName().equals(keyType)) {
} else if (Curve.SECP256K1.getName().equals(keyType)) {

if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new P256K_ES256K_PublicKeyVerifier((ECKey) publicKey);
if (JWSAlgorithm.ES256K.getName().equals(algorithm)) return new secp256k1_ES256K_PublicKeyVerifier((ECKey) publicKey);
} else if (Curve.Ed25519.getName().equals(keyType)) {

if (JWSAlgorithm.EdDSA.getName().equals(algorithm)) return new Ed25519_EdDSA_PublicKeyVerifier((byte[]) publicKey);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@

import info.weboftrust.ldsignatures.crypto.PrivateKeySigner;

public class P256K_ES256K_PrivateKeySigner extends PrivateKeySigner<ECKey> {
public class secp256k1_ES256K_PrivateKeySigner extends PrivateKeySigner<ECKey> {

public P256K_ES256K_PrivateKeySigner(ECKey privateKey) {
public secp256k1_ES256K_PrivateKeySigner(ECKey privateKey) {

super(privateKey, "ES256K");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@

import info.weboftrust.ldsignatures.crypto.PublicKeyVerifier;

public class P256K_ES256K_PublicKeyVerifier extends PublicKeyVerifier<ECKey> {
public class secp256k1_ES256K_PublicKeyVerifier extends PublicKeyVerifier<ECKey> {

public P256K_ES256K_PublicKeyVerifier(ECKey publicKey) {
public secp256k1_ES256K_PublicKeyVerifier(ECKey publicKey) {

super(publicKey, "ES256K");
}
Expand Down
Loading

0 comments on commit 4ccb6da

Please sign in to comment.