0

Getting False Response while verifying the data and signature. I have used the below link but not luck [Text] Verify RSA SHA256 signature in C#

Public Key : -----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAj1UpJQHGsdlkvlJ6IBWD
KwwczIM3e+NkoBcyUhxSGxB2C7W8x2hbU66uSqLDOaKeXXf/owvRJMLawHCBZgMv
5pTKwFQllD63sZQEAl5dl+VpWf9jmy1BAE3/HBQYM6tEUykx7a9h+4f167v3JxPt
PWpFcBEL3OdnGlYkV/4nhLFop0MSN2szDTfu4IYToy36QlzEhvS9xmNZbVhKkgJN
fxAVgJDMmttJFQdF5ax4jENF04YHO+OPuTPW2HIDkImKXyme9rEqeg0WWslyKoO3
3X0TFa5KTr9sGl5jcgqhJklzvVUUEfzaEK3w1+B1zfmgv7ZfgMq8mCBSm6+DkhVG
nQIDAQAB
-----END PUBLIC KEY-----


RequestBody :{
  "amount": "100.00",
  "customResponse": "{}",
  "gatewayReferenceId": "806115044725",
  "gatewayResponseCode": "00",
  "gatewayResponseMessage": "Your transaction is successfule",
  "gatewayResponseStatus": "SUCCESS",
  "gatewayTransactionId": "YJPd0c077f39c45497912it3i0192",
  "merchantChannelId": "UAT",
  "merchantId": "UAT",
  "merchantRequestId": "TXN1234567",
  "payeeMcc": "1520",
  "payeeVpa": "test@transact",
  "payerMerchantCustomerId": "DEMO-CUST-5678",
  "payerName": "Customer Name",
  "payerVpa": "customer@xyz",
  "refUrl": "https://www.abcxyz.com/",
  "transactionTimestamp": "2021-07-23T13:45:00+05:30",
  "type": "MERCHANT_CREDITED_VIA_PAY",
  "udfParameters": "{}"
},
 

Signature :26b339a48db62a5b3e779a8e95e6c39d81942fe4549a1ce2b31cb8cd6e6b7781e9b1ac6c5e5b7e31ec722227ab2d7277964dd0ec7f2868f0ac5d76cb7ce3f723b5f708397d5889612a86548fa9963e4b4f1a3dab3cf51c8600ed8da3f4afae23034f2fb3f2c141325091e248c8912ef124121df7988fd52522843f7c0448727d5a6e8dd945a1bb31d7b120940ee6e96814075e46a380fd7da54066aee27fd1d1d8b495bd7a606e4e43aa65dfc4d54de9120bd3026acc19a3d51bb61ef98662bc5cc2bb3838707b779d8db4c049c4421a10d8f897c3f7d5190f668ed5f8b4567cfbb445d2ed288b1add3ea5eaecc3862c252a732aa97832c27461c299e3016f6c
//String input = RequestBody in String UTF-8 encoding
// Getting RequestBody through post . Please refer the RequestBody mentioned above
string input = await Request.Content.ReadAsStringAsync();



//String signature = headers["x-merchant-signature"]
string signature = Request.Headers.GetValues("X-Merchant-Payload-Signature").First(); // Signature Above



//Convert Public Key through Onine Tool
[Text] https://superdry.apphb.com/tools/online-rsa-key-converter]



string publicKey = "<RSAKeyValue><Modulus>j1UpJQHGsdlkvlJ6IBWDKwwczIM3e+NkoBcyUhxSGxB2C7W8x2hbU66uSqLDOaKeXXf/owvRJMLawHCBZgMv5pTKwFQllD63sZQEAl5dl+VpWf9jmy1BAE3/HBQYM6tEUykx7a9h+4f167v3JxPtPWpFcBEL3OdnGlYkV/4nhLFop0MSN2szDTfu4IYToy36QlzEhvS9xmNZbVhKkgJNfxAVgJDMmttJFQdF5ax4jENF04YHO+OPuTPW2HIDkImKXyme9rEqeg0WWslyKoO33X0TFa5KTr9sGl5jcgqhJklzvVUUEfzaEK3w1+B1zfmgv7ZfgMq8mCBSm6+DkhVGnQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>"
                                      


//Convert Request Body in UTF Bytes
byte[] InputdataForSignAsBytes = Encoding.UTF8.GetBytes(input);



byte[] signatureAsBytes = StringToByteArray(signature);

//Create Instance of Crypto
//Signature rsa = Signature.getInstance("SHA256withRSA");
RSACryptoServiceProvider rsaCryptoServiceProvider = new RSACryptoServiceProvider();
rsaCryptoServiceProvider.FromXmlString(publicKey);

