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

introduce EncryptedLocationSpecificPart to allow read of header without decrypt the whole message.

parent e9481397
Pipeline #227555 passed with stage
in 1 minute and 47 seconds
/*
* Copyright (C) Inria, 2021
*/
package fr.inria.clea.lsp;
import java.util.Arrays;
import java.util.UUID;
import javax.validation.constraints.Max;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.LocationSpecificPart.LocationSpecificPartBuilder;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
/**
* LocationSpecificPart (LSP) contents data respecting the CLEA protocol
*
* @see <a href="https://hal.inria.fr/hal-03146022">CLEA protocol</a>
*/
@Builder
@Getter
@EqualsAndHashCode
@ToString
public class EncryptedLocationSpecificPart {
/* Clea protocol version number */
@Builder.Default
@Max(value = 8)
private int version = 0;
/*
* LSP type, in order to be able to use multiple formats in parallel in the
* future.
*/
@Builder.Default
@Max(value = 8)
private int type = 0;
/*
* Location Temporary public universally unique Identifier (UUID), specific to a
* given location at a given period.
*/
private UUID locationTemporaryPublicId;
/*
* Location Specific Part in binary format without the Header (non-encrypted data) and encrypted.
*/
private byte[] encryptedLocationMessage;
/**
* Unpack the data message (binary format) :
* | Staff | pad2 |CRIexp | vType |
* vCat1 | vCat2 | countryCode | | periodDuration | ct_periodStart | t_qrStart |
* LTKey | to extract parameters
*/
public LocationSpecificPart decodeMessage() {
byte[] messageBinary = Arrays.copyOfRange(encryptedLocationMessage, 0, CleaEciesEncoder.MSG_BYTES_SIZE);
BitUtils message = new BitUtils(messageBinary);
byte[] encryptedLocationContactMessage = Arrays.copyOfRange(encryptedLocationMessage,
CleaEciesEncoder.MSG_BYTES_SIZE, encryptedLocationMessage.length);
if (encryptedLocationContactMessage.length == 0) {
encryptedLocationContactMessage = null;
}
LocationSpecificPartBuilder locationSpecificPartbuilder = LocationSpecificPart.builder()
.version(version)
.type(type)
.locationTemporaryPublicId(locationTemporaryPublicId)
.staff(message.getNextInteger(1) == 1);
message.getNextInteger(1); // skip locationContactMessagePresent
locationSpecificPartbuilder
.countryCode(message.getNextInteger(12))
.qrCodeRenewalIntervalExponentCompact(message.getNextInteger(5))
.venueType(message.getNextInteger(5))
.venueCategory1(message.getNextInteger(4))
.venueCategory2(message.getNextInteger(4))
.periodDuration(message.getNextInteger(8))
.compressedPeriodStartTime(message.getNextInteger(24))
.qrCodeValidityStartTime(message.getNextInteger(32))
.locationTemporarySecretKey(message.getNextByte(256))
.encryptedLocationContactMessage(encryptedLocationContactMessage);
return locationSpecificPartbuilder.build();
}
}
......@@ -12,11 +12,11 @@ import java.util.Base64;
import org.bouncycastle.crypto.InvalidCipherTextException;
import fr.devnied.bitlib.BitUtils;
import fr.inria.clea.lsp.LocationSpecificPart.LocationSpecificPartBuilder;
import fr.inria.clea.lsp.EncryptedLocationSpecificPart.EncryptedLocationSpecificPartBuilder;
import lombok.extern.slf4j.Slf4j;
/**
* locationSpecificPart (LSP) contents reader respecting the CLEA protocol
* LocationSpecificPart (LSP) contents reader respecting the CLEA protocol
*
* @see <a href="https://hal.inria.fr/hal-03146022">CLEA protocol</a>
*/
......@@ -33,48 +33,14 @@ public class LocationSpecificPartDecoder {
}
/**
* Unpack the data message (binary format) :
* | Staff | pad2 |CRIexp | vType |
* vCat1 | vCat2 | countryCode | | periodDuration | ct_periodStart | t_qrStart |
* LTKey | to extract parameters
* Unpack the data decrypted header (binary format):
* | version | LSPtype | pad | LTId | to extract parameters
*/
private LocationSpecificPart decodeMessage(byte[] binaryLocationSpecificPart) {
byte[] messageBinary = Arrays.copyOfRange(binaryLocationSpecificPart, CleaEciesEncoder.HEADER_BYTES_SIZE,
CleaEciesEncoder.HEADER_BYTES_SIZE + CleaEciesEncoder.MSG_BYTES_SIZE);
BitUtils message = new BitUtils(messageBinary);
byte[] encryptedLocationContactMessage = Arrays.copyOfRange(binaryLocationSpecificPart,
CleaEciesEncoder.HEADER_BYTES_SIZE + CleaEciesEncoder.MSG_BYTES_SIZE, binaryLocationSpecificPart.length);
if (encryptedLocationContactMessage.length == 0) {
encryptedLocationContactMessage = null;
}
LocationSpecificPartBuilder locationSpecificPartbuilder = LocationSpecificPart.builder()
.staff(message.getNextInteger(1) == 1);
message.getNextInteger(1); // skip locationContactMessagePresent
locationSpecificPartbuilder
.countryCode(message.getNextInteger(12))
.qrCodeRenewalIntervalExponentCompact(message.getNextInteger(5))
.venueType(message.getNextInteger(5))
.venueCategory1(message.getNextInteger(4))
.venueCategory2(message.getNextInteger(4))
.periodDuration(message.getNextInteger(8))
.compressedPeriodStartTime(message.getNextInteger(24))
.qrCodeValidityStartTime(message.getNextInteger(32))
.locationTemporarySecretKey(message.getNextByte(256))
.encryptedLocationContactMessage(encryptedLocationContactMessage);
this.setHeader(binaryLocationSpecificPart, locationSpecificPartbuilder);
return locationSpecificPartbuilder.build();
}
/**
* Unpack the data decrypted header (binary format): | version | LSPtype | pad |
* LTId | to extract parameters
*/
private void setHeader(byte[] binaryLocationSpecificPart, LocationSpecificPartBuilder locationSpecificPartbuilder) {
private EncryptedLocationSpecificPart decodeHeader(byte[] binaryLocationSpecificPart) {
byte[] headerBinary = Arrays.copyOfRange(binaryLocationSpecificPart, 0, CleaEciesEncoder.HEADER_BYTES_SIZE);
BitUtils header = new BitUtils(headerBinary);
locationSpecificPartbuilder
EncryptedLocationSpecificPartBuilder builder = EncryptedLocationSpecificPart.builder()
.version(header.getNextInteger(3))
.type(header.getNextInteger(3));
/* padding (2 bits) */
......@@ -83,7 +49,11 @@ public class LocationSpecificPartDecoder {
/* LTId (16 bytes) */
byte[] uuidBinary = new byte[16];
uuidBinary = header.getNextByte(128);
locationSpecificPartbuilder.locationTemporaryPublicId(this.cleaEciesEncoder.bytesToUuid(uuidBinary));
builder.locationTemporaryPublicId(this.cleaEciesEncoder.bytesToUuid(uuidBinary));
byte[] messageBinary = Arrays.copyOfRange(binaryLocationSpecificPart, CleaEciesEncoder.HEADER_BYTES_SIZE,
binaryLocationSpecificPart.length);
builder.encryptedLocationMessage(messageBinary);
return builder.build();
}
/**
......@@ -92,7 +62,7 @@ public class LocationSpecificPartDecoder {
* @param lspBase64 Location Specific Part in base64
* @throws CleaEncryptionException
*/
public LocationSpecificPart decrypt(String lspBase64) throws CleaEncryptionException {
public EncryptedLocationSpecificPart decrypt(String lspBase64) throws CleaEncryptionException {
byte[] encryptedLocationSpecificPart = Base64.getDecoder().decode(lspBase64);
log.debug("Base 64 decoded LSP: {}", encryptedLocationSpecificPart);
byte[] binaryLocationSpecificPart;
......@@ -102,6 +72,7 @@ public class LocationSpecificPartDecoder {
| IOException e) {
throw new CleaEncryptionException(e);
}
return this.decodeMessage(binaryLocationSpecificPart);
return this.decodeHeader(binaryLocationSpecificPart);
//this.decodeMessage(binaryLocationSpecificPart);
}
}
......@@ -32,7 +32,7 @@ public class LspEncoderDecoder {
String serverAuthoritySecretKey = args[2];
String manualContactTracingAuthoritySecretKey = args[3];
LocationSpecificPartDecoder lspDecoder = new LocationSpecificPartDecoder(serverAuthoritySecretKey);
LocationSpecificPart lsp = lspDecoder.decrypt(lspBase64);
LocationSpecificPart lsp = lspDecoder.decrypt(lspBase64).decodeMessage();
String valuesToreturn = (lsp.isStaff()? 1 : 0) + " " + lsp.getCountryCode() + " " + lsp.getQrCodeRenewalIntervalExponentCompact() + " " + lsp.getVenueType();
valuesToreturn += " " + lsp.getVenueCategory1() + " " + lsp.getVenueCategory2() + " " + lsp.getPeriodDuration() + " " + lsp.getLocationTemporaryPublicId();
......
......@@ -145,7 +145,8 @@ class LocationSpecificPartTest {
String encryptedLocationSpecificPart = location.getLocationSpecificPartEncryptedBase64();
assertThat(encryptedLocationSpecificPart).isNotNull();
/* Decode the encoded LSP */
LocationSpecificPart decodedLsp = new LocationSpecificPartDecoder(serverAuthorityKeyPair[0]).decrypt(encryptedLocationSpecificPart);
LocationSpecificPart decodedLsp = new LocationSpecificPartDecoder(serverAuthorityKeyPair[0])
.decrypt(encryptedLocationSpecificPart).decodeMessage();
assertThat(decodedLsp).isEqualTo(lsp);
assertThat(lsp.getEncryptedLocationContactMessage()).isNotNull();
......@@ -175,7 +176,8 @@ class LocationSpecificPartTest {
/* Encode a LSP with location */
String encryptedLocationSpecificPart = location.getLocationSpecificPartEncryptedBase64();
/* Decode the encoded LSP */
LocationSpecificPart decodedLsp = new LocationSpecificPartDecoder(serverAuthorityKeyPair[0]).decrypt(encryptedLocationSpecificPart);
LocationSpecificPart decodedLsp = new LocationSpecificPartDecoder(serverAuthorityKeyPair[0])
.decrypt(encryptedLocationSpecificPart).decodeMessage();
assertThat(decodedLsp).isEqualTo(lsp);
}
......@@ -258,7 +260,7 @@ class LocationSpecificPartTest {
LocationSpecificPartDecoder decoder = new LocationSpecificPartDecoder(servertAuthoritySecretKey);
LocationSpecificPart lsp = decoder.decrypt(lsp_base64);
LocationSpecificPart lsp = decoder.decrypt(lsp_base64).decodeMessage();
assertThat(lsp.isStaff()).isEqualTo(false);
assertThat(lsp.getCountryCode()).isEqualTo(492);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment