I am developing a P2P Infrastructure that will have data from a set of different applications, distributed through the network. This P2P overlay is composed by a set of Python Twisted Servers.
I need to guarantee the security and privacy of the stored data, for each user of each application. Consequently, I am generating pairs of RSA keys in the client side of the web app, using the Web Crypto API. The RSA key pairs will be stored in the P2P overlay as well. So, I cipher on the client side, the private keys with a derivation of the user password.
In addition, I am using jwk to pem module to convert the JWK public key into a PEM key, to be used in the Python Cryptography library (PyCrypt or m2Crypto).
Finally, I have to guarantee that the message containing those credentials, as well as the user data , maintain its integrity. Therefore, in the client side, I am signing this data with the user's private key.
I send the data, as well as the signature, both in ArrayBuffer type to the server, encoded in base64.
function signData(private_key, data, callback){
var dataForHash = str2ab(JSON.stringify(sortObject(data)));
computeSHA(dataForHash, "SHA-256", function(hash){
signRSA(private_key, hash, function(data){
callback(data.buffer.b64encode(), dataForHash.b64encode());
});
});
}
function computeSHA(data, mode, callback){
window.crypto.subtle.digest(
{
name: mode,
},
data
)
.then(function(hash){
callback(new Uint8Array(hash).buffer);
})
.catch(function(err){
console.error(err);
});
}
function signRSA(private_key, data, callback){
window.crypto.subtle.sign(
{
name: "RSASSA-PKCS1-v1_5",
},
private_key,
data
)
.then(function(signature){
callback(new Uint8Array(signature));
})
.catch(function(err){
console.error(err);
});
}
ArrayBuffer.prototype.b64encode = function(){
return btoa(String.fromCharCode.apply(null, new Uint8Array(this)));
};
Afterwards, when the Python Server receives this http request, it decodes data and signature from base64.
dataForHash = base64.b64decode(dataReceived['data'])
signature = base64.b64decode(dataReceived['signature'])
For validating the signature, the public key is needed. Consequently:
data = utils.byteify(json.loads(dataForHash.decode("utf-16")))
pub_key = base64.b64decode(data['pub_key']) # Get PEM Public Key
(utils.byteify() converts unicode string to regular strings)
Verifying signature:
Authentication.verifySignature(signature, dataForHash, pub_key)
Method definition:
from Crypto.Signature import PKCS1_v1_5
from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA
def verifySignature(signature, data, pub_key):
key = RSA.importKey(pub_key)
h = SHA256.new(data)
verifier = PKCS1_v1_5.new(key)
return verifier.verify(h, signature)
However, the signature verification returns False. I have also tried to use the m2crypto library, but it returns 0.