initial scaffolding for SDK encryption#37
Conversation
dcb1cab to
1081765
Compare
Signed-off-by: Lance-Drane <Lance-Drane@users.noreply.github.com>
1081765 to
94e17fb
Compare
|
UPDATE:
One thing that is sort of blocking me:
|
| ) | ||
|
|
||
| @intersect_message() | ||
| def get_public_key(self) -> Dict[str, str]: |
There was a problem hiding this comment.
we should be more explicit with the typing here, we can use Union types if necessary
| from pydantic import BaseModel | ||
|
|
||
| class IntersectDecryptedPayload(BaseModel): | ||
| model: BaseModel |
There was a problem hiding this comment.
this might need to be an Any typing because we don't necessarily require BaseModels as the input/output models
| - If your Content-Type value is ANYTHING ELSE, you MUST mark it as "bytes" . In this instance, INTERSECT will not base64-encode or base64-decode the value. | ||
| """ | ||
|
|
||
| IntersectEncryptionScheme = Literal['NONE', 'RSA'] |
There was a problem hiding this comment.
move to intersect-sdk-common: https://github.com/INTERSECT-SDK/intersect-python-common
There was a problem hiding this comment.
be more explicit in the RSA typing, i.e. RSA_AES_2048
| from .aes_cypher import AESCipher | ||
| from .client_encryption import intersect_payload_encrypt | ||
| from .service_decryption import intersect_payload_decrypt | ||
|
|
||
|
|
||
| __all__ = ( | ||
| 'AESCipher', | ||
| 'intersect_payload_encrypt', | ||
| 'intersect_payload_decrypt', |
There was a problem hiding this comment.
Everything in this namespace should probably be moved to intersect-sdk-common: https://github.com/INTERSECT-SDK/intersect-python-common
| # Generate a key pair for encryption | ||
| self._private_key: rsa.RSAPrivateKey = rsa.generate_private_key( | ||
| public_exponent=65537, key_size=2048 | ||
| ) | ||
| self._public_key = self._private_key.public_key() | ||
|
|
||
| # Get the PEM encoded public key | ||
| self._public_key_pem = self._public_key.public_bytes( | ||
| encoding=serialization.Encoding.PEM, | ||
| format=serialization.PublicFormat.SubjectPublicKeyInfo, | ||
| ).decode() | ||
|
|
||
| self._private_key.private_bytes( | ||
| encoding=serialization.Encoding.PEM, | ||
| format=serialization.PrivateFormat.TraditionalOpenSSL, | ||
| encryption_algorithm=serialization.NoEncryption(), | ||
| ) |
There was a problem hiding this comment.
we should use a configuration parameter (both here and the Client) to ensure that we can always regenerate the same public/private key. We should also have some logic to allow for key rotation without necessarily restarting the Service/Client.
| """Basic status function which returns a hard-coded string.""" | ||
| return 'Up' | ||
|
|
||
| @intersect_message() |
There was a problem hiding this comment.
may want to explicitly set the encryption schemes to the RSA scheme only, to enforce the encryption
| step three: start up client with user callback | ||
| """ | ||
| intersect_client.startup(user_callback=user_callback) | ||
|
|
There was a problem hiding this comment.
this will need to call intersect_sdk.get_public_key before calling say_hello_to_name
Needs to be completed before done:
(I don't really care too much about unit tests, but you can unit test the encryption function itself if you want)
To add the capability endpoints for a Service (which, IIRC, is just the
get_public_keyfunction), add it toIntersectSdkCoreCapability(https://github.com/INTERSECT-SDK/python-sdk/blob/candidate-0.9.0/src/intersect_sdk/capability/universal_capability/universal_capability.py), it should be annotated with@intersect_message. If we need additional state in the capability, we can modify the constructor for this capability and potentially the service as well.Then you can call the capability with
intersect_sdk.<YOUR_FUNCTION_NAME_HERE>as the operation from clients.The actual encrypt/decrypt functions I would prefer to be separated out into utility functions in another file somewhere under the
_internaldirectory, because both the Service and the Client will use them and users also have no reason to ever use this function themselves. I have marked the areas which need the inserted functions with#TODO comments, there should be one of each inclient.pyand two of each inservice.py.