Refactored signature creation to Gxs security

Fixed signing of msgs 
Added signing of groups (follows p3distrib grp creation method)
Refactored GxsGroupDialog in 2 new UIs, GxsCreateGroupDialog and GxsViewGroup for ease of logic, retaining flexibility across GXS services. 

git-svn-id: http://svn.code.sf.net/p/retroshare/code/branches/v0.5-gxs-b1@5762 b45a01b8-16f6-495d-af2f-9b41ad6348cc
This commit is contained in:
chrisparker126 2012-11-02 23:35:10 +00:00
parent 563e3df91e
commit 6f6f55c166
10 changed files with 286 additions and 62 deletions

View File

@ -1,10 +1,10 @@
/*
* libretroshare/src/distrib: p3distribverify.cc
* libretroshare/src/gxs: gxssecurity.cc
*
*
* Copyright 2008-2010 by Robert Fernie
* 2011 Christopher Evi-Parker
* 2011-2012 Christopher Evi-Parker
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -49,6 +49,30 @@ RSA *GxsSecurity::extractPublicKey(RsTlvSecurityKey& key)
return rsakey;
}
bool GxsSecurity::getSignature(char* data, uint32_t data_len, RsTlvSecurityKey* privKey, RsTlvKeySignature& sign)
{
RSA* rsa_pub = extractPrivateKey(*privKey);
EVP_PKEY *key_pub = EVP_PKEY_new();
EVP_PKEY_assign_RSA(key_pub, rsa_pub);
/* calc and check signature */
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
bool ok = EVP_SignInit(mdctx, EVP_sha1()) == 1;
ok &= EVP_SignUpdate(mdctx, data, data_len) == 1;
unsigned int siglen = EVP_PKEY_size(key_pub);
unsigned char sigbuf[siglen];
ok &= EVP_SignFinal(mdctx, sigbuf, &siglen, key_pub) == 1;
// clean up
EVP_MD_CTX_destroy(mdctx);
EVP_PKEY_free(key_pub);
sign.signData.setBinData(sigbuf, siglen);
sign.keyId = privKey->keyId;
return ok;
}
bool GxsSecurity::validateNxsMsg(RsNxsMsg *msg, RsTlvKeySignature& sign, RsTlvSecurityKeySet& key)
{
@ -135,7 +159,7 @@ bool GxsSecurity::validateNxsMsg(RsNxsMsg *msg, RsTlvKeySignature& sign, RsTlvSe
// std::cerr << std::endl;
//#endif
// return false;
return false;
}
@ -321,7 +345,7 @@ std::string GxsSecurity::getRsaKeySign(RSA *pubkey)
bool GxsSecurity::validateNxsGrp(RsNxsGrp *newGrp, RsTlvKeySignature& sign, RsTlvSecurityKey& key)
{
return false;
}
void GxsSecurity::setRSAPublicKey(RsTlvSecurityKey & key, RSA *rsa_pub)

View File

@ -130,6 +130,16 @@ public:
* @return false if verfication of signature is not passed
*/
static bool validateNxsMsg(RsNxsMsg *msg, RsTlvKeySignature& sign, RsTlvSecurityKeySet& key);
/*!
* @param data data to be signed
* @param data_len length of data to be signed
* @param privKey private key to used to make signature
* @param sign the signature is stored here
* @return false if signature creation failed, true is signature created
*/
static bool getSignature(char* data, uint32_t data_len, RsTlvSecurityKey* privKey, RsTlvKeySignature& sign);
};
#endif // GXSSECURITY_H

View File

