Skip to content

Commit

Permalink
Merge pull request #235 from TokenScript/liscon-changes
Browse files Browse the repository at this point in the history
Change of the usage value for Liscon
  • Loading branch information
jot2re authored Feb 23, 2022
2 parents 23cd326 + ad5d864 commit 110b98a
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 60 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ task testJavaScript(type: NodeTask) {

group = "org.tokenscript"
archivesBaseName = "attestation"
version = "0.3.8"
version = "0.3.13"

/** See https://docs.gradle.org/current/userguide/publishing_maven.html for details
* For actually updating the Maven repo update the version reference in README.md,
Expand Down
2 changes: 1 addition & 1 deletion devcon.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,4 @@ The command will print `Ticket is VALID and was issued to email [email protected]` if

For example:

java -cp attestation-0.3.8-all.jar org.devcon.ticket.Validator pub.pem MIGYMA8MATYCBwCMryzpzeQCAQAEQQQtqLOcLgwsajj19K141ER4A4fblUH-cH0ZM_HZQmylYiSxsPljEL--ldyfbPIslT7djTuYJakQdyapeuPpnEDjA0IA1LMfG8yWPpa2Yuyssn5fBB4MsNY3PpF0hwELzugBxw96zU4Q2k9jz5_L3Y3qIyshm8AH5EiIwm5k5LIZs3idghw= MIGqBEEECwGwPNcyCsaGTbr5_BVaThbVuQr7kUWGFI3XgT68kpMi3JGIuO5SCAX4C-ySQxSnQO-9qAZeUjYo7dfnyJiAuwQgLY3YogvmiVW8frt3wxbX9qIBqkgMTcoCdN8af7_QXCEEQQQWPq3mXaFk68AgZgOXq0ORy1XPeTicyazBHv7WGDa_3x-swwhLDW1q8JvvRfbi2t0juMdiEhiG4NgRF-4oOiIOBAA= [email protected]
java -cp attestation-0.3.13-all.jar org.devcon.ticket.Validator pub.pem MIGYMA8MATYCBwCMryzpzeQCAQAEQQQtqLOcLgwsajj19K141ER4A4fblUH-cH0ZM_HZQmylYiSxsPljEL--ldyfbPIslT7djTuYJakQdyapeuPpnEDjA0IA1LMfG8yWPpa2Yuyssn5fBB4MsNY3PpF0hwELzugBxw96zU4Q2k9jz5_L3Y3qIyshm8AH5EiIwm5k5LIZs3idghw= MIGqBEEECwGwPNcyCsaGTbr5_BVaThbVuQr7kUWGFI3XgT68kpMi3JGIuO5SCAX4C-ySQxSnQO-9qAZeUjYo7dfnyJiAuwQgLY3YogvmiVW8frt3wxbX9qIBqkgMTcoCdN8af7_QXCEEQQQWPq3mXaFk68AgZgOXq0ORy1XPeTicyazBHv7WGDa_3x-swwhLDW1q8JvvRfbi2t0juMdiEhiG4NgRF-4oOiIOBAA= [email protected]
54 changes: 54 additions & 0 deletions src/main/java/org/devcon/ticket/LisconTicket.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package org.devcon.ticket;

import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1EncodableVector;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERBitString;
import org.bouncycastle.asn1.DEROctetString;
import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

/**
* Proof of concept Ticket system for Liscon.
* It is significantly less secure than the regular Ticket format and should only be used in legacy settings!
*/
@Deprecated
public class LisconTicket extends Ticket {
public LisconTicket(String mail, String devconId, BigInteger ticketId, int ticketClass,
AsymmetricCipherKeyPair keys, BigInteger secret) {
super(mail, devconId, ticketId, ticketClass, keys, secret);
}

public LisconTicket(String devconId, BigInteger ticketId, int ticketClass, byte[] commitment,
byte[] signature, AsymmetricKeyParameter publicKey) {
super(devconId, ticketId, ticketClass, commitment, signature, publicKey);
}

@Override
ASN1Sequence makeTicket() {
ASN1EncodableVector ticket = new ASN1EncodableVector();
ticket.add(new DERUTF8String(getDevconId()));
ticket.add(new ASN1Integer(getTicketId()));
ticket.add(new ASN1Integer(getTicketClass()));
return new DERSequence(ticket);
}

@Override
byte[] encodeSignedTicket(ASN1Sequence ticket) throws IOException {
ASN1EncodableVector signedTicket = new ASN1EncodableVector();
signedTicket.add(ticket);
signedTicket.add(new DEROctetString(getCommitment()));
signedTicket.add(new DERBitString(getSignature()));
return new DERSequence(signedTicket).getEncoded();
}

@Override
public byte[] getDerEncodingWithPK() {
throw new InternalError(
"This method is not implemented and there should be no need for it as this class should only be used for legacy reasons ");
}
}
35 changes: 35 additions & 0 deletions src/main/java/org/devcon/ticket/LisconTicketDecoder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.devcon.ticket;

import java.io.IOException;
import java.math.BigInteger;
import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.DERUTF8String;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;

/**
* Proof of concept Ticket system for Liscon.
* It is significantly less secure than the regular Ticket format and should only be used in legacy settings!
*/
@Deprecated
public class LisconTicketDecoder extends TicketDecoder {
public LisconTicketDecoder(AsymmetricKeyParameter publicKey) {
super(publicKey);
}

@Override
public Ticket decode(byte[] encoding) throws IOException {
ASN1InputStream input = new ASN1InputStream(encoding);
ASN1Sequence asn1 = ASN1Sequence.getInstance(input.readObject());
ASN1Sequence ticket = ASN1Sequence.getInstance(asn1.getObjectAt(0));
String devconId = (DERUTF8String.getInstance(ticket.getObjectAt(0))).getString();
BigInteger ticketId = (ASN1Integer.getInstance(ticket.getObjectAt(1))).getValue();
int ticketClassInt = ASN1Integer.getInstance(ticket.getObjectAt(2)).getValue().intValueExact();

byte[] commitment = (ASN1OctetString.getInstance(asn1.getObjectAt(1))).getOctets();
byte[] signature = parsePKandSignature(asn1, devconId, 2);
return new LisconTicket(devconId, ticketId, ticketClassInt, commitment, signature, getPk(devconId));
}
}
6 changes: 3 additions & 3 deletions src/main/java/org/devcon/ticket/Ticket.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public Ticket(String devconId, BigInteger ticketId, int ticketClass, byte[] comm
}
}

