[openstack-dev] [nova][keystone] Message Queue Security

JIANGANG Zhang jgzhang at hotmail.com
Fri Apr 26 20:59:44 UTC 2013


Comments in line belowŠ
> 
> Regards,
> JZ
> 
> On 4/26/13 12:59 PM, "Simo Sorce" <simo at redhat.com> wrote:
> 
>> On Fri, 2013-04-26 at 11:23 -0700, JIANGANG Zhang wrote:
>>> (The previous reply used the wrong subject line - my appologies)
>>> 
>>> 
>>> Hi Simo,
>>> 
>>> Nice writeup. A couple of comments I have just in case:
>> 
>> Hi,
>> thank you for your comments!
>> 
>> 
>>> 1) Regardless public key or shared key based solution, there's always
>>> a need to store the secret key. The difference is with public key
>>> based, only the owner has the private key.
>> 
>> Yup.
>>> 
>>> 2) You mentioned that PKI is slow and complex, which is true
>>> comparatively but should be ok in this use case. For example, I can do
>>> 1034 sign/s and 22829 verify/s on my shabby macbook pro of 2010 and
>>> the CPU usage does not seem to be an issue. Compared to the 2 lookups
>>> per message in your proposal as you mentioned, it's much much more
>>> efficient.
>> 
>> And how many HMACs can you do ?
> 
> [JZ] definitely a lot more, but the throughput with RSA is good enough for
> this scenario.
> 
>> 
>>> 
>>> 3) It looks like your key server is like Kerberos.  There's probably
>>> no point to reinvent the wheel. It should easily adapt to this 1:1 use
>>> case as you proposal supported.
>> 
>> I already replied about this, there is however a difference, where it
>> comes to trusts between different realms and most importantly group
>> recipients. They are all solvable so I always keep an option open to
>> just move everything over to use Kerberos for most of what is done here.
>> The changes would be minimal so far and would be able to drop in place
>> easily. I am just trying to do a simpler implementation now so we can
>> have something decent in Havana that works.
>>> 
>>> 4) Arguably, your proposal supports confidentiality, authorization
>>> control (via the shared secret)  and integrity and anti-replay (via
>>> timestamp), but it falls short on non-repudiation due to the nature of
>>> shared secret. 
>> 
>> True, but I do not think we need non-repudiation at this stage.
> 
> [JZ] That is arguable - we should design for the near future as well.
> 
>>> 
>>> 5) The 2 lookups to Key Server per message is way too much with regard
>>> to efficiency.
>> 
>> Keep in mind that the 2 lookups are not *per-message* but per-peer-pair.
>> Ie if you send many messages between A and B in a short timeframe you do
>> only 2 lookups in total, not 2 lookups per message.
>> 
>> Also read the email I sent today, the number of lookups is down to 1
>> now, just like in the public key case.
>>> 
>>> 6) As mentioned, failure to support 1:m, m:n messaging imposes too
>>> much restriction to the overall system.
>> 
>> Indeed this has been mostly addressed though.
> 
> [JZ] Addressed by not doing it:) As openstack adoption grows, more
> functionality are needed and we should not have too much restrictions if
> absolutely needed.
> 
>>> 
>>> That said, the following is what I would suggest, which supports 1:1,
>>> 1:m and m:n messaging with confidentiality, integrity, authorization,
>>> non-repudiation and anti-reply:
>>> 
>>> 
>>> a) In keystone, for each user add an entry for its public key - only
>>> the user itself knows its own private key.
>>> 
>>> 
>>> b) To support 1:m and m:n, each "group/role" of users is provisioned
>>> with its group public key - all users of this "group/role" is
>>> provisioned with the "group/role" private key.
>> 
>> How do you provision these keys ? How do you revoke and replace them ?
> 
> [JZ] Provision it to keystone. Replacing it in place with versioning.
> Revoke is tough without x.509 revocation but cautious peers can always
> check at the beginning of a "session"
> 
>> 
>> In my recent design I have a very simple method that avoids very
>> expensive provisioning. (still setting up the share key need to be done,
>> but that's inevitable)
>>> 
>>> c) All public keys (via x.509 or bare key) are cacheable. Cautious
>>> senders and recipients should check regularly but it's an overkill to
>>> check once per message.
>>> 
>> Indeed, nobody is suggesting to check once per message.
>> 
>>> d) On sending the message, the sender does the following:
>>> 
>>> 
>>>        d.a) looks up (if not cached or to be cautious - assuming
>>>        there's no revocation in place) for the recipient's or
>>>        recipients' public key.
>>> 
>>> 
>>>        d.b) generate a encryption key (EK) and a signing key (SK)
>>>        (not necessary if public key signing is used) and decide its
>>>        lifetime (expiration and)
>>> 
>>> 
>>>        d.c) generate a random # of at least 128 bit long,
>>>        start/current time (e.g. via gettimeofday), EK and SK
>>>        signature, expiration and and sender-id, concatenate and sign
>>>        them using its private key
>>> 
>>> 
>>>        d.d) Encrypt the message (together necessary meta data, e.g.
>>>        recipient list and lifetime left, sequence counter) using EK,
>>>        as BodyE and sign the encrypted BodyE using the sign key as
>>>        SIGN.
>>> 
>>> 
>>>        d.e) For each recipient, use its public key to encrypt EK, the
>>>        encryption algo,  signing key SK (if needed), signing algo,
>>>         and EK/SK expiration), then prepend it with the recipient's
>>>        public key identifier - e.g. uid.
>>> 
>>> 
>>>        d.f) Send the the outcome of d.c), BodyE and SIGN from d.d)
>>>        and d.e) over the all recipients.
>>> 
>>> 
>>>        Note: d.b), d.c) and d.e) are only done once for the duration
>>>        of the EK/SK lifetime, so the # of public key calculations
>>>        (RSA/EC etc) are minimized. The algos are there for
>>>        extensibility and the recipient can reject if it's weak.
>> 
>> Yes this is very similar to what I described in the document and the
>> recent amendment to the list except you use a public key scheme to
>> protect EK and SK.
>> However there is a problem here, you assume that either the sender knows
>> the identity of all recipients one by one or use of a shared private key
>> for groups of services.
> 
> [JZ] Yes, that can be retrieved from keystone with one call.
> 
>> 
>> If you send to multiple recipients, you need one lookup for each
>> recipient, which becomes very expansive rapidly. and the message size
>> also increases quite rapidly as you have to encrypt the same body
>> multiple times, plus you need to use something like a dict so the
>> recipient can find the correct key, which further increases message
>> size.
> 
> 
> [JZ] Mostly, you know your recipients and you can cache the public keys of
> them. You only need to check periodically or if you have revocation in
> place, that'll be better.
> 
>> 
>> If you send to a shared identity you still have a shared private key
>> system but your shared key for a group is long term and not short term.
>> Also you need a way to communicate this key to all peers, how do you do
>> that ?
> 
> [JZ] That's a tough one - I am assuming out-of-band or design an interface
> in the UI.
> 
>> 
>>> e) On receiving the message, the recipient doe the following:
>>> 
>>> 
>>>        e.a) looks up )if not cached or to be cautious - assuming
>>>        there's no revocation in place)  for the sender's public key.
>>> 
>>> 
>>>        e.b) verify sender signature and time window etc if not
>>>        previously verified for this "session" (a while ago - time
>>>        window == expiration).
>>> 
>>> 
>>>        e.c) decrypt the block prepared by d.e), gets the EK, SK,
>>>        expiration and verify the expiration.
>>> 
>>> 
>>>        e.d) Using SK to verify signature
>>> 
>>> 
>>>        e.e) Decrypt the message using EK, check against replay via
>>>        verifying the expiration and counter/sequence etc.
>>> 
>>> 
>>> If more detailes are needed, please let me know. Note that there may
>>> be loose ends given the limited time I have spent on this.
>> 
>> Well I see 2 problems with this scheme.
>> 
>> 1. Now you are doing 2 lookups because you have to look up keys on both
>> sender and receiver. While my revised scheme needs only one :-)
> 
> [JZ] You only do that when you don't have it:).
> 
>> 
>> 2. Because you do not have a key server in the mix you also do not have
>> access control there, which means the receiver will have to additionally
>> perform access control to decide whether the sending party is allowed to
>> send messages at all, and this is an additional policy lookup from some
>> central server. It can be cached, but you still need to regularly
>> refresh it in case policies change.
> 
> [JZ] I do rely on keystone like system to hold the public key. And access
> control is a different thing, as I have presented during the summit.
> 
>> 
>> In my design if the A -> B message is not permitted the sender doesn't
>> even get a key so no resources are spent at all either on the sender or
>> on the receiver. So it seem to me my proposal is more efficient on
>> various levels.
> 
> [JZ] Access control is different from authentication/integrity,
> confidentiality and non-repudiation. Access control can be role-based with
> context-awareness, different system indeed.
>> 
>> Simo.
>> 
>> 
>> -- 
>> Simo Sorce * Red Hat, Inc * New York
>> 
> 
> 


More information about the OpenStack-dev mailing list