@ -125,7 +125,7 @@ bool RsGenExchange::acknowledgeTokenGrp(const uint32_t& token,
return true;
}
void RsGenExchange::createGroup(RsNxsGrp *grp)
bool RsGenExchange::createGroup(RsNxsGrp *grp)
{
/* create Keys */
@ -162,17 +162,40 @@ void RsGenExchange::createGroup(RsNxsGrp *grp)
adminKey.endTS = 0; /* no end */
RsGxsGrpMetaData* meta = grp->metaData;
/* add keys to grp */
/* add public keys to grp */
meta->keys.keys[adminKey.keyId] = adminKey;
meta->keys.keys[privAdminKey.keyId] = privAdminKey;
meta->keys.keys[pubKey.keyId] = pubKey;
// group is self signing
// for the creation of group signature
// only public admin and publish keys are present
// key set
uint32_t metaDataLen = meta->serial_size();
uint32_t allGrpDataLen = metaDataLen + grp->grp.bin_len;
char* metaData = new char[metaDataLen];
char* allGrpData = new char[allGrpDataLen]; // msgData + metaData
meta->serialise(metaData, metaDataLen);
// copy msg data and meta in allMsgData buffer
memcpy(allGrpData, grp->grp.bin_data, grp->grp.bin_len);
memcpy(allGrpData+(grp->grp.bin_len), metaData, metaDataLen);
RsTlvKeySignature adminSign;
bool ok = GxsSecurity::getSignature(allGrpData, allGrpDataLen, &privAdminKey, adminSign);
/* now add private keys to grp */
meta->keys.keys[privAdminKey.keyId] = privAdminKey;
meta->keys.keys[privPubKey.keyId] = privPubKey;
// add admin sign to grpMeta
meta->signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_ADMIN] = adminSign;
pqihash hash;
// get hash of msg data to create msg id
hash.addData(grp->grp.bin_data, grp->grp.bin_len);
hash.addData(allGrpData, allGrpDataLen);
hash.Complete(meta->mGroupId);
grp->grpId = meta->mGroupId;
@ -181,12 +204,17 @@ void RsGenExchange::createGroup(RsNxsGrp *grp)
privPubKey.TlvClear();
pubKey.TlvClear();
// free the private key for now, as it is not in use
// clean up
RSA_free(rsa_admin);
RSA_free(rsa_admin_pub);
RSA_free(rsa_publish);
RSA_free(rsa_publish_pub);
delete[] allGrpData;
delete[] metaData;
return ok;
}
bool RsGenExchange::createMessage(RsNxsMsg* msg)
@ -198,7 +226,7 @@ bool RsGenExchange::createMessage(RsNxsMsg* msg)
metaMap.insert(std::make_pair(id, (RsGxsGrpMetaData*)(NULL)));
mDataStore->retrieveGxsGrpMetaData(metaMap);
bool ok = true;
RSA* rsa_pub = NULL;
RSA* rsa_pub = NULL;
if(!metaMap[id])
{
@ -207,7 +235,7 @@ bool RsGenExchange::createMessage(RsNxsMsg* msg)
else
{
// get publish key
RsGxsGrpMetaData* grpMeta = metaMap[id];
RsGxsGrpMetaData* grpMeta = metaMap[id];
// public and shared is publish key
RsTlvSecurityKeySet& keys = grpMeta->keys;
@ -219,70 +247,56 @@ bool RsGenExchange::createMessage(RsNxsMsg* msg)
for(; mit != mit_end; mit++)
{
pub_key_found = mit->second.keyFlags & (RSTLV_KEY_DISTRIB_PRIVATE | RSTLV_KEY_TYPE_FULL);
pub_key_found = mit->second.keyFlags & (RSTLV_KEY_DISTRIB_PRIVATE | RSTLV_KEY_TYPE_FULL);
if(pub_key_found)
break;
}
if(pub_key_found)
{
RsGxsMsgMetaData &meta = *(msg->metaData);
uint32_t metaDataLen = meta.serial_size();
uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len;
char* metaData = new char[metaDataLen];
char* allMsgData = new char[allMsgDataLen]; // msgData + metaData
meta.serialise(metaData, &metaDataLen);
// copy msg data and meta in allmsgData buffer
memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len);
memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen);
// private publish key
pubKey = &(mit->second);
rsa_pub = GxsSecurity::extractPrivateKey(*pubKey);
EVP_PKEY *key_pub = EVP_PKEY_new();
EVP_PKEY_assign_RSA(key_pub, rsa_pub);
/* calc and check signature */
EVP_MD_CTX *mdctx = EVP_MD_CTX_create();
RsTlvKeySignatureSet& signSet = meta.signSet;
RsTlvKeySignature pubSign = signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH];
RsGxsMsgMetaData &meta = *(msg->metaData);
GxsSecurity::getSignature(allMsgData, allMsgDataLen, pubKey, pubSign);
uint32_t metaDataLen = meta.serial_size();
uint32_t allMsgDataLen = metaDataLen + msg->msg.bin_len;
char* metaData = new char[metaDataLen];
char* allMsgData = new char[allMsgDataLen]; // msgData + metaData
// get hash of msg data to create msg id
pqihash hash;
hash.addData(allMsgData, allMsgDataLen);
hash.Complete(msg->msgId);
meta.serialise(metaData, &metaDataLen);
// assign msg id to msg meta
msg->metaData->mMsgId = msg->msgId;
// copy msg data and meta in allmsgData buffer
memcpy(allMsgData, msg->msg.bin_data, msg->msg.bin_len);
memcpy(allMsgData+(msg->msg.bin_len), metaData, metaDataLen);
ok = EVP_SignInit(mdctx, EVP_sha1()) == 1;
ok = EVP_SignUpdate(mdctx, allMsgData, allMsgDataLen) == 1;
unsigned int siglen = EVP_PKEY_size(key_pub);
unsigned char sigbuf[siglen];
ok = EVP_SignFinal(mdctx, sigbuf, &siglen, key_pub) == 1;
//place signature in msg meta
RsTlvKeySignatureSet& signSet = meta.signSet;
RsTlvKeySignature pubSign = signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH];
pubSign.signData.setBinData(sigbuf, siglen);
pubSign.keyId = pubKey->keyId;
// get hash of msg data to create msg id
pqihash hash;
hash.addData(allMsgData, allMsgDataLen);
hash.Complete(msg->msgId);
msg->metaData->mMsgId = msg->msgId;
//place signature in msg meta
signSet.keySignSet[GXS_SERV::FLAG_AUTHEN_PUBLISH] = pubSign;
// clean up
EVP_MD_CTX_destroy(mdctx);
//RSA_free(rsa_pub);
EVP_PKEY_free(key_pub);
// no need to free rsa key as evp key is considered parent key by SSL
delete[] metaData;
delete[] allMsgData;
delete[] metaData;
delete[] allMsgData;
}
else
{
ok = false;
}
delete grpMeta;
delete grpMeta;
}
return ok;
@ -694,11 +708,11 @@ void RsGenExchange::publishGrps()
grpItem->meta.mPublishTs = time(NULL);
*(grp->metaData) = grpItem->meta;
grp->metaData->mSubscribeFlags = GXS_SERV::GROUP_SUBSCRIBE_ADMIN;
createGroup(grp);
ok &= createGroup(grp);
size = grp->metaData->serial_size();
char mData[size];
grp->metaData->mGroupId = grp->grpId;
ok = grp->metaData->serialise(mData, size);
ok &= grp->metaData->serialise(mData, size);
grp->meta.setBinData(mData, size);
RsGxsGroupId grpId = grp->grpId;
mDataAccess->addGroupData(grp);

