{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# FHIR Digitally Signing FHIR Bundle Object\n", "\n", "This is a Jupyter Notebook using Python 3.7 and openSSl to create JSON Web Signature (JWS)(see RFC 7515) and attach it to a FHIR Bundle. \n", "\n", "See enveloped signatures: http://build.fhir.org/signatures.html\n", "\n", "*Although self-signed certificates are used for the purpose of these examples, they are not recommended for production systems.*" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Sender/Signer Steps" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 1. Generate RSA256 public and private keys for signing the bundle\n", "\n", "**DO THIS STEP ONLY ONCE-**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 2. Create a sef-signed certificate for authenticating the signer\n", "\n", "create the public and private keys and cert using openssl on the command line.\n", "\n", "1. pre-configure the self-signed cert with a configuration file\n", "\n", "~~~\n", "[req]\n", "default_bit = 4096\n", "distinguished_name = req_distinguished_name\n", "prompt = no\n", "x509_extensions = v3_ca\n", "\n", "[req_distinguished_name]\n", "countryName = US\n", "stateOrProvinceName = California\n", "localityName = Sausalito\n", "organizationName = HealtheData1\n", "commonName = Eric Haas, DVM\n", "emailAddress = ehaas@healthedata1.org\n", "\n", "[v3_ca]\n", "basicConstraints = CA:TRUE\n", "keyUsage=nonRepudiation, digitalSignature, keyEncipherment\n", "subjectAltName = @alt_names\n", "\n", "[alt_names]\n", "DNS.1 = www.healthedatainc.com\n", "~~~" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "2\\. generate the public and private keys and cert\n", "\n", "~~~\n", "!openssl genrsa -out private-key.pem 3072\n", "!openssl rsa -in private-key.pem -pubout -out public-key.pem\n", "!openssl req -new -x509 -key private-key.pem -outform DER -out cert.der -days 360 -config cert.config\n", "~~~" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### For the purpose of this example display the keys (normally would never share the private key)" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-----BEGIN RSA PRIVATE KEY-----\n", "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\n", "-----END RSA PRIVATE KEY-----\n", "\n", "-----BEGIN PUBLIC KEY-----\n", "MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA6SnEpKADOrFttfr1k3iF\n", "ThsddDFmrEMu1R4nes8qlwATPs53wZ13p8lNI9RU7z5kXzg6Dg11bj1MA6JoQh4f\n", "m3JVvSjNqOet3MUShLwZ2h67I8OcjZsTuWIxEW4bR3UHqpLXcN1WBEUfR6MSztxZ\n", "LM0dvdh0weMVt8lpVd4E5DEKMz0nCSh92xvD6qugGDyewuGASJVEnQTFZd6p3hH4\n", "O37sYhX16H3U1Zu6zIohu1/c+Nz34pamnorH5rUcQJUcBDV6x9zrzgz8i9K05xvA\n", "rGwF2FSDJnXR3uGRfaZYfebI+KTE4S7XCV/6PVxy44exJmcoCR1hEKuD8BcGXZm3\n", "H4Qpjq/PB/AW1K7v+1es27BtTdQlpZ3ZW1c5y/tyDDq/JF2h3Gp6n3JIBVeBK534\n", "xSatTiGgJrDI/OcTJI8ly8nCy/7uZ9qOgYPd/1EX6rjqEiBjgkduQ2mc6cNpN7O6\n", "BPXTMBFl7X14GLYdm5Y8ubRR9Bo6TpMdO4+2U+R58Z5bAgMBAAE=\n", "-----END PUBLIC KEY-----\n" ] } ], "source": [ "!cat private-key.pem\n", "!echo\n", "!cat public-key.pem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Show the Certificate in DER Format" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Certificate:\n", " Data:\n", " Version: 3 (0x2)\n", " Serial Number: 16322561221100825744 (0xe28562f33047ec90)\n", " Signature Algorithm: sha256WithRSAEncryption\n", " Issuer: C=US, ST=California, L=Sausalito, O=HealtheData1, CN=Eric Haas, DVM/emailAddress=ehaas@healthedata1.org\n", " Validity\n", " Not Before: Oct 27 17:42:04 2021 GMT\n", " Not After : Oct 22 17:42:04 2022 GMT\n", " Subject: C=US, ST=California, L=Sausalito, O=HealtheData1, CN=Eric Haas, DVM/emailAddress=ehaas@healthedata1.org\n", " Subject Public Key Info:\n", " Public Key Algorithm: rsaEncryption\n", " Public-Key: (3072 bit)\n", " Modulus:\n", " 00:e9:29:c4:a4:a0:03:3a:b1:6d:b5:fa:f5:93:78:\n", " 85:4e:1b:1d:74:31:66:ac:43:2e:d5:1e:27:7a:cf:\n", " 2a:97:00:13:3e:ce:77:c1:9d:77:a7:c9:4d:23:d4:\n", " 54:ef:3e:64:5f:38:3a:0e:0d:75:6e:3d:4c:03:a2:\n", " 68:42:1e:1f:9b:72:55:bd:28:cd:a8:e7:ad:dc:c5:\n", " 12:84:bc:19:da:1e:bb:23:c3:9c:8d:9b:13:b9:62:\n", " 31:11:6e:1b:47:75:07:aa:92:d7:70:dd:56:04:45:\n", " 1f:47:a3:12:ce:dc:59:2c:cd:1d:bd:d8:74:c1:e3:\n", " 15:b7:c9:69:55:de:04:e4:31:0a:33:3d:27:09:28:\n", " 7d:db:1b:c3:ea:ab:a0:18:3c:9e:c2:e1:80:48:95:\n", " 44:9d:04:c5:65:de:a9:de:11:f8:3b:7e:ec:62:15:\n", " f5:e8:7d:d4:d5:9b:ba:cc:8a:21:bb:5f:dc:f8:dc:\n", " f7:e2:96:a6:9e:8a:c7:e6:b5:1c:40:95:1c:04:35:\n", " 7a:c7:dc:eb:ce:0c:fc:8b:d2:b4:e7:1b:c0:ac:6c:\n", " 05:d8:54:83:26:75:d1:de:e1:91:7d:a6:58:7d:e6:\n", " c8:f8:a4:c4:e1:2e:d7:09:5f:fa:3d:5c:72:e3:87:\n", " b1:26:67:28:09:1d:61:10:ab:83:f0:17:06:5d:99:\n", " b7:1f:84:29:8e:af:cf:07:f0:16:d4:ae:ef:fb:57:\n", " ac:db:b0:6d:4d:d4:25:a5:9d:d9:5b:57:39:cb:fb:\n", " 72:0c:3a:bf:24:5d:a1:dc:6a:7a:9f:72:48:05:57:\n", " 81:2b:9d:f8:c5:26:ad:4e:21:a0:26:b0:c8:fc:e7:\n", " 13:24:8f:25:cb:c9:c2:cb:fe:ee:67:da:8e:81:83:\n", " dd:ff:51:17:ea:b8:ea:12:20:63:82:47:6e:43:69:\n", " 9c:e9:c3:69:37:b3:ba:04:f5:d3:30:11:65:ed:7d:\n", " 78:18:b6:1d:9b:96:3c:b9:b4:51:f4:1a:3a:4e:93:\n", " 1d:3b:8f:b6:53:e4:79:f1:9e:5b\n", " Exponent: 65537 (0x10001)\n", " X509v3 extensions:\n", " X509v3 Basic Constraints: \n", " CA:TRUE\n", " X509v3 Key Usage: \n", " Digital Signature, Non Repudiation, Key Encipherment\n", " X509v3 Subject Alternative Name: \n", " DNS:www.healthedatainc.com\n", " Signature Algorithm: sha256WithRSAEncryption\n", " 0a:e3:14:36:af:5a:cb:ef:9e:e5:80:bb:40:53:bd:e2:b7:f3:\n", " c4:64:27:17:71:a4:95:93:40:5e:62:2b:ec:f5:46:76:21:98:\n", " d8:64:f1:ff:d4:6d:1c:2c:13:2b:39:0b:fb:2b:ca:a2:37:99:\n", " f5:d5:4a:f3:0a:c6:56:24:64:3b:f8:d4:c9:9f:8a:71:64:68:\n", " 91:48:ec:e7:d9:dc:24:64:4c:49:24:71:b5:e0:90:ba:3b:78:\n", " 85:fd:be:fe:a5:7e:7f:6b:0c:42:d1:2b:c0:f1:37:d2:f6:ea:\n", " 45:85:0d:34:d0:55:11:0a:5a:43:1f:da:70:90:d4:bf:db:fb:\n", " b2:31:e2:24:3a:97:c1:0f:ab:ce:3f:79:88:70:08:69:e1:07:\n", " a8:5f:cc:b3:6d:a9:d9:b7:99:ba:ab:c8:40:a7:8c:97:eb:2f:\n", " 56:a1:ed:8a:ec:d6:9c:5e:14:e9:52:26:a6:4a:f8:6c:79:7b:\n", " 7a:05:7d:1f:a9:7a:4f:64:8c:92:3e:aa:0d:4e:5e:f4:d8:34:\n", " 66:52:d3:b6:8b:2c:84:12:e6:a2:91:7b:7b:b1:f2:ad:31:00:\n", " 99:f3:8f:29:07:b4:12:0f:44:da:ea:f3:c6:a0:6e:1b:9e:24:\n", " e7:41:b6:27:41:62:3e:c4:09:02:11:62:34:6c:12:83:84:b7:\n", " 1f:25:43:1b:bb:9e:29:dd:0b:f7:7c:0a:38:d3:98:1a:f3:0a:\n", " 8b:30:87:07:ea:4a:bc:43:09:a1:9f:32:f6:e8:81:f8:71:57:\n", " 72:9f:51:68:9a:89:f7:b1:e9:65:31:2f:fa:58:82:a7:63:d2:\n", " 5f:37:0a:d2:bd:b9:49:cc:a3:17:a7:4b:a2:e2:b6:48:1d:f4:\n", " c4:0b:c9:f2:d1:39:f3:8f:a3:a9:0e:82:19:e7:14:f5:78:ef:\n", " 94:08:ee:25:d0:ab:0d:e5:4f:b2:39:27:ec:e3:d7:1b:ef:17:\n", " 65:4e:f3:a8:76:4d:99:75:f5:61:8e:07:e6:b8:04:27:8f:25:\n", " ad:4a:cf:dc:8f:11\n", "-----BEGIN CERTIFICATE-----\n", "MIIE3zCCA0egAwIBAgIJAOKFYvMwR+yQMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD\n", "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU2F1c2FsaXRv\n", "MRUwEwYDVQQKDAxIZWFsdGhlRGF0YTExFzAVBgNVBAMMDkVyaWMgSGFhcywgRFZN\n", "MSUwIwYJKoZIhvcNAQkBFhZlaGFhc0BoZWFsdGhlZGF0YTEub3JnMB4XDTIxMTAy\n", "NzE3NDIwNFoXDTIyMTAyMjE3NDIwNFowgY0xCzAJBgNVBAYTAlVTMRMwEQYDVQQI\n", "DApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTYXVzYWxpdG8xFTATBgNVBAoMDEhlYWx0\n", "aGVEYXRhMTEXMBUGA1UEAwwORXJpYyBIYWFzLCBEVk0xJTAjBgkqhkiG9w0BCQEW\n", "FmVoYWFzQGhlYWx0aGVkYXRhMS5vcmcwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw\n", "ggGKAoIBgQDpKcSkoAM6sW21+vWTeIVOGx10MWasQy7VHid6zyqXABM+znfBnXen\n", "yU0j1FTvPmRfODoODXVuPUwDomhCHh+bclW9KM2o563cxRKEvBnaHrsjw5yNmxO5\n", "YjERbhtHdQeqktdw3VYERR9HoxLO3FkszR292HTB4xW3yWlV3gTkMQozPScJKH3b\n", "G8Pqq6AYPJ7C4YBIlUSdBMVl3qneEfg7fuxiFfXofdTVm7rMiiG7X9z43Pfilqae\n", "isfmtRxAlRwENXrH3OvODPyL0rTnG8CsbAXYVIMmddHe4ZF9plh95sj4pMThLtcJ\n", "X/o9XHLjh7EmZygJHWEQq4PwFwZdmbcfhCmOr88H8BbUru/7V6zbsG1N1CWlndlb\n", "VznL+3IMOr8kXaHcanqfckgFV4ErnfjFJq1OIaAmsMj85xMkjyXLycLL/u5n2o6B\n", "g93/URfquOoSIGOCR25DaZzpw2k3s7oE9dMwEWXtfXgYth2bljy5tFH0GjpOkx07\n", "j7ZT5HnxnlsCAwEAAaNAMD4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCBeAwIQYD\n", "VR0RBBowGIIWd3d3LmhlYWx0aGVkYXRhaW5jLmNvbTANBgkqhkiG9w0BAQsFAAOC\n", "AYEACuMUNq9ay++e5YC7QFO94rfzxGQnF3GklZNAXmIr7PVGdiGY2GTx/9RtHCwT\n", "KzkL+yvKojeZ9dVK8wrGViRkO/jUyZ+KcWRokUjs59ncJGRMSSRxteCQujt4hf2+\n", "/qV+f2sMQtErwPE30vbqRYUNNNBVEQpaQx/acJDUv9v7sjHiJDqXwQ+rzj95iHAI\n", "aeEHqF/Ms22p2beZuqvIQKeMl+svVqHtiuzWnF4U6VImpkr4bHl7egV9H6l6T2SM\n", "kj6qDU5e9Ng0ZlLTtosshBLmopF7e7HyrTEAmfOPKQe0Eg9E2urzxqBuG54k50G2\n", "J0FiPsQJAhFiNGwSg4S3HyVDG7ueKd0L93wKONOYGvMKizCHB+pKvEMJoZ8y9uiB\n", "+HFXcp9RaJqJ97HpZTEv+liCp2PSXzcK0r25ScyjF6dLouK2SB30xAvJ8tE584+j\n", "qQ6CGecU9XjvlAjuJdCrDeVPsjkn7OPXG+8XZU7zqHZNmXX1YY4H5rgEJ48lrUrP\n", "3I8R\n", "-----END CERTIFICATE-----\n" ] } ], "source": [ "!openssl x509 -in cert.der -inform DER -text" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "##### Show the Certicate in PEM format" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "-----BEGIN CERTIFICATE-----\n", "MIIE3zCCA0egAwIBAgIJAOKFYvMwR+yQMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD\n", "VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU2F1c2FsaXRv\n", "MRUwEwYDVQQKDAxIZWFsdGhlRGF0YTExFzAVBgNVBAMMDkVyaWMgSGFhcywgRFZN\n", "MSUwIwYJKoZIhvcNAQkBFhZlaGFhc0BoZWFsdGhlZGF0YTEub3JnMB4XDTIxMTAy\n", "NzE3NDIwNFoXDTIyMTAyMjE3NDIwNFowgY0xCzAJBgNVBAYTAlVTMRMwEQYDVQQI\n", "DApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTYXVzYWxpdG8xFTATBgNVBAoMDEhlYWx0\n", "aGVEYXRhMTEXMBUGA1UEAwwORXJpYyBIYWFzLCBEVk0xJTAjBgkqhkiG9w0BCQEW\n", "FmVoYWFzQGhlYWx0aGVkYXRhMS5vcmcwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAw\n", "ggGKAoIBgQDpKcSkoAM6sW21+vWTeIVOGx10MWasQy7VHid6zyqXABM+znfBnXen\n", "yU0j1FTvPmRfODoODXVuPUwDomhCHh+bclW9KM2o563cxRKEvBnaHrsjw5yNmxO5\n", "YjERbhtHdQeqktdw3VYERR9HoxLO3FkszR292HTB4xW3yWlV3gTkMQozPScJKH3b\n", "G8Pqq6AYPJ7C4YBIlUSdBMVl3qneEfg7fuxiFfXofdTVm7rMiiG7X9z43Pfilqae\n", "isfmtRxAlRwENXrH3OvODPyL0rTnG8CsbAXYVIMmddHe4ZF9plh95sj4pMThLtcJ\n", "X/o9XHLjh7EmZygJHWEQq4PwFwZdmbcfhCmOr88H8BbUru/7V6zbsG1N1CWlndlb\n", "VznL+3IMOr8kXaHcanqfckgFV4ErnfjFJq1OIaAmsMj85xMkjyXLycLL/u5n2o6B\n", "g93/URfquOoSIGOCR25DaZzpw2k3s7oE9dMwEWXtfXgYth2bljy5tFH0GjpOkx07\n", "j7ZT5HnxnlsCAwEAAaNAMD4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCBeAwIQYD\n", "VR0RBBowGIIWd3d3LmhlYWx0aGVkYXRhaW5jLmNvbTANBgkqhkiG9w0BAQsFAAOC\n", "AYEACuMUNq9ay++e5YC7QFO94rfzxGQnF3GklZNAXmIr7PVGdiGY2GTx/9RtHCwT\n", "KzkL+yvKojeZ9dVK8wrGViRkO/jUyZ+KcWRokUjs59ncJGRMSSRxteCQujt4hf2+\n", "/qV+f2sMQtErwPE30vbqRYUNNNBVEQpaQx/acJDUv9v7sjHiJDqXwQ+rzj95iHAI\n", "aeEHqF/Ms22p2beZuqvIQKeMl+svVqHtiuzWnF4U6VImpkr4bHl7egV9H6l6T2SM\n", "kj6qDU5e9Ng0ZlLTtosshBLmopF7e7HyrTEAmfOPKQe0Eg9E2urzxqBuG54k50G2\n", "J0FiPsQJAhFiNGwSg4S3HyVDG7ueKd0L93wKONOYGvMKizCHB+pKvEMJoZ8y9uiB\n", "+HFXcp9RaJqJ97HpZTEv+liCp2PSXzcK0r25ScyjF6dLouK2SB30xAvJ8tE584+j\n", "qQ6CGecU9XjvlAjuJdCrDeVPsjkn7OPXG+8XZU7zqHZNmXX1YY4H5rgEJ48lrUrP\n", "3I8R\n", "-----END CERTIFICATE-----\n" ] } ], "source": [ "!openssl x509 -in cert.der -inform DER -outform PEM -out cert.pem\n", "!cat cert.pem" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3. Create JWS to Attach to Bundle" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3.1. Prepare Header\n", "\n", " note the base64 DER is Cert PEM file wihout the footer and header and line returns" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "with open('cert.pem') as f:\n", " der = (f.read()) # base64 DER is PEM wihout the footer and header and line returns\n", "der = der.replace('-----BEGIN CERTIFICATE-----','')\n", "der = der.replace('-----END CERTIFICATE-----','')\n", "der = der.replace('\\n','')" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'alg': 'RS256',\n", " 'kty': 'RS',\n", " 'x5c': ['MIIE3zCCA0egAwIBAgIJAOKFYvMwR+yQMA0GCSqGSIb3DQEBCwUAMIGNMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTESMBAGA1UEBwwJU2F1c2FsaXRvMRUwEwYDVQQKDAxIZWFsdGhlRGF0YTExFzAVBgNVBAMMDkVyaWMgSGFhcywgRFZNMSUwIwYJKoZIhvcNAQkBFhZlaGFhc0BoZWFsdGhlZGF0YTEub3JnMB4XDTIxMTAyNzE3NDIwNFoXDTIyMTAyMjE3NDIwNFowgY0xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRIwEAYDVQQHDAlTYXVzYWxpdG8xFTATBgNVBAoMDEhlYWx0aGVEYXRhMTEXMBUGA1UEAwwORXJpYyBIYWFzLCBEVk0xJTAjBgkqhkiG9w0BCQEWFmVoYWFzQGhlYWx0aGVkYXRhMS5vcmcwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDpKcSkoAM6sW21+vWTeIVOGx10MWasQy7VHid6zyqXABM+znfBnXenyU0j1FTvPmRfODoODXVuPUwDomhCHh+bclW9KM2o563cxRKEvBnaHrsjw5yNmxO5YjERbhtHdQeqktdw3VYERR9HoxLO3FkszR292HTB4xW3yWlV3gTkMQozPScJKH3bG8Pqq6AYPJ7C4YBIlUSdBMVl3qneEfg7fuxiFfXofdTVm7rMiiG7X9z43PfilqaeisfmtRxAlRwENXrH3OvODPyL0rTnG8CsbAXYVIMmddHe4ZF9plh95sj4pMThLtcJX/o9XHLjh7EmZygJHWEQq4PwFwZdmbcfhCmOr88H8BbUru/7V6zbsG1N1CWlndlbVznL+3IMOr8kXaHcanqfckgFV4ErnfjFJq1OIaAmsMj85xMkjyXLycLL/u5n2o6Bg93/URfquOoSIGOCR25DaZzpw2k3s7oE9dMwEWXtfXgYth2bljy5tFH0GjpOkx07j7ZT5HnxnlsCAwEAAaNAMD4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCBeAwIQYDVR0RBBowGIIWd3d3LmhlYWx0aGVkYXRhaW5jLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEACuMUNq9ay++e5YC7QFO94rfzxGQnF3GklZNAXmIr7PVGdiGY2GTx/9RtHCwTKzkL+yvKojeZ9dVK8wrGViRkO/jUyZ+KcWRokUjs59ncJGRMSSRxteCQujt4hf2+/qV+f2sMQtErwPE30vbqRYUNNNBVEQpaQx/acJDUv9v7sjHiJDqXwQ+rzj95iHAIaeEHqF/Ms22p2beZuqvIQKeMl+svVqHtiuzWnF4U6VImpkr4bHl7egV9H6l6T2SMkj6qDU5e9Ng0ZlLTtosshBLmopF7e7HyrTEAmfOPKQe0Eg9E2urzxqBuG54k50G2J0FiPsQJAhFiNGwSg4S3HyVDG7ueKd0L93wKONOYGvMKizCHB+pKvEMJoZ8y9uiB+HFXcp9RaJqJ97HpZTEv+liCp2PSXzcK0r25ScyjF6dLouK2SB30xAvJ8tE584+jqQ6CGecU9XjvlAjuJdCrDeVPsjkn7OPXG+8XZU7zqHZNmXX1YY4H5rgEJ48lrUrP3I8R']}" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "header = {\"alg\": \"RS256\",\"kty\": \"RS\", \"x5c\": [der]}\n", "header" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### 3.2.1 Fetch Payload\n", "\n", "todo verify if bundle or turn into fhir bundle" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "PosixPath('in_files/test_bundle.json')" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "from pathlib import Path\n", "out_file = 'signed_object.json'\n", "in_file = 'in_files/test_bundle.json'\n", "path = Path() / in_file\n", "path" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### 3.2.1 Prepare Payload\n", "\n", "The payload is the base64_url form of the canonicalized version of the document Bundle before attaching the signature\n", " \n", "\n", "##### Canonicalize the bundle using IETF JSON Canonicalization Scheme (JCS) before adding the signature element:\n", "\n", "- Remove the id and meta elements if present before canonicalization" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{\n", " \"resourceType\": \"Bundle\",\n", " \"id\": \"12521\",\n", " \"meta\": {\n", " \"versionId\": \"1\",\n", " \"lastUpdated\": \"2022-02-15T15:53:19.296Z\"\n", " },\n", " \"identifier\": {\n", " \"system\": \"urn:ietf:rfc:3986\",\n", " \"value\": \"urn:uuid:0c3151bd-1cbf-4d64-b04d-cd9187a4c6e0\"\n", " },\n", " \"type\": \"document\",\n", " \"timestamp\": \"2013-05-28T22:12:21Z\",\n", " \"entry\": [\n", " {\n", " \"fullUrl\": \"http://fhir.healthintersections.com.au/open/Composition/180f219f-97a8-486d-99d9-ed631fe4fc57\",\n", " \"resource\": {\n", " \"resourceType\": \"Composition\",\n", " \"id\": \"180f219f-97a8-486d-99d9-ed631fe4fc57\",\n", " \"meta\": {\n", " \"lastUpdated\": \"2013-05-28T22:12:21Z\"\n", " },\n", " \"text\": {\n", " \"status\": \"generated\",\n", " \"div\": \"
Generated Narrative with Details
id: 180f219f-97a8-486d-99d9-ed631fe4fc57
meta:
status: final
type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)
encounter: urn:uuid:a16719d5-5267-4f69-913a-f29e4b800a14
date: 01/02/2013 12:30:02 PM
author: Doctor Dave
title: Discharge Summary
confidentiality: N
| Details | \\n\\n\\n\\n |
| Acute Asthmatic attack. Was wheezing for days prior to admission. | \\n\\n\\n\\n |
| Medication | \\n\\nLast Change | \\n\\nLast ChangeReason | \\n\\n
| Theophylline 200mg BD after meals | \\n\\ncontinued | \\n\\n|
| Ventolin Inhaler | \\n\\nstopped | \\n\\nGetting side effect of tremor | \\n\\n
| Allergen | \\n\\nReaction | \\n\\n
| Doxycycline | \\n\\nHives | \\n\\n
Dr Adam Careful
\\n\\nTheophylline 200mg twice a day
\\n\\nVentolin inhaler discontinued
\\n\\n| Details | \\\\n\\\\n\\\\n\\\\n |
| Acute Asthmatic attack. Was wheezing for days prior to admission. | \\\\n\\\\n\\\\n\\\\n |
| Medication | \\\\n\\\\nLast Change | \\\\n\\\\nLast ChangeReason | \\\\n\\\\n
| Theophylline 200mg BD after meals | \\\\n\\\\ncontinued | \\\\n\\\\n|
| Ventolin Inhaler | \\\\n\\\\nstopped | \\\\n\\\\nGetting side effect of tremor | \\\\n\\\\n
| Allergen | \\\\n\\\\nReaction | \\\\n\\\\n
| Doxycycline | \\\\n\\\\nHives | \\\\n\\\\n
Generated Narrative with Details
id: 180f219f-97a8-486d-99d9-ed631fe4fc57
meta:
status: final
type: Discharge Summary from Responsible Clinician (Details : {LOINC code \\'28655-9\\' = \\'Physician attending Discharge summary)
encounter: urn:uuid:a16719d5-5267-4f69-913a-f29e4b800a14
date: 01/02/2013 12:30:02 PM
author: Doctor Dave
title: Discharge Summary
confidentiality: N
Dr Adam Careful
\\\\n\\\\nTheophylline 200mg twice a day
\\\\n\\\\nVentolin inhaler discontinued
\\\\n\\\\n| Details | \\n\\n\\n\\n |
| Acute Asthmatic attack. Was wheezing for days prior to admission. | \\n\\n\\n\\n |
| Medication | \\n\\nLast Change | \\n\\nLast ChangeReason | \\n\\n
| Theophylline 200mg BD after meals | \\n\\ncontinued | \\n\\n|
| Ventolin Inhaler | \\n\\nstopped | \\n\\nGetting side effect of tremor | \\n\\n
| Allergen | \\n\\nReaction | \\n\\n
| Doxycycline | \\n\\nHives | \\n\\n
Generated Narrative with Details
id: 180f219f-97a8-486d-99d9-ed631fe4fc57
meta:
status: final
type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)
encounter: urn:uuid:a16719d5-5267-4f69-913a-f29e4b800a14
date: 01/02/2013 12:30:02 PM
author: Doctor Dave
title: Discharge Summary
confidentiality: N
Dr Adam Careful
\\n\\nTheophylline 200mg twice a day
\\n\\nVentolin inhaler discontinued
\\n\\n| Details | \\n\\n\\n\\n |
| Acute Asthmatic attack. Was wheezing for days prior to admission. | \\n\\n\\n\\n |
| Medication | \\n\\nLast Change | \\n\\nLast ChangeReason | \\n\\n
| Theophylline 200mg BD after meals | \\n\\ncontinued | \\n\\n|
| Ventolin Inhaler | \\n\\nstopped | \\n\\nGetting side effect of tremor | \\n\\n
| Allergen | \\n\\nReaction | \\n\\n
| Doxycycline | \\n\\nHives | \\n\\n
Generated Narrative with Details
id: 180f219f-97a8-486d-99d9-ed631fe4fc57
meta:
status: final
type: Discharge Summary from Responsible Clinician (Details : {LOINC code '28655-9' = 'Physician attending Discharge summary)
encounter: urn:uuid:a16719d5-5267-4f69-913a-f29e4b800a14
date: 01/02/2013 12:30:02 PM
author: Doctor Dave
title: Discharge Summary
confidentiality: N
Dr Adam Careful
\\n\\nTheophylline 200mg twice a day
\\n\\nVentolin inhaler discontinued
\\n\\n