Commit ddecd30f authored by calocedre TAC's avatar calocedre TAC
Browse files

WIP: use Instant for times whenever possible

parent d36e56f5
......@@ -20,6 +20,7 @@ import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.InvalidKeySpecException;
import java.time.Instant;
import java.util.Arrays;
import java.util.UUID;
......@@ -44,6 +45,9 @@ import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
/**
* Encryption/Decription respecting ECIES-KEM (Elliptic Curve Integrated
* Encryption Scheme with Key encapsulation mechanisms )
......@@ -56,6 +60,7 @@ import org.bouncycastle.util.encoders.Hex;
* for Public-Key Encryption”, 2006</a>
*
*/
@Slf4j
public class CleaEciesEncoder {
/* Type of the elliptic curve */
......@@ -249,65 +254,6 @@ public class CleaEciesEncoder {
return out;
}
/**
* concat two bytes array in one
*
* @param part1 first bytes array
* @param part2 second bytes array
* @return bytes array concatenation
*/
protected byte[] concat(byte[] part1, byte[] part2) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(part1);
outputStream.write(part2);
byte concatParts[] = outputStream.toByteArray();
return concatParts;
}
/**
* convert 32 bytes array in UUID format
*
* @param bytes 32 bytes array
* @return UUID
*/
protected UUID bytesToUuid(byte[] bytes) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
long firstLong = bb.getLong();
long secondLong = bb.getLong();
return new UUID(firstLong, secondLong);
}
/**
* convert a UUID format in 32 bytes array
*
* @param uuid UUID
* @return 32 bytes array
*/
protected byte[] uuidToBytes(UUID uuid) {
ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
return buffer.array();
}
/**
* convert an int in 32 bytes array
*
* @param data int to be converted
* @return 32 bytes array
*/
private static byte[] intToBytes(int data) {
return new byte[] {
(byte) ((data >> 24) & 0xff),
(byte) ((data >> 16) & 0xff),
(byte) ((data >> 8) & 0xff),
(byte) ((data >> 0) & 0xff) };
}
/**
* Compute the LTKey (Temporary Location Key) respecting Cléa protocol
* LTKey(t_periodStart) = SHA256(SK_L | t_periodStart)
......@@ -318,9 +264,10 @@ public class CleaEciesEncoder {
* @return LTKey (Temporary Location Key)
* @throws CleaEncryptionException
*/
public byte[] computeLocationTemporarySecretKey(String permanentLocationSecretKey, int periodStartTime) throws CleaEncryptionException {
public byte[] computeLocationTemporarySecretKey(String permanentLocationSecretKey, Instant periodStartTime) throws CleaEncryptionException {
log.info("permanentLocationSecretKey: {}, periodStartTime= {}", permanentLocationSecretKey, periodStartTime);
try {
byte[] concatKey = this.concat(intToBytes(periodStartTime), Hex.decode(permanentLocationSecretKey));
byte[] concatKey = this.concat(instantToBytes(periodStartTime), Hex.decode(permanentLocationSecretKey));
MessageDigest msg = MessageDigest.getInstance("SHA-256");
byte[] locationTemporarySecretKey = msg.digest(concatKey);
......@@ -359,4 +306,68 @@ public class CleaEciesEncoder {
}
}
private byte[] instantToBytes(Instant periodStartTime) {
long timestamp = TimeUtils.ntpTimestampFromInstant(periodStartTime);
return intToBytes((int) timestamp);
}
/**
* convert an int in 32 bytes array
*
* @param data int to be converted
* @return 32 bytes array
*/
private static byte[] intToBytes(int data) {
return new byte[] {
(byte) ((data >> 24) & 0xff),
(byte) ((data >> 16) & 0xff),
(byte) ((data >> 8) & 0xff),
(byte) ((data >> 0) & 0xff) };
}
/**
* concat two bytes array in one
*
* @param part1 first bytes array
* @param part2 second bytes array
* @return bytes array concatenation
*/
protected byte[] concat(byte[] part1, byte[] part2) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(part1);
outputStream.write(part2);
byte concatParts[] = outputStream.toByteArray();
return concatParts;
}
/**
* convert 32 bytes array in UUID format
*
* @param bytes 32 bytes array
* @return UUID
*/
protected UUID bytesToUuid(byte[] bytes) {
ByteBuffer bb = ByteBuffer.wrap(bytes);
long firstLong = bb.getLong();
long secondLong = bb.getLong();
return new UUID(firstLong, secondLong);
}
/**
* convert a UUID format in 32 bytes array
*
* @param uuid UUID
* @return 32 bytes array
*/
protected byte[] uuidToBytes(UUID uuid) {
ByteBuffer buffer = ByteBuffer.wrap(new byte[16]);
buffer.putLong(uuid.getMostSignificantBits());
buffer.putLong(uuid.getLeastSignificantBits());
return buffer.array();
}
}
package fr.inria.clea.lsp;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Objects;
import java.util.UUID;
import fr.devnied.bitlib.BytesUtils;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
......@@ -32,7 +33,7 @@ public class Location {
* @throws CleaEncryptionException
*/
public String newDeepLink() throws CleaEncryptionException {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
return this.newDeepLink(periodStartTime);
}
......@@ -41,14 +42,11 @@ public class Location {
* at the given period start time with a QR code validaty
* starting at the period start time.
*
* @param periodStartTime Starting time of the period, expressed as the number
* of seconds since January 1st, 1900 (NTP timestamp limited to the 32-bit
* seconds field), by convention in the UTC (Coordinated Universal Time) timezone.
* A period necessarily starts at a round hour.
* @param periodStartTime Starting time of the period. A period necessarily starts at a round hour.
* @return the deep link as a String
* @throws CleaEncryptionException
*/
public String newDeepLink(int periodStartTime) throws CleaEncryptionException {
public String newDeepLink(Instant periodStartTime) throws CleaEncryptionException {
// QR-code validity starts at period start time
return this.newDeepLink(periodStartTime, periodStartTime);
}
......@@ -58,18 +56,12 @@ public class Location {
* at the given period start time with a QR code validaty
* starting at the period start time.
*
* @param periodStartTime Starting time of the period, expressed as the number
* of seconds since January 1st, 1900 (NTP timestamp limited to the 32-bit
* seconds field), by convention in the UTC (Coordinated Universal Time) timezone.
* A period necessarily starts at a round hour.
* @param qrCodeValidityStartTime Starting time of the QR code validity timespan,
* expressed as the number of seconds since January 1st, 1900 (NTP timestamp
* limited to the 32-bit seconds field),
* by convention in UTC (Coordinated Universal Time) timezone.
* @param periodStartTime Starting time of the period. A period necessarily starts at a round hour.
* @param qrCodeValidityStartTime Starting time of the QR code validity timespan.
* @return the deep link as a String
* @throws CleaEncryptionException
*/
public String newDeepLink(int periodStartTime, int qrCodeValidityStartTime) throws CleaEncryptionException {
public String newDeepLink(Instant periodStartTime, Instant qrCodeValidityStartTime) throws CleaEncryptionException {
this.setPeriodStartTime(periodStartTime);
this.setQrCodeValidityStartTime(periodStartTime, qrCodeValidityStartTime);
return COUNTRY_SPECIFIC_PREFIX + this.getLocationSpecificPartEncryptedBase64();
......@@ -95,7 +87,7 @@ public class Location {
return new LocationContactMessageEncoder(this.manualContactTracingAuthorityPublicKey).encode(contact);
}
protected void setPeriodStartTime(int periodStartTime) throws CleaEncryptionException {
protected void setPeriodStartTime(Instant periodStartTime) throws CleaEncryptionException {
byte[] locationTemporarySecretKey = this.getCleaEncoder().computeLocationTemporarySecretKey(this.permanentLocationSecretKey, periodStartTime);
UUID currentLocationTemporaryPublicId = this.getCleaEncoder().computeLocationTemporaryPublicId(locationTemporarySecretKey);
this.locationSpecificPart.setPeriodStartTime(periodStartTime);
......@@ -104,32 +96,32 @@ public class Location {
if (Objects.nonNull(this.contact)) {
this.contact.setPeriodStartTime(periodStartTime);
}
log.debug("new periodStartTime: {} ", Integer.toUnsignedString(periodStartTime));
log.debug("new periodStartTime: {} ", periodStartTime);
log.debug("locationTemporarySecretKey*: {}*", BytesUtils.bytesToString(locationTemporarySecretKey));
log.debug("locationTemporaryPublicID: " + currentLocationTemporaryPublicId.toString());
}
protected void setQrCodeValidityStartTime(int periodStartTime, int qrCodeValidityStartTime) {
protected void setQrCodeValidityStartTime(Instant periodStartTime, Instant qrCodeValidityStartTime) {
if ((this.locationSpecificPart.getQrCodeRenewalInterval() == 0)
&& (this.locationSpecificPart.getQrCodeValidityStartTime() != 0)) {
&& Objects.nonNull(this.locationSpecificPart.getQrCodeValidityStartTime())) {
log.warn("Cannot update QrCode validity start time. No renewal specified!");
return;
}
if(qrCodeValidityStartTime < periodStartTime){
if (qrCodeValidityStartTime.isBefore(periodStartTime)) {
log.warn("Cannot set QrCode validity start time to {}. It preceeds period validity (start: {}, duration (in hours): {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getPeriodDuration());
return;
}
if (qrCodeValidityStartTime > periodStartTime + this.locationSpecificPart.getPeriodDuration() * TimeUtils.NB_SECONDS_PER_HOUR) {
if (qrCodeValidityStartTime.isAfter(periodStartTime.plus(this.locationSpecificPart.getPeriodDuration(), ChronoUnit.HOURS))) {
log.warn("Cannot set QrCode validity start time to {}. It exceeds period validity (start: {}, duration (in hours): {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getPeriodDuration());
return;
}
if ((this.locationSpecificPart.getQrCodeRenewalInterval() != 0) &&
(((qrCodeValidityStartTime - periodStartTime) % this.locationSpecificPart.getQrCodeRenewalInterval()) != 0)) {
(((qrCodeValidityStartTime.getEpochSecond() - periodStartTime.getEpochSecond()) % this.locationSpecificPart.getQrCodeRenewalInterval()) != 0)) {
log.warn("Cannot set QrCode validity start time to {}. It is not a multiple of qrCodeRenewalInterval (qrCodeValidityStartTime: {}, periodStartTime: {}, qrCodeRenewalInterval: {}",
qrCodeValidityStartTime, periodStartTime, this.locationSpecificPart.getQrCodeRenewalInterval());
return;
......
package fr.inria.clea.lsp;
import java.time.Instant;
import javax.validation.constraints.Max;
import lombok.Builder;
......@@ -21,5 +23,5 @@ public class LocationContact {
String locationPin;
/* Starting time of the period in seconds */
@Setter(AccessLevel.PROTECTED)
int periodStartTime;
Instant periodStartTime;
}
......@@ -9,6 +9,7 @@ import java.security.spec.InvalidKeySpecException;
import org.bouncycastle.crypto.InvalidCipherTextException;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
......@@ -67,7 +68,8 @@ public class LocationContactMessageEncoder {
}
/* t_periodStart (32 bits) */
locationContactMessage.setNextInteger(message.getPeriodStartTime(), 32);
int periodStartTime = (int) TimeUtils.ntpTimestampFromInstant(message.getPeriodStartTime());
locationContactMessage.setNextInteger(periodStartTime, 32);
return locationContactMessage.getData();
}
......@@ -107,7 +109,8 @@ public class LocationContactMessageEncoder {
/* t_periodStart (32 bits) */
int periodStartTime = bitLocationContactMessage.getNextInteger(32);
return new LocationContact(locationPhone.toString(), locationPin.toString(), periodStartTime);
return new LocationContact(locationPhone.toString(),
locationPin.toString(), TimeUtils.instantFromTimestamp(periodStartTime));
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IllegalStateException | InvalidCipherTextException
| IOException e) {
throw new CleaEncryptionException(e);
......
......@@ -3,6 +3,7 @@
*/
package fr.inria.clea.lsp;
import java.time.Instant;
import java.util.Objects;
import java.util.UUID;
......@@ -88,7 +89,7 @@ public class LocationSpecificPart {
/* Starting time of the QR code validity timespan in seconds */
@Setter
protected int qrCodeValidityStartTime;
protected Instant qrCodeValidityStartTime;
/* Temporary location key for the period */
@Setter
......@@ -104,10 +105,18 @@ public class LocationSpecificPart {
return Objects.nonNull(this.encryptedLocationContactMessage);
}
public void setPeriodStartTime(int periodStartTime) {
this.compressedPeriodStartTime = Integer.divideUnsigned(periodStartTime, TimeUtils.NB_SECONDS_PER_HOUR);
public Instant getPeriodStartTime() {
return TimeUtils.instantFromTimestamp((long) this.compressedPeriodStartTime * TimeUtils.NB_SECONDS_PER_HOUR);
}
public void setPeriodStartTime(Instant periodStartTime) {
long periodStartTimeAsNtpTimestamp = TimeUtils.ntpTimestampFromInstant(periodStartTime);
this.compressedPeriodStartTime = (int) (periodStartTimeAsNtpTimestamp / TimeUtils.NB_SECONDS_PER_HOUR);
}
/**
* @return the number of seconds between a new QR code generation.
*/
public int getQrCodeRenewalInterval() {
if (this.qrCodeRenewalIntervalExponentCompact == 0x1F) {
return 0;
......
......@@ -15,6 +15,7 @@ import org.bouncycastle.crypto.InvalidCipherTextException;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.EncryptedLocationSpecificPart.EncryptedLocationSpecificPartBuilder;
import fr.inria.clea.lsp.LocationSpecificPart.LocationSpecificPartBuilder;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
/**
......@@ -150,7 +151,7 @@ public class LocationSpecificPartDecoder {
.venueCategory2(message.getNextInteger(4))
.periodDuration(message.getNextInteger(8))
.compressedPeriodStartTime(message.getNextInteger(24))
.qrCodeValidityStartTime(message.getNextInteger(32))
.qrCodeValidityStartTime(TimeUtils.instantFromTimestamp(message.getNextInteger(32)))
.locationTemporarySecretKey(message.getNextByte(256))
.encryptedLocationContactMessage(encryptedLocationContactMessage);
return locationSpecificPartbuilder.build();
......
......@@ -8,6 +8,7 @@ import java.util.Objects;
import java.util.UUID;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
/**
......@@ -103,7 +104,8 @@ public class LocationSpecificPartEncoder {
/* ct_periodStart (24 bits) */
message.setNextInteger(locationSpecificPart.getCompressedPeriodStartTime(), 24);
/* t_qrStart (32 bits) */
message.setNextInteger(locationSpecificPart.getQrCodeValidityStartTime(), 32);
int qrCodeValidityStartTime = (int) TimeUtils.ntpTimestampFromInstant(locationSpecificPart.getQrCodeValidityStartTime());
message.setNextInteger(qrCodeValidityStartTime, 32);
/* LTKey (32 bytes) */
message.setNextByte(locationSpecificPart.getLocationTemporarySecretKey(), 256);
/* Encode the locContactMsg with encryption if required */
......
package fr.inria.clea.lsp;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import fr.inria.clea.lsp.Location.LocationBuilder;
import fr.inria.clea.lsp.utils.TimeUtils;
......@@ -36,7 +39,7 @@ public class LspEncoderDecoder {
String valuesToreturn = (lsp.isStaff()? 1 : 0) + " " + lsp.getCountryCode() + " " + lsp.getQrCodeRenewalIntervalExponentCompact() + " " + lsp.getVenueType();
valuesToreturn += " " + lsp.getVenueCategory1() + " " + lsp.getVenueCategory2() + " " + lsp.getPeriodDuration() + " " + lsp.getLocationTemporaryPublicId();
valuesToreturn += " " + Integer.toUnsignedString(lsp.getCompressedPeriodStartTime()) + " " + Integer.toUnsignedString(lsp.getQrCodeValidityStartTime());
valuesToreturn += " " + Integer.toUnsignedString(lsp.getCompressedPeriodStartTime()) + " " + TimeUtils.ntpTimestampFromInstant(lsp.getQrCodeValidityStartTime());
if (lsp.isLocationContactMessagePresent()) {
LocationContactMessageEncoder contactMessageDecode = new LocationContactMessageEncoder(manualContactTracingAuthoritySecretKey);
......@@ -58,7 +61,7 @@ public class LspEncoderDecoder {
final String manualContactTracingAuthorityPublicKey = args[9];
final String permanentLocationSecretKey = args[10];
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
/* Encode a LSP with location */
LocationSpecificPart lsp = LocationSpecificPart.builder()
.staff(staff == 1)
......@@ -84,14 +87,14 @@ public class LspEncoderDecoder {
Location location = locationBuilder.build();
location.setPeriodStartTime(periodStartTime);
//location.setQrCodeValidityStartTime(periodStartTime, (int) TimeUtils.currentNtpTime());
location.getLocationSpecificPart().setQrCodeValidityStartTime( (int) TimeUtils.currentNtpTime());
location.getLocationSpecificPart().setQrCodeValidityStartTime(Instant.now().truncatedTo(ChronoUnit.HOURS));
String encryptedLocationSpecificPart = location.getLocationSpecificPartEncryptedBase64();
final String valuesToreturn = encryptedLocationSpecificPart + " "
+ location.getLocationSpecificPart().getLocationTemporaryPublicId() + " "
+ Integer.toUnsignedString(location.getLocationSpecificPart().getCompressedPeriodStartTime()) + " "
+ Integer.toUnsignedString(location.getLocationSpecificPart().getQrCodeValidityStartTime());
+ TimeUtils.ntpTimestampFromInstant(location.getLocationSpecificPart().getQrCodeValidityStartTime());
System.out.println(valuesToreturn);
}
......
......@@ -12,6 +12,8 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Base64;
import java.util.Random;
......@@ -78,7 +80,7 @@ class LocationSpecificPartTest {
@Test
public void testEncodinsAndDecodingOfALocationMessage() throws CleaEncryptionException {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
LocationContact locationContact = new LocationContact("0612150292", "01234567", periodStartTime);
Location location = Location.builder().contact(locationContact)
.manualContactTracingAuthorityPublicKey(manualContactTracingAuthorityKeyPair[1])
......@@ -93,7 +95,7 @@ class LocationSpecificPartTest {
@Test
public void testEncodingAndDecodingOfALocationSpecificPart() throws CleaEncryptionException, CleaEncodingException {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
LocationContact locationContact = new LocationContact("33800130000", "01234567", periodStartTime);
/* Encode a LSP with location */
LocationSpecificPart lsp = LocationSpecificPart.builder().staff(true).countryCode(33)
......@@ -119,7 +121,7 @@ class LocationSpecificPartTest {
@Test
public void testEncodingAndDecodingOfALocationSpecificPartWithoutLocationContact()
throws CleaEncryptionException, CleaEncodingException {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
/* Encode a LSP with location */
LocationSpecificPart lsp = LocationSpecificPart.builder().staff(true).countryCode(33)
.qrCodeRenewalIntervalExponentCompact(2).venueType(4).venueCategory1(0).venueCategory2(0)
......@@ -128,7 +130,7 @@ class LocationSpecificPartTest {
.serverAuthorityPublicKey(serverAuthorityKeyPair[1])
.permanentLocationSecretKey(permanentLocationSecretKey).build();
location.setPeriodStartTime(periodStartTime);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime+120);
location.setQrCodeValidityStartTime(periodStartTime, periodStartTime.plus(120, ChronoUnit.SECONDS));
/* Encode a LSP with location */
String encryptedLocationSpecificPart = location.getLocationSpecificPartEncryptedBase64();
......@@ -164,7 +166,7 @@ class LocationSpecificPartTest {
@Disabled("Keep this piece of code as example how to generate a Qrcode image")
@Test
public void testQrCodeGeneration() throws Exception {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
/* Encode the LSP */
LocationSpecificPart lsp = LocationSpecificPart.builder().staff(true).countryCode(33)
.qrCodeRenewalIntervalExponentCompact(2).venueType(4).venueCategory1(0).venueCategory2(0)
......@@ -211,10 +213,7 @@ class LocationSpecificPartTest {
assertThat(lsp.getVenueCategory1()).isEqualTo(venueCat1);
assertThat(lsp.getVenueCategory2()).isEqualTo(venueCat2);
assertThat(lsp.getCompressedPeriodStartTime()).isEqualTo(periodStartTime);
/* Be careful the int qrCodeValidityStartTime is unsigned */
System.out.println("qrCodeValidityStartTime = " + Integer.toUnsignedString(lsp.getQrCodeValidityStartTime()));
int tstQrCodeValidityStartTime = Integer.compareUnsigned(lsp.getQrCodeValidityStartTime(), (int) qrStartTime);
assertThat(tstQrCodeValidityStartTime).isEqualTo(0);
assertThat(lsp.getQrCodeValidityStartTime()).isEqualTo(TimeUtils.instantFromTimestamp(qrStartTime));
}
/**
......@@ -230,7 +229,7 @@ class LocationSpecificPartTest {
String serverAuthorityPublicKey, String lspbase64) throws CleaEncryptionException, CleaEncodingException {
/* Use only testLSPDecoding.csv parameters to have a variety of parameters */
/* times parameters and location are generated */
int myPeriodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
Instant myPeriodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
Random rn = new Random();
int nbDigits = rn.nextInt(6) + 10;
String phone = generateRandomDigits(nbDigits);
......@@ -278,10 +277,7 @@ class LocationSpecificPartTest {
assertThat(decodedLocationContact.getLocationPhone()).isEqualTo(locationPhone);
assertThat(decodedLocationContact.getLocationPin()).isEqualTo(locationPin);
/* Be careful the int PeriodStartTime is unsigned */
System.out.println("PeriodStartTime = " + Integer.toUnsignedString(decodedLocationContact.getPeriodStartTime()));
int tstPeriodStartTime = Integer.compareUnsigned(decodedLocationContact.getPeriodStartTime(), (int) t_periodStart);
assertThat(tstPeriodStartTime).isEqualTo(0);
assertThat(decodedLocationContact.getPeriodStartTime()).isEqualTo(TimeUtils.instantFromTimestamp(t_periodStart));
}
@Test
......@@ -309,6 +305,15 @@ class LocationSpecificPartTest {
assertThat(message).isEqualTo(plainTextBytes);
}
@Test
public void testCompressedPeriodStartTime() {
LocationSpecificPart lsp = LocationSpecificPart.builder().build();
Instant periodStartTime = Instant.parse("2007-12-03T10:00:00.00Z");
lsp.setPeriodStartTime(periodStartTime);
assertThat(lsp.getPeriodStartTime()).isEqualTo(periodStartTime);
}
/**
* Generates a random long with n digits
......
......@@ -4,12 +4,13 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import fr.inria.clea.lsp.utils.TimeUtils;
// @ExtendWith(MockitoJUnitRunner.class)
public class LocationTest {
......@@ -17,7 +18,7 @@ public class LocationTest {
private final String permanentLocationSecretKey = "23c9b8f36ac1c0cddaf869c3733b771c3dc409416a9695df40397cea53e7f39e21f76925fc0c74ca6ee7c7eafad92473fd85758bab8f45fe01aac504";
private String[] serverAuthorityKeyPair;
private String[] manualContactTracingAuthorityKeyPair;
private int periodStartTime;
private Instant periodStartTime;
private LocationContact locationContact;
//@Mock
private LocationSpecificPart lsp;
......@@ -28,7 +29,7 @@ public class LocationTest {
CleaEciesEncoder cleaEciesEncoder = new CleaEciesEncoder();
serverAuthorityKeyPair = cleaEciesEncoder.genKeysPair(true);
manualContactTracingAuthorityKeyPair = cleaEciesEncoder.genKeysPair(true);