View File

@ -158,7 +158,7 @@ protected:
/*!
* @param grpItem
* @deprecated only here to temporarily to testing
* @deprecated only here temporarily for testing
*/
void createDummyGroup(RsGxsGrpItem* grpItem);
@ -231,7 +231,7 @@ public:
bool acknowledgeTokenMsg(const uint32_t& token, RsGxsGrpMsgIdPair& msgId);
/*!
* This allows the client service to acknowledge that their grps has \n
* This allows the client service to acknowledge that their grps has \n
* been created/modified and retrieve the create/modified grp ids
* @param token the token related to modification/create request
* @param msgIds vector of ids of groups created/modified
@ -270,20 +270,46 @@ public:
/*!
* sets the group subscribe flag
* @param token this is set to token value associated to this request
* @param
* @param grpId Id of group whose subscribe file will be changed
* @param status
* @param mask
*/
void setGroupSubscribeFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask);
/*!
* sets the group subscribe flag
* @param token this is set to token value associated to this request
* @param grpId Id of group whose subscribe file will be changed
* @param status
* @param mask
*/
void setGroupStatusFlags(uint32_t& token, const RsGxsGroupId& grpId, const uint32_t& status, const uint32_t& mask);
/*!
* sets the group service string
* @param token this is set to token value associated to this request
* @param grpId Id of group whose subscribe file will be changed
* @param servString
*/
void setGroupServiceString(uint32_t& token, const RsGxsGroupId& grpId, const std::string& servString);
/*!
* sets the msg status flag
* @param token this is set to token value associated to this request
* @param grpId Id of group whose subscribe file will be changed
* @param status
* @param mask Mask to apply to status flag
*/
void setMsgStatusFlags(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const uint32_t& status, const uint32_t& mask);
/*!
* sets the message service string
* @param token this is set to token value associated to this request
* @param msgId Id of message whose service string will be changed
* @param servString The service string to set msg to
*/
void setMsgServiceString(uint32_t& token, const RsGxsGrpMsgIdPair& msgId, const std::string& servString );
protected:
/** Notifications **/
@ -324,7 +350,20 @@ private:
*/
void processGrpMetaChanges();
void createGroup(RsNxsGrp* grp);
/*!
* This completes the creation of an instance on RsNxsGrp
* by assigning it a groupId and signature via SHA1 and EVP_sign respectively
* @param grp Nxs group to create
*/
bool createGroup(RsNxsGrp* grp);
/*!
* This completes the creation of an instance on RsNxsMsg
* by assigning it a groupId and signature via SHA1 and EVP_sign respectively
* What signatures are calculated are based on the authentication policy
* of the service
* @param msg the Nxs message to create
*/
bool createMessage(RsNxsMsg* msg);