private ASN1Sequence makeTicket() {
ASN1Sequence makeTicket() {
ASN1EncodableVector ticket = new ASN1EncodableVector();
ticket.add(new DERUTF8String(devconId));
ticket.add(new ASN1Integer(ticketId));
Expand All @@ -106,14 +106,14 @@ private ASN1Sequence makeTicket() {
return new DERSequence(ticket);
}

private byte[] encodeSignedTicket(ASN1Sequence ticket) throws IOException {
byte[] encodeSignedTicket(ASN1Sequence ticket) throws IOException {
ASN1EncodableVector signedTicket = new ASN1EncodableVector();
signedTicket.add(ticket);
signedTicket.add(new DERBitString(signature));
return new DERSequence(signedTicket).getEncoded();
}

public byte[] getDerEncodingWithPK() {
byte[] getDerEncodingWithPK() {
try {
ASN1Sequence ticket = makeTicket();
ASN1EncodableVector signedTicket = new ASN1EncodableVector();
Expand Down
14 changes: 7 additions & 7 deletions src/main/java/org/devcon/ticket/TicketDecoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public Ticket decode(byte[] encoding) throws IOException {
}
*/
byte[] signature = parsePKandSignature(asn1, devconId);
byte[] signature = parsePKandSignature(asn1, devconId, 1);
return new Ticket(devconId, ticketId, ticketClassInt, commitment, signature, getPk(devconId));
}

Expand All @@ -72,24 +72,24 @@ public Ticket decode(byte[] encoding) throws IOException {
* @param input The encoded Ticket
* @return
*/
private byte[] parsePKandSignature(ASN1Sequence input, String devconId) throws IOException, IllegalArgumentException{
byte[] parsePKandSignature(ASN1Sequence input, String devconId, int asnBaseIdx) throws IOException, IllegalArgumentException{
byte[] signature;
ASN1Encodable object = input.getObjectAt(1);
ASN1Encodable object = input.getObjectAt(asnBaseIdx);
if (object instanceof ASN1Sequence) {
// The optional PublicKeyInfo is included
parseEncodingOfPKInfo((ASN1Sequence) object, devconId);
signature = DERBitString.getInstance(input.getObjectAt(2)).getBytes();
signature = DERBitString.getInstance(input.getObjectAt(asnBaseIdx+1)).getBytes();
} else if (object instanceof DERBitString) {
// Only the signature is included
signature = DERBitString.getInstance(input.getObjectAt(1)).getBytes();
signature = DERBitString.getInstance(input.getObjectAt(asnBaseIdx)).getBytes();
} else {
throw ExceptionUtil.throwException(logger,
new IllegalArgumentException("Invalid ticket encoding"));
}
return signature;
}

private void parseEncodingOfPKInfo(ASN1Sequence publicKeyInfo, String devconId) throws IOException, IllegalArgumentException {
void parseEncodingOfPKInfo(ASN1Sequence publicKeyInfo, String devconId) throws IOException, IllegalArgumentException {
AlgorithmIdentifier algorithm = AlgorithmIdentifier.getInstance(publicKeyInfo.getObjectAt(0));
byte[] publicKeyBytes = DERBitString.getInstance(publicKeyInfo.getObjectAt(1)).getEncoded();
AsymmetricKeyParameter decodedPublicKey = SignatureUtility.restoreDefaultKey(algorithm, publicKeyBytes);
Expand All @@ -107,7 +107,7 @@ private void parseEncodingOfPKInfo(ASN1Sequence publicKeyInfo, String devconId)
idsToKeys.put(devconId, decodedPublicKey);
}

private AsymmetricKeyParameter getPk(String devconId) {
AsymmetricKeyParameter getPk(String devconId) {
AsymmetricKeyParameter pk;
if (idsToKeys.get(devconId) != null) {
pk = idsToKeys.get(devconId);
Expand Down
68 changes: 27 additions & 41 deletions src/main/java/org/tokenscript/attestation/demo/Demo.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,6 @@
import static java.nio.file.StandardOpenOption.CREATE;
import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;

import org.tokenscript.attestation.AttestationRequest;
import org.tokenscript.attestation.AttestationAndUsageValidator;
import org.tokenscript.attestation.AttestationRequestWithUsage;
import org.tokenscript.attestation.AttestedObject;
import org.tokenscript.attestation.FullProofOfExponent;
import org.tokenscript.attestation.IdentifierAttestation;
import org.tokenscript.attestation.IdentifierAttestation.AttestationType;
import org.tokenscript.attestation.SignedIdentifierAttestation;
import org.tokenscript.attestation.UseAttestation;
import org.tokenscript.attestation.cheque.Cheque;
import org.tokenscript.attestation.cheque.ChequeDecoder;
import org.tokenscript.attestation.core.AttestationCrypto;
import org.tokenscript.attestation.core.DERUtility;
import org.tokenscript.attestation.core.SignatureUtility;
import org.tokenscript.attestation.core.Validateable;
import org.tokenscript.attestation.core.Verifiable;
import org.tokenscript.attestation.eip712.Eip712AttestationRequest;
import org.tokenscript.attestation.eip712.Eip712AttestationRequestWithUsage;
import org.tokenscript.attestation.eip712.Eip712AttestationUsage;
import org.tokenscript.attestation.eip712.Nonce;
import org.tokenscript.attestation.Timestamp;
import org.tokenscript.attestation.eip712.TokenValidateable;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
Expand All @@ -51,6 +29,28 @@
import org.bouncycastle.crypto.util.PrivateKeyInfoFactory;
import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
import org.tokenscript.attestation.AttestationAndUsageValidator;
import org.tokenscript.attestation.AttestationRequest;
import org.tokenscript.attestation.AttestationRequestWithUsage;
import org.tokenscript.attestation.AttestedObject;
import org.tokenscript.attestation.FullProofOfExponent;
import org.tokenscript.attestation.IdentifierAttestation;
import org.tokenscript.attestation.IdentifierAttestation.AttestationType;
import org.tokenscript.attestation.SignedIdentifierAttestation;
import org.tokenscript.attestation.Timestamp;
import org.tokenscript.attestation.UseAttestation;
import org.tokenscript.attestation.cheque.Cheque;
import org.tokenscript.attestation.cheque.ChequeDecoder;
import org.tokenscript.attestation.core.AttestationCrypto;
import org.tokenscript.attestation.core.DERUtility;
import org.tokenscript.attestation.core.SignatureUtility;
import org.tokenscript.attestation.core.Verifiable;
import org.tokenscript.attestation.eip712.Eip712AttestationRequest;
import org.tokenscript.attestation.eip712.Eip712AttestationRequestEncoder;
import org.tokenscript.attestation.eip712.Eip712AttestationRequestWithUsage;
import org.tokenscript.attestation.eip712.Eip712AttestationUsage;
import org.tokenscript.attestation.eip712.Nonce;
import org.tokenscript.attestation.eip712.TokenValidateable;

public class Demo {
static SecureRandom rand = new SecureRandom();
Expand Down Expand Up @@ -344,7 +344,8 @@ private static void requestAttest(AttestationCrypto crypto, Path pathUserKey, St
byte[] nonce = Nonce.makeNonce(address, ATTESTOR_DOMAIN, new Timestamp());
FullProofOfExponent pok = crypto.computeAttestationProof(secret, nonce);
AttestationRequest attRequest = new AttestationRequest(type, pok);
Eip712AttestationRequest request = new Eip712AttestationRequest(ATTESTOR_DOMAIN, receiverId, attRequest, keys.getPrivate());
Eip712AttestationRequestEncoder encoder = new Eip712AttestationRequestEncoder(Eip712AttestationRequestEncoder.LISCON_USAGE_VALUE);
Eip712AttestationRequest request = new Eip712AttestationRequest(ATTESTOR_DOMAIN, Timestamp.DEFAULT_TIME_LIMIT_MS, receiverId, attRequest, keys.getPrivate(), encoder);
Files.write(outputDirRequest, request.getJsonEncoding().getBytes(StandardCharsets.UTF_8),
CREATE, TRUNCATE_EXISTING);
DERUtility.writePEM(DERUtility.encodeSecret(secret), "SECRET", outputDirSecret);
Expand Down Expand Up @@ -372,9 +373,7 @@ private static void constructAttest(Path pathAttestorKey, String issuerName,
long validityInMilliseconds, Path pathRequest, Path attestationDir) throws Exception {
AsymmetricCipherKeyPair keys = DERUtility.restoreBase64Keys(Files.readAllLines(pathAttestorKey));
String jsonRequest = String.join("", Files.readAllLines(pathRequest));
Eip712AttestationRequest attestationRequest = new Eip712AttestationRequest(ATTESTOR_DOMAIN, jsonRequest);
checkAttestRequestVerifiability(attestationRequest);
checkAttestRequestValidity(attestationRequest);
Eip712AttestationRequest attestationRequest = Eip712AttestationRequest.decodeAndValidateAttestation(ATTESTOR_DOMAIN, jsonRequest);
byte[] commitment = AttestationCrypto.makeCommitment(attestationRequest.getIdentifier(), attestationRequest.getType(), attestationRequest.getPok().getRiddle());
IdentifierAttestation att = new IdentifierAttestation(commitment, attestationRequest.getUserPublicKey());
att.setIssuer("CN=" + issuerName);
Expand All @@ -391,8 +390,8 @@ private static void constructAttestAndUse(Path pathAttestorKey, String issuerNam
AsymmetricCipherKeyPair keys = DERUtility.restoreBase64Keys(Files.readAllLines(pathAttestorKey));
String jsonRequest = String.join("", Files.readAllLines(pathRequest));
Eip712AttestationRequestWithUsage attestationRequest = new Eip712AttestationRequestWithUsage(ATTESTOR_DOMAIN, jsonRequest);
checkAttestRequestVerifiability(attestationRequest);
checkAttestRequestValidity(attestationRequest);
Eip712AttestationRequestWithUsage.checkAttestRequestVerifiability(attestationRequest);
Eip712AttestationRequestWithUsage.checkAttestRequestValidity(attestationRequest);
byte[] commitment = AttestationCrypto.makeCommitment(attestationRequest.getIdentifier(), attestationRequest.getType(), attestationRequest.getPok().getRiddle());
IdentifierAttestation att = new IdentifierAttestation(commitment, attestationRequest.getUserPublicKey());
att.setIssuer("CN=" + issuerName);
Expand All @@ -404,19 +403,6 @@ private static void constructAttestAndUse(Path pathAttestorKey, String issuerNam
DERUtility.writePEM(signed.getDerEncoding(), "ATTESTATION", attestationDir);
}

private static void checkAttestRequestVerifiability(Verifiable input) {
if (!input.verify()) {
System.err.println("Could not verify attestation signing request");
throw new RuntimeException("Verification failed");
}
}
private static void checkAttestRequestValidity(Validateable input) {
if (!input.checkValidity()) {
System.err.println("Could not validate attestation signing request");
throw new RuntimeException("Validation failed");
}
}

private static void useAttest(AttestationCrypto crypto, Path pathUserKey, Path attestationDir, Path pathAttestationSecret, Path attestorVerificationKey,
String receiverId, AttestationType type, Path outputSessionPrivKeyDir, Path outputDirRequest) throws IOException {
AsymmetricCipherKeyPair userKeys = DERUtility.restoreBase64Keys(Files.readAllLines(pathUserKey));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,26 @@ public class Eip712AttestationRequest extends Eip712Validator implements JsonEnc
private final AsymmetricKeyParameter publicKey;
private final long acceptableTimeLimit;

public static Eip712AttestationRequest decodeAndValidateAttestation(String attestorDomain, String jsonEncoding) {
Eip712AttestationRequest attestationRequest;
try {
// Try with Liscon encoder
Eip712AttestationRequestEncoder encoder = new Eip712AttestationRequestEncoder(Eip712AttestationRequestEncoder.LISCON_USAGE_VALUE);
attestationRequest = new Eip712AttestationRequest(attestorDomain,
Timestamp.DEFAULT_TIME_LIMIT_MS, jsonEncoding, encoder);
checkAttestRequestVerifiability(attestationRequest);
checkAttestRequestValidity(attestationRequest);
} catch (Exception e) {
// Try with legacy encoding
Eip712AttestationRequestEncoder encoder = new Eip712AttestationRequestEncoder(Eip712AttestationRequestEncoder.LEGACY_USAGE_VALUE);
attestationRequest = new Eip712AttestationRequest(attestorDomain,
Timestamp.DEFAULT_TIME_LIMIT_MS, jsonEncoding, encoder);
checkAttestRequestVerifiability(attestationRequest);
checkAttestRequestValidity(attestationRequest);
}
return attestationRequest;
}

public Eip712AttestationRequest(String attestorDomain, String identifier,
AttestationRequest request, AsymmetricKeyParameter signingKey) {
this(attestorDomain, Timestamp.DEFAULT_TIME_LIMIT_MS, identifier, request, signingKey);
Expand All @@ -35,7 +55,13 @@ public Eip712AttestationRequest(String attestorDomain, String identifier,
public Eip712AttestationRequest(String attestorDomain, long acceptableTimeLimit,
String identifier, AttestationRequest request,
AsymmetricKeyParameter signingKey) {
super(attestorDomain, new Eip712AttestationRequestEncoder());
this(attestorDomain, acceptableTimeLimit, identifier, request, signingKey, new Eip712AttestationRequestEncoder(Eip712AttestationRequestEncoder.LISCON_USAGE_VALUE));
}

public Eip712AttestationRequest(String attestorDomain, long acceptableTimeLimit,
String identifier, AttestationRequest request,
AsymmetricKeyParameter signingKey, Eip712AttestationRequestEncoder encoder) {
super(attestorDomain, encoder);
try {
this.acceptableTimeLimit = acceptableTimeLimit;
this.attestationRequest = request;
Expand All @@ -55,7 +81,12 @@ public Eip712AttestationRequest(String attestorDomain, String jsonEncoding) {

public Eip712AttestationRequest(String attestorDomain, long acceptableTimeLimit,
String jsonEncoding) {
super(attestorDomain, new Eip712AttestationRequestEncoder());
this(attestorDomain, acceptableTimeLimit, jsonEncoding, new Eip712AttestationRequestEncoder(Eip712AttestationRequestEncoder.LISCON_USAGE_VALUE));
}

public Eip712AttestationRequest(String attestorDomain, long acceptableTimeLimit,
String jsonEncoding, Eip712AttestationRequestEncoder encoder) {
super(attestorDomain, encoder);
try {
this.acceptableTimeLimit = acceptableTimeLimit;
this.jsonEncoding = jsonEncoding;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ public class Eip712AttestationRequestEncoder extends Eip712Encoder {

private static final String PROTOCOL_VERSION = "0.1";
private static final String PRIMARY_NAME = "AttestationRequest";
private static final String USAGE_VALUE = "Linking Ethereum address to phone or email";
public static final String LEGACY_USAGE_VALUE = "Linking Ethereum address to phone or email";
public static final String LISCON_USAGE_VALUE = "Creating email attestation";

public Eip712AttestationRequestEncoder() {
super(USAGE_VALUE, PROTOCOL_VERSION, PRIMARY_NAME);
public Eip712AttestationRequestEncoder(String usageValue) {
super(usageValue, PROTOCOL_VERSION, PRIMARY_NAME);
}

public HashMap<String, List<Entry>> getTypes() {
Expand Down
Loading

0 comments on commit 110b98a

Please sign in to comment.