Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Persona on LAN + OpenSSL verifier.

25 views
Skip to first unread message

jérôme Muffat-Méridol

unread,
Nov 9, 2012, 4:41:25 AM11/9/12
to dev-id...@lists.mozilla.org
I'm working on a bit of a specific case where, for example, your home
server would let you share things over your home wifi with
friends/visitors. The application is in C++ and uses OpenSSL for crypto
related matters.

Persona works great, giving me confidence that when I ask
"x...@uvw.comwants to connect", we're really talking about
x...@uvw.com. The context makes it impossible to use SSL between the browser
and the application, but I don't think you can setup a man in the middle
attack between machines on the same subnet.

One thing that could occur is a bundle getting reused on a different LAN:
right now, my "audience" looks like "192.168.0.100:31416". So, if I visit a
different friend with a similar LAN setup, I run the risk of
unintentional autologin ... I could do with a custom field in the bundle:
- sign-in button would call
navigator.id.request({siteName:'ApplicationName',siteParam:'InstanceSpecificValue'});
- IdP would provide certificate as usual
- browser would add the siteParam to signed assertion
This way, when my app receives wrong value, it can have "wrong audience"
behaviour.


Implementing my own verifier was reasonably straightforward. The main
difficulties were:
- big numbers sometimes decimal, sometimes hexadecimal (not a big deal)
- DSA verification with OpenSSL took time to figure out


Here are a few useful snippets for people wanting to use OpenSSL too,
limited to the case of DS128 and RS256 case I encountered:

- loading User's Public Key
m_pUserPK = DSA_new();
BN_hex2bn(&m_pUserPK->pub_key, sY);
BN_hex2bn(&m_pUserPK->p, sP);
BN_hex2bn(&m_pUserPK->q, sQ);
BN_hex2bn(&m_pUserPK->g, sG);

- loading IdP's Public Key
m_pIdpPK = RSA_new();
BN_dec2bn(&m_pIdpPK->n, sN);
BN_dec2bn(&m_pIdpPK->e, sE);

- verifying IdP's signature
int VerifyRSA( const void* pData, size_t DataSize,
const void* pSig, size_t SigSize,
RSA *r)
{
unsigned char hash[SHA256_DIGEST_LENGTH];

if (!SHA256((const unsigned char*)pData, DataSize, hash))
return 0;

if (!RSA_verify(NID_sha256, hash, sizeof(hash), (unsigned char*)pSig,
(unsigned int)SigSize, r))
return 0;

return 1;
}

- verifying user's signature
int VerifyDSA( const char* pData, size_t DataSize,
const void* pSig, size_t SigSize,
DSA *d)
{
unsigned char hash[SHA_DIGEST_LENGTH];
DSA_SIG* pDSAsig;
BIGNUM* R;
BIGNUM* S;
int a;
if (!SHA1((const unsigned char*)pData, DataSize, hash))
return 0;

switch(SigSize)
{
case 40:
{
const unsigned char* SigVal = (const unsigned char*)pSig;

R = BN_bin2bn(&SigVal[ 0], 20, NULL);
S = BN_bin2bn(&SigVal[20], 20, NULL);
} break;

default: return false;
}

pDSAsig = DSA_SIG_new();
pDSAsig->r = R; R=NULL;
pDSAsig->s = S; S=NULL;

a = DSA_do_verify(hash, sizeof(hash), pDSAsig, d);
DSA_SIG_free(pDSAsig);

return a==1;
}


Hope it helps
Thanks for the great initiative

J.
0 new messages