View File

@ -0,0 +1,26 @@
#include "GxsCreateGroupDialog.h"
#include "ui_GxsCreateGroupDialog.h"
GxsCreateGroupDialog::GxsCreateGroupDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::GxsCreateGroupDialog)
{
ui->setupUi(this);
}
GxsCreateGroupDialog::~GxsCreateGroupDialog()
{
delete ui;
}
void GxsCreateGroupDialog::changeEvent(QEvent *e)
{
QDialog::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

View File

@ -0,0 +1,23 @@
#ifndef GXSCREATEGROUPDIALOG_H
#define GXSCREATEGROUPDIALOG_H
#include <QDialog>
namespace Ui {
class GxsCreateGroupDialog;
}
class GxsCreateGroupDialog : public QDialog {
Q_OBJECT
public:
GxsCreateGroupDialog(QWidget *parent = 0);
~GxsCreateGroupDialog();
protected:
void changeEvent(QEvent *e);
private:
Ui::GxsCreateGroupDialog *ui;
};
#endif // GXSCREATEGROUPDIALOG_H

View File

@ -0,0 +1,18 @@
<ui version="4.0">
<class>GxsCreateGroupDialog</class>
<widget class="QDialog" name="GxsCreateGroupDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -0,0 +1,26 @@
#include "GxsViewGroup.h"
#include "ui_GxsViewGroup.h"
GxsViewGroup::GxsViewGroup(QWidget *parent) :
QWidget(parent),
ui(new Ui::GxsViewGroup)
{
ui->setupUi(this);
}
GxsViewGroup::~GxsViewGroup()
{
delete ui;
}
void GxsViewGroup::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}

View File

@ -0,0 +1,23 @@
#ifndef GXSVIEWGROUP_H
#define GXSVIEWGROUP_H
#include <QWidget>
namespace Ui {
class GxsViewGroup;
}
class GxsViewGroup : public QWidget {
Q_OBJECT
public:
GxsViewGroup(QWidget *parent = 0);
~GxsViewGroup();
protected:
void changeEvent(QEvent *e);
private:
Ui::GxsViewGroup *ui;
};
#endif // GXSVIEWGROUP_H

View File

@ -0,0 +1,21 @@
<ui version="4.0">
<author/>
<comment/>
<exportmacro/>
<class>GxsViewGroup</class>
<widget class="QWidget" name="GxsViewGroup">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
</widget>
<pixmapfunction/>
<connections/>
</ui>