Attention une mise à jour du service Gitlab va être effectuée le mardi 30 novembre entre 17h30 et 18h00. Cette mise à jour va générer une interruption du service dont nous ne maîtrisons pas complètement la durée mais qui ne devrait pas excéder quelques minutes. Cette mise à jour intermédiaire en version 14.0.12 nous permettra de rapidement pouvoir mettre à votre disposition une version plus récente.

Commit 2f966ca5 authored by Cypres TAC's avatar Cypres TAC
Browse files

change SK_L size key in input json tests

parents 9f8ba9f8 62fcde6c
......@@ -3,7 +3,7 @@
#include <stdint.h>
#define SK_L_SIZE (60)
#define SK_L_SIZE (51)
/* Permanent location secret key, this key is not defined in the clea library itself,
it should be defined outside as it depends on the hardware specific storage location */
......
......@@ -3,7 +3,7 @@
#include <stdlib.h>
#include "clea.h"
uint8_t SK_L[SK_L_SIZE] = {17, 50, 178, 117, 142, 93, 11, 228, 16, 198, 218, 172, 28, 203, 30, 149, 105, 157, 195, 247, 12, 226, 62, 13, 255, 126, 84, 96, 87, 163, 80, 97, 213, 211, 66, 20, 248, 127, 9, 64, 84, 127, 135, 165, 127, 171, 14, 78, 34, 229, 223, 249, 156, 59, 123, 51, 153, 17, 250, 106};
uint8_t SK_L[SK_L_SIZE] = {17, 50, 178, 117, 142, 93, 11, 228, 16, 198, 218, 172, 28, 203, 30, 149, 105, 157, 195, 247, 12, 226, 62, 13, 255, 126, 84, 96, 87, 163, 80, 97, 213, 211, 66, 20, 248, 127, 9, 64, 84, 127, 135, 165, 127, 171, 14, 78, 34, 229, 223};
uint8_t PK_SA[PUBLIC_KEY_SIZE] = {0xbc, 0x05, 0x51, 0x56, 0x7e, 0xcc, 0x32, 0x77, 0x99, 0x8f, 0x4b, 0xa9, 0xaf, 0x0c, 0xa6, 0x35, 0xdd, 0xe3, 0x6b, 0xd2, 0x01, 0x55, 0x95, 0xbc, 0xab, 0xa2, 0x74, 0x0c, 0xcd, 0xc0, 0x6e, 0x7f, 0x78, 0x0d, 0x9e, 0xd2, 0xf4, 0x7f, 0xbc, 0xc5, 0xb4, 0xb4, 0x65, 0x49, 0x73, 0x3e, 0x2f, 0x9f, 0xb0, 0xf5, 0xc5, 0x86, 0x7a, 0x08, 0xec, 0xf6, 0x45, 0x16, 0xf9, 0x8d, 0x4c, 0x8a, 0x7e, 0xd5};
uint8_t PK_MCTA[PUBLIC_KEY_SIZE] = {0xbc, 0x05, 0x51, 0x56, 0x7e, 0xcc, 0x32, 0x77, 0x99, 0x8f, 0x4b, 0xa9, 0xaf, 0x0c, 0xa6, 0x35, 0xdd, 0xe3, 0x6b, 0xd2, 0x01, 0x55, 0x95, 0xbc, 0xab, 0xa2, 0x74, 0x0c, 0xcd, 0xc0, 0x6e, 0x7f, 0x78, 0x0d, 0x9e, 0xd2, 0xf4, 0x7f, 0xbc, 0xc5, 0xb4, 0xb4, 0x65, 0x49, 0x73, 0x3e, 0x2f, 0x9f, 0xb0, 0xf5, 0xc5, 0x86, 0x7a, 0x08, 0xec, 0xf6, 0x45, 0x16, 0xf9, 0x8d, 0x4c, 0x8a, 0x7e, 0xd5};
......
......@@ -13,7 +13,7 @@
#include "external_deps/time.h"
#include "clea.h"
uint8_t SK_L[SK_L_SIZE] = {17, 50, 178, 117, 142, 93, 11, 228, 16, 198, 218, 172, 28, 203, 30, 149, 105, 157, 195, 247, 12, 226, 62, 13, 255, 126, 84, 96, 87, 163, 80, 97, 213, 211, 66, 20, 248, 127, 9, 64, 84, 127, 135, 165, 127, 171, 14, 78, 34, 229, 223, 249, 156, 59, 123, 51, 153, 17, 250, 106};
uint8_t SK_L[SK_L_SIZE] = {17, 50, 178, 117, 142, 93, 11, 228, 16, 198, 218, 172, 28, 203, 30, 149, 105, 157, 195, 247, 12, 226, 62, 13, 255, 126, 84, 96, 87, 163, 80, 97, 213, 211, 66, 20, 248, 127, 9, 64, 84, 127, 135, 165, 127, 171, 14, 78, 34, 229, 223};
uint8_t PK_HA[PUBLIC_KEY_SIZE] = {0xbc, 0x05, 0x51, 0x56, 0x7e, 0xcc, 0x32, 0x77, 0x99, 0x8f, 0x4b, 0xa9, 0xaf, 0x0c, 0xa6, 0x35, 0xdd, 0xe3, 0x6b, 0xd2, 0x01, 0x55, 0x95, 0xbc, 0xab, 0xa2, 0x74, 0x0c, 0xcd, 0xc0, 0x6e, 0x7f, 0x78, 0x0d, 0x9e, 0xd2, 0xf4, 0x7f, 0xbc, 0xc5, 0xb4, 0xb4, 0x65, 0x49, 0x73, 0x3e, 0x2f, 0x9f, 0xb0, 0xf5, 0xc5, 0x86, 0x7a, 0x08, 0xec, 0xf6, 0x45, 0x16, 0xf9, 0x8d, 0x4c, 0x8a, 0x7e, 0xd5};
uint8_t PK_MCTA[PUBLIC_KEY_SIZE] = {0xbc, 0x05, 0x51, 0x56, 0x7e, 0xcc, 0x32, 0x77, 0x99, 0x8f, 0x4b, 0xa9, 0xaf, 0x0c, 0xa6, 0x35, 0xdd, 0xe3, 0x6b, 0xd2, 0x01, 0x55, 0x95, 0xbc, 0xab, 0xa2, 0x74, 0x0c, 0xcd, 0xc0, 0x6e, 0x7f, 0x78, 0x0d, 0x9e, 0xd2, 0xf4, 0x7f, 0xbc, 0xc5, 0xb4, 0xb4, 0x65, 0x49, 0x73, 0x3e, 0x2f, 0x9f, 0xb0, 0xf5, 0xc5, 0x86, 0x7a, 0x08, 0xec, 0xf6, 0x45, 0x16, 0xf9, 0x8d, 0x4c, 0x8a, 0x7e, 0xd5};
......
......@@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>fr.inria.clea</groupId>
<artifactId>clea-crypto</artifactId>
<version>0.0.1-SNAPSHOT</version>
<version>0.0.2-SNAPSHOT</version>
<dependencies>
<dependency>
......@@ -22,11 +22,23 @@
<artifactId>bcpkix-jdk15on</artifactId>
<version>1.68</version>
</dependency>
<!-- Bean validation -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>2.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.0.13.Final</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.el</artifactId>
<version>3.0.0</version>
</dependency>
<!-- end Bean validation -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
......
......@@ -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,10 @@ import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import fr.inria.clea.lsp.exception.CleaEncryptionException;
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 +61,7 @@ import org.bouncycastle.util.encoders.Hex;
* for Public-Key Encryption”, 2006</a>
*
*/
@Slf4j
public class CleaEciesEncoder {
/* Type of the elliptic curve */
......@@ -249,65 +255,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 +265,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 +307,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();
}
}
......@@ -9,6 +9,8 @@ import javax.validation.constraints.Max;
import org.bouncycastle.util.Arrays;
import fr.inria.clea.lsp.exception.CleaEncodingException;
import fr.inria.clea.lsp.exception.CleaEncryptionException;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
......
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 fr.inria.clea.lsp.exception.CleaCryptoException;
import fr.inria.clea.lsp.exception.CleaEncryptionException;
import lombok.Builder;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
......@@ -31,8 +34,8 @@ public class Location {
* @return the deep link as a String
* @throws CleaEncryptionException
*/
public String newDeepLink() throws CleaEncryptionException {
int periodStartTime = TimeUtils.hourRoundedCurrentTimeTimestamp32();
public String newDeepLink() throws CleaCryptoException {
Instant periodStartTime = Instant.now().truncatedTo(ChronoUnit.HOURS);
return this.newDeepLink(periodStartTime);
}
......@@ -41,14 +44,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 CleaCryptoException {
// QR-code validity starts at period start time
return this.newDeepLink(periodStartTime, periodStartTime);
}
......@@ -58,18 +58,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 CleaCryptoException {
this.setPeriodStartTime(periodStartTime);
this.setQrCodeValidityStartTime(periodStartTime, qrCodeValidityStartTime);
return COUNTRY_SPECIFIC_PREFIX + this.getLocationSpecificPartEncryptedBase64();
......@@ -80,22 +74,22 @@ public class Location {
* @return the base 64 encoded location specific part
* @throws CleaEncryptionException
*/
public String getLocationSpecificPartEncryptedBase64() throws CleaEncryptionException {
public String getLocationSpecificPartEncryptedBase64() throws CleaCryptoException {
return Base64.getEncoder().encodeToString(this.getLocationSpecificPartEncrypted());
}
protected byte[] getLocationSpecificPartEncrypted() throws CleaEncryptionException {
protected byte[] getLocationSpecificPartEncrypted() throws CleaCryptoException {
if (Objects.nonNull(this.contact)) {
this.locationSpecificPart.setEncryptedLocationContactMessage(this.getLocationContactMessageEncrypted());
}
return new LocationSpecificPartEncoder(this.serverAuthorityPublicKey).encode(locationSpecificPart);
}
protected byte[] getLocationContactMessageEncrypted() throws CleaEncryptionException {
protected byte[] getLocationContactMessageEncrypted() throws CleaCryptoException {
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 +98,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 javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.AccessLevel;
@Builder
@Getter
@EqualsAndHashCode
@ToString
public class LocationContact {
/* Phone number of the location contact person, one digit = one character, 15 digits max */
@Max(value = 15)
public static final String PHONE_VALIDATION_MESSAGE = "Location phone is mandatory";
public static final String REGION_VALIDATION_MESSAGE = "Location phone is mandatory";
public static final String PIN_VALIDATION_MESSAGE = "Secret digit PIN must contain exactly 6 characters";
public static final String PERIOD_START_TIME_VALIDATION_MESSAGE = "Period start time must not be null";
/* Phone number of the location contact person, one digit = one character */
@NotBlank(message= PHONE_VALIDATION_MESSAGE)
String locationPhone;
/* Coarse grain geographical information for the location */
@Max(value = 255)
/* Coarse grain geographical information for the location */
@Min(value = 0, message = REGION_VALIDATION_MESSAGE)
@Max(value = 255, message = REGION_VALIDATION_MESSAGE)
int locationRegion;
/* Secret 6 digit PIN, one digit = one character */
@Max(value = 6)
@Size(min = 6, max = 6,
message = PIN_VALIDATION_MESSAGE)
String locationPin;
/* Starting time of the period in seconds */
@NotNull(message= PERIOD_START_TIME_VALIDATION_MESSAGE)
@Setter(AccessLevel.PROTECTED)
int periodStartTime;
}
Instant periodStartTime;
}
\ No newline at end of file
......@@ -5,24 +5,38 @@ import java.security.InvalidAlgorithmParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidKeySpecException;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.bouncycastle.crypto.InvalidCipherTextException;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.exception.CleaCryptoException;
import fr.inria.clea.lsp.exception.CleaEncryptionException;
import fr.inria.clea.lsp.exception.CleaInvalidLocationContactMessageException;
import fr.inria.clea.lsp.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LocationContactMessageEncoder {
private String manualContactTracingAuthorityPublicKey;
private CleaEciesEncoder cleaEncoder;
private Validator validator;
public LocationContactMessageEncoder(String manualContactTracingAuthorityPublicKey) {
super();
this.manualContactTracingAuthorityPublicKey = manualContactTracingAuthorityPublicKey;
cleaEncoder = new CleaEciesEncoder();
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
public byte[] encode(LocationContact message) throws CleaEncryptionException {
public byte[] encode(LocationContact message) throws CleaCryptoException {
this.validateMessage(message);
try {
byte[] messageBinary = this.getBinaryMessage(message);
byte[] encryptedLocationContactMessage = cleaEncoder.encrypt(null, messageBinary, manualContactTracingAuthorityPublicKey);
......@@ -36,6 +50,16 @@ public class LocationContactMessageEncoder {
throw new CleaEncryptionException(e);
}
}
protected void validateMessage(LocationContact message) throws CleaInvalidLocationContactMessageException {
Set<ConstraintViolation<LocationContact>> violations = validator.validate(message);
for (ConstraintViolation<LocationContact> violation : violations) {
log.error(violation.getMessage());
}
if (!violations.isEmpty()) {
throw new CleaInvalidLocationContactMessageException(violations);
}
}
/**
* Encode the data locContactMsg in binary format:
......@@ -73,7 +97,8 @@ public class LocationContactMessageEncoder {
}
/* t_periodStart (32 bits) */
locationContactMessage.setNextInteger(message.getPeriodStartTime(), 32);
long periodStartTime = TimeUtils.ntpTimestampFromInstant(message.getPeriodStartTime());
locationContactMessage.setNextLong(periodStartTime, 32);
return locationContactMessage.getData();
}
......@@ -83,7 +108,7 @@ public class LocationContactMessageEncoder {
* | locationPhone | locationPIN | t_periodStart |
* @throws CleaEncryptionException
*/
public LocationContact decode(byte[] encryptedLocationContactMessage) throws CleaEncryptionException {
public LocationContact decode(byte[] encryptedLocationContactMessage) throws CleaCryptoException {
try {
/* Decrypt the data */
byte[] binaryLocationContactMessage = cleaEncoder.decrypt(encryptedLocationContactMessage, this.manualContactTracingAuthorityPublicKey , false);
......@@ -118,9 +143,13 @@ public class LocationContactMessageEncoder {
}
/* t_periodStart (32 bits) */
int periodStartTime = bitLocationContactMessage.getNextInteger(32);
long periodStartTime = bitLocationContactMessage.getNextLong(32);
LocationContact locationContact = new LocationContact(locationPhone.toString(),
locationRegion, locationPin.toString(), TimeUtils.instantFromTimestamp(periodStartTime));
this.validateMessage(locationContact);
return locationContact;
return new LocationContact(locationPhone.toString(), locationRegion, locationPin.toString(), periodStartTime);
} catch (NoSuchAlgorithmException | InvalidKeySpecException | IllegalStateException | InvalidCipherTextException
| IOException e) {
throw new CleaEncryptionException(e);
......
package fr.inria.clea.lsp;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import fr.inria.clea.lsp.exception.CleaInvalidLocationContactMessageException;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class LocationContactValidator {
private Validator validator;
public LocationContactValidator() {
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
validator = factory.getValidator();
}
protected void validateMessage(LocationContact message) throws CleaInvalidLocationContactMessageException {
Set<ConstraintViolation<LocationContact>> violations = validator.validate(message);
for (ConstraintViolation<LocationContact> violation : violations) {
log.error(violation.getMessage());
}
if (!violations.isEmpty()) {
throw new CleaInvalidLocationContactMessageException(violations);
}
}
}
......@@ -3,10 +3,14 @@
*/
package fr.inria.clea.lsp;
import java.time.Instant;
import java.util.Objects;
import java.util.UUID;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;