//* Licensed Materials - Property of *
//* IBM *
//* Alexandra Instituttet A/S *
//* *
//* eu.abc4trust.pabce.1.34 *
//* *
//* (C) Copyright IBM Corp. 2014. All Rights Reserved. *
//* (C) Copyright Alexandra Instituttet A/S, Denmark. 2014. All *
//* Rights Reserved. *
//* US Government Users Restricted Rights - Use, duplication or *
//* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. *
//* *
//* This file is 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. *
//*/**/****************************************************************
package eu.abc4trust.abce.smartcard;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.net.URI;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.crypto.Cipher;
import javax.smartcardio.Card;
import javax.smartcardio.CardException;
import javax.smartcardio.CardTerminal;
import javax.smartcardio.TerminalFactory;
import org.junit.Ignore;
import org.junit.Test;
import com.ibm.zurich.idmx.buildingBlock.systemParameters.EcryptSystemParametersWrapper;
import com.ibm.zurich.idmx.exception.ConfigurationException;
import eu.abc4trust.abce.testharness.ImagePathBuilder;
import eu.abc4trust.cryptoEngine.user.CredentialSerializer;
import eu.abc4trust.cryptoEngine.user.CredentialSerializerObjectGzip;
import eu.abc4trust.cryptoEngine.util.SystemParametersUtil;
import eu.abc4trust.smartcard.HardwareSmartcard;
import eu.abc4trust.smartcard.RSAKeyPair;
import eu.abc4trust.smartcard.RSASignature;
import eu.abc4trust.smartcard.RSASignatureSystem;
import eu.abc4trust.smartcard.RSASignatureSystemTest;
import eu.abc4trust.smartcard.RSAVerificationKey;
import eu.abc4trust.smartcard.Smartcard;
import eu.abc4trust.smartcard.SmartcardBackup;
import eu.abc4trust.smartcard.SmartcardBlob;
import eu.abc4trust.smartcard.SmartcardCrypto;
import eu.abc4trust.smartcard.SmartcardParameters;
import eu.abc4trust.smartcard.SmartcardStatusCode;
import eu.abc4trust.smartcard.SystemParameters;
import eu.abc4trust.smartcard.ZkProofCommitment;
import eu.abc4trust.smartcard.ZkProofResponse;
import eu.abc4trust.smartcard.ZkProofSystem;
import eu.abc4trust.xml.Credential;
import eu.abc4trust.xml.CredentialDescription;
import eu.abc4trust.xml.CryptoParams;
public class HardwareSmartcardTest {
private static final int pin = 1234;
@SuppressWarnings("unused")
private static final int puk = 17751674;
private static final byte[] accesscode = new byte[]{(byte) 0xDD, (byte) 0xE8, (byte) 0x90, (byte) 0x96, 0x3E, (byte) 0xF8, 0x09, 0x0E};
private static BigInteger challenge;
private static Random rand = new Random(42);
//private static final PseudonymSerializer pseudonymSerializer = new PseudonymSerializerGzipXml();
//private static final int keyIDForFirstSignKey = 1;
private static final int keyIDForSecondSignKey = 1;
private static final URI deviceURI = URI.create("ImbaCardNo42");
private static final URI IssuerURINo1 = URI.create("urn:patras:issuer:credUniv:idemix");
private static final URI IssuerURINo2 = URI.create("urn:patras:issuer:credCourse:uprove");
private static RSAKeyPair rootKey = new RSAKeyPair(
new BigInteger("13188739541922660896646064269210831728935525607028122743662847644630716074667792017963587041964414609957176615536380624327700918306145189040520169692459457"),
new BigInteger("12965542865437711645486684206961737786619579267694394955648937336793338179891217408971833767983283274280247590175826238504374133935543138269003896636545659"));
/*
private static RSAKeyPair rootKey = new RSAKeyPair(
new BigInteger("98123248929977781234033599438430872512413464343146397351387389379354368678144441573871246352773205104826862682926853362525445766087875638152522866999171082979077110521492402490396873693935392516032428981301612806156847276776118279635414146466050412914757988580508268698346492883186329475125347579894931495911"),
new BigInteger("153675233447601346431048868855343067422415662106390990153196543740996536617679216226026465835429401901713210990800796200382364371445046479284855834231353845317728582606162246819027954438959188793527020710865829941771890543954962333617286117444708446256701507879424546361300317931079057381850093323907216844089"));
*/
public static HardwareSmartcard getSmartcard() {
HardwareSmartcard smartcard = null;
try {
List<CardTerminal> terminals = TerminalFactory.getDefault()
.terminals().list();
for (CardTerminal terminal : terminals) {
if (!terminal.isCardPresent()) {
continue;
}
Card card = terminal.connect("*");
smartcard = new HardwareSmartcard(terminal, card, rand);
//smartcard.initializeNoOfIssuersAndCreds(pin);
}
} catch (CardException ex) {
throw new RuntimeException(ex);
}
HardwareSmartcard.printInput = true;
challenge = new BigInteger(32, rand);
return smartcard;
}
public static SmartcardParameters getCredentialBases() {
/*
BigInteger p = new BigInteger(
"12626253643225658788054945243310161001518279478947653549052908831079155905872956458802477139613130936776937607840700839905021318088742281050346423374661061");
BigInteger q = new BigInteger(
"10703344939754407345467437772082699346739860491968578743102602332992358121160532991562371831707432661485771211677230593441997251930402068779708696552944203");
*/
// n =
// 59611897368131366507364942276670668747995323268474975289271614234218937009935107719366762946802866847720072176517579036188074246487493444834020695796207762776438347095237876273178780516676456685032464805596922499374627605877256498945463430940126396361032161179291118883563104866211893115282075236693902324109
BigInteger n = new BigInteger(new byte[]{-81, -56, 2, 34, 56, 127, -112, 69, -5, 88, 116, -58, -58, -84, 70, -59, -110, -32, 2, -107, -114, -75, 26, 96, 53, -44, -19, -5, -66, -68, 3, 18, 36, -123, -26, 55, -126, 15, -69, 39, -4, -1, -117, 22, 109, 36, 73, 123, 37, -112, 14, 104, 24, 38, 14, 102, -88, -15, 118, -61, 111, -90, -118, -20, 33, 81, -20, -88, -75, -80, -11, -32, 55, 22, 78, -32, -76, 110, -32, -112, 37, 115, 4, 20, 70, -120, 27, 72, -74, -37, -49, -16, -21, 91, -73, -27, 6, -80, 84, -101, 62, 60, 86, -17, 59, 45, -73, -3, 63, -15, 82, -67, 12, 81, -108, -65, -68, 50, 52, 98, 13, 122, 108, 71, 45, 40, 48, 91, 72, 67, -86, -90, -114, 108, 92, -39, 94, -55, 103, 53, 92, 102, -112, -17, -107, -76, 57, 113, -76, -29, 2, -42, -114, -52, 80, -30, -84, -80, 21, 51, -97, -57, 0, 103, 14, -47, -78, 38, -9, -108, 58, -81, 113, 101, -115, 50, 30, 116, 26, 46, -66, -71, 35, -38, -5, -11, -26, 101, 82, -79, 101, 7});
BigInteger R0 = new BigInteger(new byte[]{72, -108, 10, 99, 97, 120, 77, 42, -113, -17, 25, 77, 126, 63, 96, 52, 12, 99, -22, 111, 39, -80, -23, 88, -54, -49, -35, -79, 68, 29, 54, -102, 98, -59, 61, 121, 122, 73, 82, 8, 22, 107, 57, 33, 60, -127, 88, -40, -86, 57, -81, -26, 3, -16, -95, 83, 21, 58, 46, -105, 125, 71, -61, -109, 97, -83, -23, -32, 86, -18, -2, 124, -119, -2, -16, -94, 75, 71, 88, -34, 49, -77, -7, 83, -115, 109, 34, -66, -77, -3, -27, -8, 78, -116, -107, -26, -91, 93, 56, 38, -85, -118, -108, -82, 106, 7, 68, 18, -56, 74, 118, 90, 15, 87, -11, -43, 33, 92, 92, 54, -74, 21, -78, -67, 41, -44, 118, -81, 114, 92, -22, 3, 42, -38, -33, -6, 6, 19, -80, 52, -9, -126, 61, 76, -107, -58, 52, -98, -57, -18, 40, 99, 125, 47, 113, -1, 56, -20, 81, 1, -65, -68, -66, -115, 55, -120, -74, -12, 69, 82, -46, -58, -66, -34, -101, 121, -108, 68, 41, 59, 100, -24, -103, -112, -41, -54, -105, 65, -16, 90, 26, 13});
BigInteger S = new BigInteger(new byte[]{-123, 124, 48, -77, 123, 68, -29, -30, -12, -34, -70, -12, -123, -19, -7, 27, -101, -111, 30, -98, -67, 71, 16, -39, 38, 124, -100, 65, -106, -97, -68, -13, -37, -109, -54, 105, -15, 26, 48, 52, 37, 105, -120, -120, -126, 52, -26, -60, -121, -54, -75, 27, -61, -23, 99, 21, 78, -128, -88, -112, -46, 49, -27, 9, 65, -19, -96, -49, 40, -27, -77, 23, -36, -100, 45, 61, 112, -113, -108, 32, 86, 72, 13, 16, -25, -36, 46, 50, -97, -54, 12, 72, 51, -14, -36, 11, 76, -6, -73, 37, -57, 59, 52, -43, 95, 77, 21, -14, -97, 68, -116, 66, -90, -119, 52, -44, -85, -25, -39, 86, 85, 106, -16, 88, 14, 50, -103, -96, -76, -68, -98, 34, -87, -18, 14, -122, 1, 84, -106, 119, -101, -43, -67, -128, 75, 41, -27, -91, 91, 19, -119, 36, -1, -126, -10, -26, -91, 84, 127, -37, -22, -4, -90, 95, 7, 19, -126, -14, 9, -53, 69, -127, 22, -8, 13, -18, -48, 28, 40, 70, 76, 11, -106, 21, 16, -96, 121, 58, -103, -94, 108, -61});
return SmartcardParameters.forTwoBaseCl(n, R0, S);
}
public static SystemParameters getSystemParameters(){
eu.abc4trust.xml.SystemParameters sp = SystemParametersUtil.getDefaultSystemParameters_2048();
EcryptSystemParametersWrapper spw = new EcryptSystemParametersWrapper(sp);
BigInteger p, g, subgroupOrder;
try {
p = spw.getDHModulus().getValue();
g = spw.getDHGenerator1().getValue();
subgroupOrder = spw.getDHSubgroupOrder().getValue();
} catch (ConfigurationException e1) {
throw new RuntimeException(e1);
}
SystemParameters system = new SystemParameters();
system.p = p;
system.g = g;
system.subgroupOrder = subgroupOrder;
return system;
}
@Ignore
@Test
public void computeRSAKey(){
RSAKeyPair key = RSASignatureSystem.generateSigningKey(1024/8);
System.out.println("p: "+ key.getP());
System.out.println("q: "+ key.getQ());
}
@Test
public void testBackupAESKey() throws Exception{
String original ="I'm a string...";
byte[] toEnc = original.getBytes("UTF-8");
byte[] IV = new byte[16];
rand.nextBytes(IV);
String salt = "very salty!";
String password = "password";
Cipher encCipher = HardwareSmartcard.getAESKey(salt, password, IV, true);
byte[] enc = encCipher.doFinal(toEnc);
Cipher decCipher = HardwareSmartcard.getAESKey(salt, password, IV, false);
byte[] dec = decCipher.doFinal(enc);
String s = new String(dec, "UTF-8");
assertEquals(original, s);
}
@Ignore
@Test
public void InitializeCard() throws UnsupportedEncodingException{
HardwareSmartcard s = getSmartcard();
int mode = s.getMode();
System.out.println("mode: " + mode);
if(mode == 0){
System.out.println("Set card into root-mode");
assertEquals(s.setRootMode(accesscode), SmartcardStatusCode.OK);
}
SystemParameters system = getSystemParameters();
short deviceID = 1234;
s.init(pin, system, rootKey, deviceID);
assertEquals(s.addIssuerParameters(rootKey, IssuerURINo1, getCredentialBases()), SmartcardStatusCode.OK);
RSAKeyPair key = RSASignatureSystemTest.getSigningKeyForTest();
RSAVerificationKey cvk = RSASignatureSystem.getVerificationKey(key);
int minAttendance = 2;
assertEquals(s.addIssuerParametersWithAttendanceCheck(rootKey, IssuerURINo2, keyIDForSecondSignKey, getCredentialBases(), cvk, minAttendance), SmartcardStatusCode.OK);
s.setWorkingMode();
//now that we have a pin on the card, and are in working more, we store the deviceURI and issuerUris
SmartcardBlob blob = new SmartcardBlob();
blob.blob = deviceURI.toASCIIString().getBytes("US-ASCII");
s.storeBlob(pin, Smartcard.device_name, blob);
//s.storeIssuerUriAndID(pin, IssuerURINo1, staticMap.getIssuerIDFromUri(IssuerURINo1));
//s.storeIssuerUriAndID(pin, IssuerURINo2, staticMap.getIssuerIDFromUri(IssuerURINo2));
}
@Ignore
@Test
public void testBlobStore(){
HardwareSmartcard s = getSmartcard();
URI uri = URI.create("This_is_a_test_URI");
SmartcardBlob blob = new SmartcardBlob();
String toBlob = "Jeg er en blob!";
try {
blob.blob = toBlob.getBytes("US-ASCII");
} catch (UnsupportedEncodingException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
s.storeBlob(HardwareSmartcardTest.pin, uri, blob);
SmartcardBlob blob2 = s.getBlob(pin, uri);
assertTrue(Arrays.equals(blob2.blob, blob.blob));
Map<URI, SmartcardBlob> blobs = s.getBlobs(pin);
for(URI u : blobs.keySet()){
SmartcardBlob smartcardBlob = blobs.get(u);
try {
String blobString = new String(smartcardBlob.blob, "US-ASCII");
System.out.println("<"+u+", "+blobString+">");
assertTrue(blobString.equals(toBlob));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
@Ignore
@Test
public void testCryptoAuth(){
byte[] challenge = new byte[]{-69, 107, -66, 1, 28, -57, 84, -68, -26, 25, -51, 76, -62, 107, 117, -114, -60, 15, -112, 39, -97, 2, 54, 111, 15, -64, 67, -41, -43, 44, -44, 107};
byte[] data = new byte[257];
RSASignature sig = SmartcardCrypto.generateSignature(data, challenge, rootKey, rand);
RSAVerificationKey verKey = new RSAVerificationKey();
verKey.n = rootKey.getN();
byte[] extracted = SmartcardCrypto.extraction(verKey, sig, challenge);
assertTrue(Arrays.equals(data, extracted));
}
@Ignore
@Test
public void testStoreCredential(){
HardwareSmartcard s = getSmartcard();
s.getBlobs(pin);
URI credentialId = URI.create("credUri");
Random r = new Random(1234);
URI longURI1 = URI.create(new BigInteger(2048*3, r).toString());
URI longURI2 = URI.create(new BigInteger(2048*2, r).toString());
URI longURI3 = URI.create(new BigInteger(2048*2, r).toString());
CredentialSerializer serializer = new CredentialSerializerObjectGzip();
Credential cred = new Credential();
CryptoParams cryptoParam = new CryptoParams();
CredentialDescription credDesc = new CredentialDescription();
credDesc.setImageReference(ImagePathBuilder.TEST_IMAGE_JPG);
credDesc.setIssuerParametersUID(longURI1);
credDesc.setCredentialSpecificationUID(longURI2);
credDesc.setCredentialUID(longURI3);
cred.setCredentialDescription(credDesc);
cred.setCryptoParams(cryptoParam);
assertEquals(s.storeCredential(pin, credentialId, cred, serializer), SmartcardStatusCode.OK);
Credential credPrime = s.getCredential(pin, credentialId, serializer);
assertNotNull(credPrime);
CredentialDescription credDescriptionPrime = credPrime.getCredentialDescription();
System.out.println("from read credential - credUID: "+credDescriptionPrime.getCredentialUID().toString());
assertEquals(credDesc.getCredentialUID(), credDescriptionPrime.getCredentialUID());
byte[] origCredSerialized = serializer.serializeCredential(cred);
byte[] newCredSerialized = serializer.serializeCredential(credPrime);
System.out.println("orig: " + origCredSerialized.length+", new: " + newCredSerialized.length);
assertTrue(Arrays.equals(origCredSerialized, newCredSerialized));
}
@Ignore
@Test
public void testBackup() throws Exception{
HardwareSmartcard s = getSmartcard();
//s.addIssuerParametersWithAttendanceCheck(pin, rootKey, IssuerURINo1, keyIDForFirstSignKey, getCredentialBases(), RSASignatureSystem.getVerificationKey(RSASignatureSystemTest.getSigningKeyForTest()), 2);
SmartcardBlob blob = new SmartcardBlob();
blob.blob = deviceURI.toASCIIString().getBytes("US-ASCII");
s.storeBlob(pin, Smartcard.device_name, blob);
String password = "12345678";
SmartcardBackup backup = s.backupAttendanceData(pin, password);
assertNotNull(backup);
System.out.println("backup device: " + Arrays.toString(backup.macDevice));
//System.out.println("backup counters: " + Arrays.toString(backup.macCounters));
for(Byte credID : backup.macCredentials.keySet()){
System.out.println("backup credential with ID: "+ credID+": "+ Arrays.toString(backup.macCredentials.get(credID)));
}
File f = new File("testBackup.bac");
backup.serialize(f);
}
@Ignore
@Test
public void testRestore(){
HardwareSmartcard s = getSmartcard();
if(s.getMode() == 0){
System.out.println("Set card into root-mode");
s.setRootMode(accesscode);
}
String password = "12345678";
File f = new File("testBackup.bac");
SmartcardBackup backup = SmartcardBackup.deserialize(f);
assertEquals(s.restoreAttendanceData(pin, password, backup), SmartcardStatusCode.OK);
assertEquals(new String(s.getBlob(pin, Smartcard.device_name).blob), deviceURI.toASCIIString());
}
@Ignore
@Test
public void testEmptyProof() {
HardwareSmartcard s = getSmartcard();
Set<URI> credentialIDs = new HashSet<URI>();
Set<URI> scopeExclusivePseudonyms = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credentialIDs, scopeExclusivePseudonyms, false);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credentialIDs, scopeExclusivePseudonyms);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
// There are no witnesses, so the challenge doesn't actually matter
assertTrue(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
@Ignore
@Test
public void testNormalPseudonym() {
HardwareSmartcard s = getSmartcard();
Set<URI> credentialIDs = new HashSet<URI>();
Set<URI> scopeExclusivePseudonyms = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credentialIDs, scopeExclusivePseudonyms, true);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credentialIDs, scopeExclusivePseudonyms);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
@Ignore
@Test
public void fixPin(){
HardwareSmartcard s = getSmartcard();
int oldPin = 5678;
int puk = 70952389;
System.out.println(s.resetPinWithPuk(puk, pin));
//System.out.println(s.changePin(oldPin, pin));
}
@Ignore
@Test
public void testScopeExclusivePseudonym() {
HardwareSmartcard s = getSmartcard();
// Scope exclusive pseudonym
URI scope = URI.create("urn:patras:registration");
Set<URI> scopeList = new HashSet<URI>();
scopeList.add(scope);
Set<URI> credentialIDs = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credentialIDs, scopeList, false);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credentialIDs, scopeList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
@Ignore
@Test
public void testSimpleCredential() {
HardwareSmartcard s = getSmartcard();
URI issuerUri = IssuerURINo1;
URI credUri = URI.create("credential");
assertEquals(s.allocateCredential(pin, credUri, issuerUri), SmartcardStatusCode.OK);
Set<URI> credList = new HashSet<URI>();
credList.add(credUri);
// First proof
{
Set<URI> scopeList = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credList, scopeList, false);
assertNotNull(comm);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, scopeList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
// Second proof should work, since no attendance checks are done
// {
// Set<URI> scopeList = new HashSet<URI>();
// ZkProofCommitment comm = s.prepareZkProof(pin, credList, scopeList, false);
// assertNotNull(comm);
// ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, scopeList, comm.nonceCommitment);
// assertTrue(ZkProofSystem.checkProof(comm, res, challenge, comm.nonceCommitment));
// assertFalse(ZkProofSystem.checkProof(comm, res, new byte[1]));
// }
s.deleteCredential(pin, credUri);
}
@Ignore
@Test
public void testCourseCredential() {
HardwareSmartcard s = getSmartcard();
URI issuerUri = IssuerURINo2;
URI credUri = URI.create("courseCred");
RSAKeyPair key = RSASignatureSystemTest.getSigningKeyForTest();
assertEquals(s.allocateCredential(pin, credUri, issuerUri), SmartcardStatusCode.OK);
// Course counter should be disabled before issuance
{
int lectureId = 42;
assertEquals(s.incrementCourseCounter(pin, key, issuerUri, lectureId), SmartcardStatusCode.NOT_MODIFIED);
}
Set<URI> credList = new HashSet<URI>();
credList.add(credUri);
// Initial ZK proof = issuance
{
Set<URI> scopeList = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credList, scopeList, false);
assertNotNull(comm);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, scopeList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
//assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
// Once the credential is issued, no more proofs until attendance check
assertNull(s.prepareZkProof(pin, credList, new HashSet<URI>(), false));
// Increment course counter
{
int lectureId = 42;
assertEquals(s.incrementCourseCounter(pin, key, issuerUri, lectureId), SmartcardStatusCode.OK);
}
// Not enough attendance
assertNull(s.prepareZkProof(pin, credList, new HashSet<URI>(), false));
// Replay attack protection
{
int lectureId = 42;
assertEquals(s.incrementCourseCounter(pin, key, issuerUri, lectureId), SmartcardStatusCode.NOT_MODIFIED);
}
// Not enough attendance
assertNull(s.prepareZkProof(pin, credList, new HashSet<URI>(), false));
// Replay attack protection
{
int lectureId = 39;
assertEquals(s.incrementCourseCounter(pin, key, issuerUri, lectureId), SmartcardStatusCode.NOT_MODIFIED);
}
// Not enough attendance
assertNull(s.prepareZkProof(pin, credList, new HashSet<URI>(), false));
// Increment counter
{
int lectureId = 43;
assertEquals(s.incrementCourseCounter(pin, key, issuerUri, lectureId), SmartcardStatusCode.OK);
}
{
for(int lectureId = 44; lectureId < 50; lectureId++){
assertEquals(SmartcardStatusCode.OK, s.incrementCourseCounter(pin, key, issuerUri, lectureId));
}
}
// Now the proof works
{
Set<URI> scopeList = new HashSet<URI>();
ZkProofCommitment comm = s.prepareZkProof(pin, credList, scopeList, false);
assertNotNull(comm);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, scopeList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
s.deleteCredential(pin, credUri);
}
@Ignore
@Test
public void testMultipleCredentialsAndPseudonyms() {
HardwareSmartcard s = getSmartcard();
URI issuerUriA = IssuerURINo1;
URI issuerUriB = IssuerURINo2;
URI credUriA1 = URI.create("credential1");
URI credUriA2 = URI.create("credential2");
URI credUriA3 = URI.create("credential3");
URI credUriB1 = URI.create("credential4");
URI credUriB2 = URI.create("credential5");
assertEquals(s.allocateCredential(pin, credUriA1, issuerUriA), SmartcardStatusCode.OK);
assertEquals(s.allocateCredential(pin, credUriA2, issuerUriA), SmartcardStatusCode.OK);
assertEquals(s.allocateCredential(pin, credUriA3, issuerUriA), SmartcardStatusCode.OK);
assertEquals(s.allocateCredential(pin, credUriB1, issuerUriB), SmartcardStatusCode.OK);
assertEquals(s.allocateCredential(pin, credUriB2, issuerUriB), SmartcardStatusCode.OK);
Set<URI> credList = new HashSet<URI>();
credList.add(credUriA1);
credList.add(credUriA2);
credList.add(credUriA3);
credList.add(credUriB1);
// without B2
Set<URI> pseuList = new HashSet<URI>();
pseuList.add(URI.create("scope1"));
pseuList.add(URI.create("scope2"));
pseuList.add(URI.create("scope3"));
// Initial ZK proof = issuance
{
ZkProofCommitment comm = s.prepareZkProof(pin, credList, pseuList, true);
assertNotNull(comm);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, pseuList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
credList.remove(credUriA1);
credList.remove(credUriA2);
credList.remove(credUriA3);
credList.remove(credUriB1);
credList.add(credUriB2);
// B2 is issued here, (B1 not in the proof), other credentials don't have attendance check
{
ZkProofCommitment comm = s.prepareZkProof(pin, credList, pseuList, true);
assertNotNull(comm);
ZkProofResponse res = s.finalizeZkProof(pin, challenge, credList, pseuList);
assertTrue(ZkProofSystem.checkProof(comm, res, challenge));
assertFalse(ZkProofSystem.checkProof(comm, res, BigInteger.ZERO));
}
// Now the attendance check kicks in
assertNull(s.prepareZkProof(pin, credList, pseuList, true));
s.deleteCredential(pin, credUriA1);
s.deleteCredential(pin, credUriA2);
s.deleteCredential(pin, credUriA3);
s.deleteCredential(pin, credUriB1);
s.deleteCredential(pin, credUriB2);
}
}