Can't verify signature in JAVA but success in .NET

We have old system using .NET 3.5 (run on Windows Server 2003 32bits) to verify e-receipts from our customers (all use SHA1RSA algorithm as agreement). We store their certificates in database in Base64 string. Old code look like that:

//Store certificates
String certificateEncodeBase64 = Convert.ToBase64String(byteArrayCertificateFile);

//Verify signatures

//Hash algorithm SHA-1
HashAlgorithm hashAlgrothm = new SHA1Managed();
//Data
byte[] data = System.Text.Encoding.UTF8.GetBytes(request.DataInUTF8);
//Signature
byte[] signature = Convert.FromBase64String(request.SignatureInBase64);
//Certificate
X509Certificate2 certificate = new X509Certificate2(Convert.FromBase64String(certEncodeBase64));
//Verify using algorithm RSA
RSACryptoServiceProvider pubKey = (RSACryptoServiceProvider)certificate.PublicKey.Key    
bool vr = pubKey.VerifyData(data, hashAlgrothm, signature);

Nothing issues except the performance is not good. That's why we want to move to new system using Java 1.7 (run on Windows Server 2012 64 bits). Our new code look like that:

//Using the same DB store certificates

//Verify signatures using Bouncy Castle JCE Provider

//Hash data using SHA-1
byte[] data_ = request.getDataInUTF8().getBytes("UTF-8");
MessageDigest messageDigest_ = MessageDigest.getInstance("SHA-1", "BC");
byte[] hashed = messageDigest.digest(data);
//Signature
byte [] signature = new BASE64Decoder().decodeBuffer(request.getSignatureInBase64());
//Certificate
CertificateFactory certificateFactory = CertificateFactory.getInstance("X509", "BC");
byte[] buffer = new BASE64Decoder().decodeBuffer(certEncodeBase64);
ByteArrayInputStream byteArrayCertificateInputStream = new ByteArrayInputStream(buffer);
Certificate certificate = certificateFactory.generateCertificate(byteArrayCertificateInputStream);
//Verify using algorithm RSA
Signature verifyEngine = Signature.getInstance("RSA", "BC");
verifyEngine.initVerify(certificate);
verifyEngine.update(hashed);
result = verifyEngine.verify(signature);

And we get this problem: In our test using all verified data taken from old system, new system verify some customer's data but some customers always return fail. For one failed example

Certificate in Base64

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

RawData

<HEADER><VERSION>1.0</VERSION><SENDER_CODE>TTSP_ICB</SENDER_CODE><SENDER_NAME>He Thong Thanh toan song phuong cua Ngan hang Vietinbank</SENDER_NAME><RECEIVER_CODE>TTSP_KBA</RECEIVER_CODE><RECEIVER_NAME>He thong Thanh toan song phuong cua Kho bac Nha nuoc</RECEIVER_NAME><TRAN_CODE>103</TRAN_CODE><MSG_ID>TTSP_ICB103004203763</MSG_ID><MSG_REFID /><SEND_DATE>04-03-2014 09:03:15</SEND_DATE><ORIGINAL_CODE>TTSP_ICB</ORIGINAL_CODE><ORIGINAL_NAME>He Thong Thanh toan song phuong cua Ngan hang Vietinbank</ORIGINAL_NAME><ORIGINAL_DATE>04-03-2014 09:03:15</ORIGINAL_DATE><ERROR_CODE /><ERROR_DESC /><SPARE1 /><SPARE2 /><SPARE3 /></HEADER><BODY><MT_ID>1420110300335833</MT_ID><SEND_BANK>89201001</SEND_BANK><RECEIVE_BANK>89701002</RECEIVE_BANK><CREATED_DATE>04-03-2014 09:26:24</CREATED_DATE><CREATOR>DD740063</CREATOR><MANAGER>DD740096</MANAGER><VERIFIED_DATE>04-03-2014 09:29:41</VERIFIED_DATE><F20>1474010300001334</F20><F23B>CRED</F23B><F26T>C</F26T><F32AS1>04-03-2014</F32AS1><F32AS2>VND</F32AS2><F32AS3>324000000.00</F32AS3><F33BS1>VND</F33BS1><F33BS2>324000000.00</F33BS2><F36 /><F50P1>VND101101001</F50P1><F50AP2 /><F50KP2>HUYNH THI KIM THOA</F50KP2><F51AP1S1 /><F51AP1S2 /><F51AP2 /><F52P1S1 /><F52P1S2 /><F52AP2>89201001</F52AP2><F52DP2>89201001</F52DP2><F53P1S1 /><F53P1S2 /><F53AP2 /><F53BP2 /><F53DP2 /><F54P1S1 /><F54P1S2 /><F54AP2 /><F54BP2 /><F54DP2 /><F55P1S1 /><F55P1S2 /><F55AP2 /><F55BP2 /><F55DP2 /><F56P1S1 /><F56P1S2 /><F56AP2 /><F56CP2 /><F56DP2 /><F57P1S1>C</F57P1S1><F57P1S2 /><F57AP2>89701002</F57AP2><F57BP2 /><F57CP2 /><F57DP2>KBNN PHU TAN - AN GIANG</F57DP2><F59P1>372301048091</F59P1><F59AP2 /><F59P2>UBND XA BINH THANH DONG#####</F59P2><F70 /><F71A>SHA</F71A><F71GS1 /><F71GS2 /><F72>UBND XA BINH THANH DONG NOP TIEN XE CHUYEN BENH</F72><F77B /><F77TS1 /><F77TS2 /><F77TS3 /><F77TS4 /><F77TS5 /><F77TS6 /><F77TS7 /><F77TS8 /><F77TS9 /><F77TS10 /><F77TS11 /><F77TS12 /><F77TS13 /><F77TS14 /><F77TS15 /><F77TS16 /><F77TS17 /><F77TS18 /><F77TS20 /><F77TS19 /></BODY>

Hash data in Base64 using SHA-1

KLpuojRk329lb++8CFKTFADh+3c=

Signature in Base64

KWMVPKpQ8Pg3fUij9pND/me3orlplkbdNLWcH5rztMhIz0BjTN8CJJHiFrN1w1Qkih0lSl24zDE5nbYw/vo+EG3tSJzC+d/h7wkm6ad9LHt5Y0cxYRIKWSHJRbCjkOXcO/eE3KZaAZONGEVWt1bLkL3zERN11RAyZjFEzrGE7WbiLvp/51Cy5zBU/mLJts3waiEpqycjOOVNo59ICulwclhcPR+gVzcwh65oxBelI+XRbRN1PfEw5J48R6fTwmdtRzD+OJejMLHmiHUBErRNo+XG7Q5ovwY1AG2GfCOCYIOu2jYd5DD9ZDuLEMa54Uz7cy3UbciXG5/n+7GtLfGeHA==

For investigate further, we debug class DigestSignatureSpi that Bouncy Castle use to verify at line

try
{
    sig = cipher.processBlock(sigBytes, 0, sigBytes.length);

    expected = derEncode(hash);
}
catch (Exception e)
{
    return false;
}

sig is

[48, 33, 48, 9, 6, 5, 43, 14, 3, 2, 26, 5, 0, 4, 20, 40, -70, 110, -94, 52, 100, -33, 111, 101, 111, -17, -68, 8, 82, -109, 20, 0, -31, -5, 119]

while expected is

[40, -70, 110, -94, 52, 100, -33, 111, 101, 111, -17, -68, 8, 82, -109, 20, 0, -31, -5, 119]

This debug show sig include expected bit (last 20 bytes).

I don't know what is wrong. PLEASE HELP!!! Thank you.

Answers


I don't think you're using the correct signature algorithm. The documentation suggests that you should probably be using SHA1withRSA as the signature algorithm. This is further indicated by the signature vs. expected. The "expected" value you give is the raw SHA-1 hash, whereas the signature you're providing is a PKCS#1 v1.5 DigestInfo (See RFC2313, section 10.1.2).


I think you should change it to Signature verifyEngine = Signature.getInstance("NoneWithRSA"); and it should work. As far as I rember that one returns the digest and not a DigestInfo structure.


Need Your Help

Why is my UIImage rotated after I edit its pixels?

ios objective-c uiimage

I scoured SO and some web tutorials to get this IBAction together that edits the pixels of an UIImage. The edit it supposed to make the photo greyscale, but it also rotates the image too, and I can't

How do I Call highlightRow of ListView.renderRow()?

listview react-native

I can't seem to figure out how to use the highlightRow attribute ListView's renderRow.