//Get HasData of InputBody
var hashData = SHA256.Create().ComputeHash(InputdataForSignAsBytes);

                    
var result1 = rsaCryptoServiceProvider.VerifyData(InputdataForSignAsBytes, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
var result2 = rsaCryptoServiceProvider.VerifyHash(hashData, CryptoConfig.MapNameToOID("SHA256"), signatureAsBytes);
var result3 = rsaCryptoServiceProvider.VerifyHash(hashData, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
var result4 = rsaCryptoServiceProvider.VerifyData(InputdataForSignAsBytes, signatureAsBytes, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
                    
                    
Console.WriteLine(result1);
Console.WriteLine(result2);
Console.WriteLine(result3);
Console.WriteLine(result4);

//Supporting methods

 private string  ReadpublickeyEncodeTo64 (string publicKeyPath)
        {
            string encodedPublicKey = File
                .ReadAllText(publicKeyPath)
                .Replace("-----BEGIN PUBLIC KEY-----", string.Empty)
                .Replace("-----END PUBLIC KEY-----", string.Empty)
                .Trim();

            return EncodeTo64(encodedPublicKey);
        }

        public string EncodeTo64(string toEncode)

        {

            byte[] toEncodeAsBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);

            string returnValue = System.Convert.ToBase64String(toEncodeAsBytes);

            return returnValue;

        }
Rahul Kumar
  • 528
  • 1
  • 3
  • 19
  • 2
    The key is imported incorrectly. The X.509 key is double Base64 encoded and used as modulus. There are [online converters](https://superdry.apphb.com/tools/online-rsa-key-converter) for this. Alternatively you can import the X.509 key directly. How depends on your .NET version, which you did not post. – Topaco Jul 26 '21 at 09:18
  • "Not luck" may take the lead in the badly described error message list. Please clearly describe your error conditions clearly by hitting [edit]. – Maarten Bodewes Jul 26 '21 at 09:20
  • @Topaco i am importing the public key using the supporting method : ReadpublickeyEncodeTo64. The Public key was shared by third party. .Net Framework 4.6.2 – Rahul Kumar Jul 26 '21 at 09:39
  • @MaartenBodewes Hello Maarten, I am getting false response. Please suggest. Thanks – Rahul Kumar Jul 26 '21 at 09:41
  • You are applying base 64 encoding. You should be **decoding** not encoding. Also, the public key is in a structure called SubjectPublicKeyInfo (which is part of X.509 as Topaco indicated). You should search this site to find out how to decode that to a public key object instead of using XML (incorrectly, the public key consist of both modulus & public exponent). – Maarten Bodewes Jul 26 '21 at 09:44
  • 1
    It is clear that you are using `ReadpublickeyEncodeTo64`, but the import is nevertheless wrong (as described above). As said, use an online converter or import the X.509 key directly. The latter is not supported by .NET Framework, i.e. you need e.g. BouncyCastle. – Topaco Jul 26 '21 at 09:47
  • Also, how sure are you that PSS is used and that SHA-256 is applied for both digests? And regarding a JSON object as message: How is this serialized? Any deviation from the signed message, e.g. blanks (as in the posted message) will cause the verification to fail. – Topaco Jul 26 '21 at 09:55
  • @Topaco This was inform by Third Party "At the time of onboarding PSP will share a public key with the merchant. The algorithm used for creating the signature is SHA256 RSA with PSS padding. Following snippet shows how merchant has to validate the signature at their end." JAVA CODE ``` String input = RequestBody in String UTF-8 encoding String signature = headers["x-merchant-signature"] Signature rsa = Signature.getInstance("SHA256withRSA"); rsa.initVerify(getPublic(keyFile)); rsa.update(input.getBytes("utf-8")); boolean isSignatureSame = rsa.verify(Hex.decode(signature)); ``` – Rahul Kumar Jul 26 '21 at 10:10
  • @Topaco I have Converted the Public key through Online Converter you shared. After using the same converted XML. still getting false response.. Please help – Rahul Kumar Jul 26 '21 at 10:11
  • Please edit the question and post the converted key you are using. – Topaco Jul 26 '21 at 10:14
  • @Topaco I have added the converted key inline in code. please help also using the request body json object and converting the same. – Rahul Kumar Jul 26 '21 at 10:24
  • Are the dots in `"gatewayTransactionId": "XYZd0c077f39c454979..."` real or did you truncate the data? Or in general are the data (message, signature, key) valid and consistent, i.e. are they definitely verifiable? – Topaco Jul 26 '21 at 10:29
  • @Topaco, I just upaded the json object they shared recently.. – Rahul Kumar Jul 26 '21 at 10:35
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/235300/discussion-between-topaco-and-rahul-kumar). – Topaco Jul 26 '21 at 10:59

0 Answers0