-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improved meta.security object #185
Comments
It looks good and matches what we need in the project where I'm working. There is however a practical problem with how to verify the signature when the signature is part of the message like this. It can be solved by specifying a canonical JSON representation for the messages. The issue is that both the event producer and the event consumer need to JSON-serialize the unsigned message (because the bytes of that message are the input to the signature algorithm). If the producer and consumer choose different JSON representations, e.g. by varying the whitespace or object key order, then the digests will not match. Compare with how X.509 uses DER instead of BER. |
Right, that would make sense if deserialization and reserialization was expected to be part of the process (e.g. I sign a message, turn it into a POJO, turn it back into JSON, hand it back to you and expect you to be able to verify the signatute). In other words, if what you're signing is the information represented by the message, rather than the message itself. In this case, I don't see that as being a requirement. If I serialize the message and then sign it, I expect you to get the exact same string of bytes as I signed, with no manipulation in between (with the exception of changing the value of Perhaps I'm missing something. It wouldn't be the first time :) If that's the case, please educate me! |
Well, my point is that just verifying the signature requires you to strip out encryptedDigest. The most natural way to do this is with a JSON library that turns it into a POJO and then back to JSON. And then if sender and receiver use different JSON libraries, they get different inputs to the signature algorithm. Here's some code to experiment with (just some quick and dirty code, not a proper implementation of the proposal): #!/usr/bin/env python
import copy
import hashlib
import hmac
import json
def sign_hmac(msg_pojo, key):
print "\nSigning (pojo):"
print repr(msg_pojo)
msg_temp = copy.deepcopy(msg_pojo)
msg_temp['meta']['security']['integrityProtection']['algorithm'] = 'HmacSHA256'
msg_temp['meta']['security']['integrityProtection']['encryptedDigest'] = ''
to_be_signed = json.dumps(msg_temp)
print "Input to signature algorithm:"
print to_be_signed
digest = hmac.new(key, to_be_signed, hashlib.sha256).hexdigest()
msg_temp['meta']['security']['integrityProtection']['encryptedDigest'] = str(digest)
signed_text = json.dumps(msg_temp)
print "Signed message:"
print signed_text
return signed_text
def verify_hmac(signed_text, key, indent):
print "\nVerifying:"
print signed_text
msg_temp = json.loads(signed_text)
assert msg_temp['meta']['security']['integrityProtection']['algorithm'] == 'HmacSHA256'
encrypted_digest = msg_temp['meta']['security']['integrityProtection']['encryptedDigest']
msg_temp['meta']['security']['integrityProtection']['encryptedDigest'] = ''
to_be_signed = json.dumps(msg_temp, indent=indent) # MUST be the same as to_be_signed in sign_hmac()
print "Input to signature algorithm:"
print to_be_signed
digest = hmac.new(key, to_be_signed, hashlib.sha256).hexdigest()
print " Digest in the message:", encrypted_digest
print " Digest from our computation:", digest
if encrypted_digest != digest:
print "BAD message digest"
def main():
msg_pojo = {'meta': {'security': {'integrityProtection': {}}}}
key = 'secret'
signed = sign_hmac(msg_pojo, key)
verify_hmac(signed, key, indent=None)
verify_hmac(signed, key, indent=2) # simulate that we are using a different JSON library
if __name__ == '__main__':
main() Output:
The problem is essentially how to ensure that I see three options:
|
Got it. Thanks! Specifying a canonical JSON representation to use in any security sensitive context seems like a good idea regardless, so I would suggest that option. Unfortunately I come up short trying to find any truly established, universal canonical JSON representation. The best I can come up with is this IET draft: https://tools.ietf.org/html/draft-staykov-hu-json-canonical-form-00. It's rather old, but the concent appears sound to me. |
Updated meta.security according to Issue #185. Documentation and schema of all event types has been updated, resulting in a major version step of all event types. Where applicable, examples have been updated, while some examples have been preserved to demonstrate previous behavior in older versions. Description of information integrity protection has been updated in security.md.
Description
The current meta.security object works, but it leaves a lot up to the wrapping layers to sort out. For instance, it's assumed that there's a naming scheme, that algorithms are handshaken, that keys are distributed etc. Sometimes they may be, and there really are very strict limitations on what a protocol can do here, but the aim should be to do/facilitate everything that can be done/facilitated to ensure secure communication.
I would recommend keeping meta.security optional, but restructuring it:
Motivation
Enabling the highest possible security is a good thing.
Exemplification
An example meta.security object would look like this:
Benefits
Would significantly strengthen the possibility to protect the integrity not just of individual Eiffel events, but the entire event stream.
Possible Drawbacks
Can't really think of any, except it will require new event type versions, so there's always compatibility to think of.
The text was updated successfully, but these errors were encountered: