Payload Code Snippets
Prepare and process NHCX JWE payloads with reference Java snippets.
Use these snippets as a reference when you prepare an NHCX encrypted payload. Prepare the FHIR bundle from the correct NRCES profile first. Then add a protected header and encrypt the bundle.
Certificate cache
Store the receiver public certificate locally.
Do not call /fetch/certs for each payload.
Refresh the certificate cache on a planned schedule.
Payload parts
An NHCX JWE payload has 2 parts. Separate the parts with a dot in the serialized JWE value.
| Part | Description |
|---|---|
| Protected header | Contains NHCX routing, workflow, and crypto parameters. |
| FHIR bundle | Contains the encrypted FHIR bundle for the use case. |
Protected header
{
"alg": "RSA-OAEP-256",
"enc": "A256GCM",
"x-hcx-api_call_id": "bbea0ea1-2750-4ec8-8974-d3edc7030913",
"x-hcx-workflow_id": "1",
"x-hcx-request_id": "1113f541-6387-4c2a-ad3e-4bebc5a9fe36",
"x-hcx-status": "request.initiated",
"x-hcx-timestamp": "2023-08-02T14:57:40+0530",
"x-hcx-sender_code": "1000000046@sbx",
"x-hcx-recipient_code": "1000000109@sbx",
"x-hcx-correlation_id": "3a2ba13b-04f5-4943-9b50-a1334e55c90e"
}Base64url encode the protected header before you place it in the payload. Use the mandatory header list in Requests and Responses.
Encrypt a payload
Pass the protected headers, the FHIR bundle, and the receiver certificate path. Use the receiver public key for encryption.
private String encryptPayload(
Map<String, Object> headers,
Map<String, Object> payloadMain,
String certificatePath) {
logger.info("-- Encrypting payload --");
JWEPayloadUtil jweRequest = new JWEPayloadUtil();
try {
String encryptedMsg = jweRequest.encryptRequestNew(
KeyLoader.loadPublicKeyFromX509Certificate(new File(certificatePath)),
headers,
payloadMain);
logger.info(String.format("-- Encrypted Payload --> %s", encryptedMsg));
logger.info("-- Payload encrypted successfully --");
return encryptedMsg;
} catch (CertificateException | JOSEException | IOException e) {
e.printStackTrace();
logger.info("-- Error while encrypting payload --");
return null;
}
}Build the JWE object
Use RSA-OAEP-256 for key management.
Use A256GCM for content encryption.
public static final JWEAlgorithm KEY_MANAGEMENT_ALGORITHM = JWEAlgorithm.RSA_OAEP_256;
public static final EncryptionMethod CONTENT_ENCRYPTION_ALGORITHM = EncryptionMethod.A256GCM;
public static final EncryptionMethod CONTENT_DECRYPTION_ALGORITHM = EncryptionMethod.A256GCM;
public String encryptRequestNew(
RSAPublicKey rsaPublicKey,
Map<String, Object> headers,
Map<String, Object> payload) throws JOSEException {
JWEHeader jweHeader = new JWEHeader.Builder(
KEY_MANAGEMENT_ALGORITHM,
CONTENT_ENCRYPTION_ALGORITHM)
.customParams(headers)
.build();
Payload jwePayload = new Payload(payload);
JWEObject jweObject = new JWEObject(jweHeader, jwePayload);
RSAEncrypter rsaEncrypter = new RSAEncrypter(rsaPublicKey);
jweObject.encrypt(rsaEncrypter);
return jweObject.serialize();
}Load the public key
Read the X.509 certificate from a PEM file. Return the public key as an RSA key.
public static RSAPublicKey loadPublicKeyFromX509Certificate(File publicKeyFile)
throws IOException, CertificateException {
FileReader fileReader = new FileReader(publicKeyFile);
try (PemReader pemReader = new PemReader(fileReader)) {
PemObject pemObject = pemReader.readPemObject();
CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
X509Certificate x509Certificate = (X509Certificate) certificateFactory
.generateCertificate(new ByteArrayInputStream(pemObject.getContent()));
return (RSAPublicKey) x509Certificate.getPublicKey();
}
}Decrypt a payload
Use the receiver private key for decryption. Read the JWE parts from the encrypted object map.
public Map<String, Object> decryptRequest(
RSAPrivateKey rsaPrivateKey,
Map<String, String> encryptedObject) throws ParseException, JOSEException {
JWEObject jweObject = new JWEObject(
new Base64URL(encryptedObject.get("protected")),
new Base64URL(encryptedObject.get("encrypted_key")),
new Base64URL(encryptedObject.get("iv")),
new Base64URL(encryptedObject.get("ciphertext")),
new Base64URL(encryptedObject.get("tag")));
JWEDecrypter jweDecrypter = new RSADecrypter(rsaPrivateKey);
jweObject.decrypt(jweDecrypter);
return new HashMap<>(jweObject.getPayload().toJSONObject());
}Sources
- code-snippets-payload-preparation.md (NHCX sandbox portal)