Search code examples
javascriptc#cryptographydigital-signaturebouncycastle

Sign data with BouncyCastle (C#) and verify with jsrsasign (js)


I am trying to sign data on the server side and validate it on the client side. the keys - private and public are saved as PEM strings both on the client (public) and server (private).

When I execute all the actions in the server OR in the client side everything works fine - the signing and verifying.

The code on the server side:

// Prepare data to sign as bytes[]
byte[] dataToSign = Encoding.UTF8.GetBytes(data);

var keyParamAsPEM = (AsymmetricCipherKeyPair)pemReader.ReadObject();
AsymmetricKeyParameter key = keyParamAsPEM.Private;

var keyParameter = new RsaKeyParameters(key.IsPrivate, ((RsaPrivateCrtKeyParameters) key).Modulus, ((RsaPrivateCrtKeyParameters) key).Exponent);

// Init alg
ISigner sig = SignerUtilities.GetSigner("SHA256withRSA");

// Populate key
sig.Init(true, keyParameter);

// Calc signature
sig.BlockUpdate(dataToSign, 0, dataToSign.Length);
byte[] signature = sig.GenerateSignature();

// Base 64 encode the sig so its 8-bit clean
string signatureServer = Convert.ToBase64String(signature);

The code in the client side:

const pubKey = rsa.KEYUTIL.getKey(PUBLIC_KEY);
const rsaObj = new rsa.Signature({ alg: 'SHA256withRSA' });
rsaObj.init(pubKey);
rsaObj.updateString(JSON.stringify(data));
const isValid = rsaObj.verify(signature);

I signed the data in the client side:

const privKey = rsa.KEYUTIL.getKey(PRIVATE_KEY);
const sig = new rsa.Signature({ alg: 'SHA256withRSA' });
sig.init(privKey);
sig.updateString(JSON.stringify(data));
const signatureClient = sig.sign();

And I found out that the signatureClient (signature created in the client side) is not equal to the signature signed in the signatureServer (signature created in the server side).


Solution

  • The issue is resolved.

    I am using JOSE-JWT dll in the server side, with Bouncy Castle, to sign the data. I create a token while storing the data in the 'sub' property in the claims section.

    In the client side I am still using jsrsasign package but I am now verifying the the TOKEN using jws.JWS.verifyJWT() method.