@@ -6,6 +6,23 @@ namespace KeeShare.Tests
66{
77 public class SignatureVerificationTests
88 {
9+ /// <summary>
10+ /// Helper to convert bytes to hex string (KeeShare format)
11+ /// </summary>
12+ private static string BytesToHex ( byte [ ] bytes )
13+ {
14+ return BitConverter . ToString ( bytes ) . Replace ( "-" , "" ) . ToLowerInvariant ( ) ;
15+ }
16+
17+ /// <summary>
18+ /// Helper to format signature in KeeShare format: "rsa|<hex>"
19+ /// </summary>
20+ private static byte [ ] FormatKeeShareSignature ( byte [ ] signature )
21+ {
22+ string hex = BytesToHex ( signature ) ;
23+ return Encoding . UTF8 . GetBytes ( $ "rsa|{ hex } ") ;
24+ }
25+
926 [ Fact ]
1027 public void VerifySignature_WithValidSignature_ReturnsTrue ( )
1128 {
@@ -15,12 +32,27 @@ public void VerifySignature_WithValidSignature_ReturnsTrue()
1532 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
1633 byte [ ] hash = SHA256 . HashData ( testData ) ;
1734 byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
18- string signatureBase64 = Convert . ToBase64String ( signature ) ;
19- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureBase64 ) ;
35+ byte [ ] signatureData = FormatKeeShareSignature ( signature ) ;
2036 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
2137 Assert . True ( result , "Signature verification should succeed with valid signature" ) ;
2238 }
2339
40+ [ Fact ]
41+ public void VerifySignature_WithValidSignatureWithoutPrefix_ReturnsTrue ( )
42+ {
43+ using var rsa = RSA . Create ( 2048 ) ;
44+ var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
45+ var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
46+ byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
47+ byte [ ] hash = SHA256 . HashData ( testData ) ;
48+ byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
49+ // Hex without "rsa|" prefix should also work
50+ string signatureHex = BytesToHex ( signature ) ;
51+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureHex ) ;
52+ bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
53+ Assert . True ( result , "Signature verification should succeed with hex signature without prefix" ) ;
54+ }
55+
2456 [ Fact ]
2557 public void VerifySignature_WithInvalidSignature_ReturnsFalse ( )
2658 {
@@ -30,8 +62,7 @@ public void VerifySignature_WithInvalidSignature_ReturnsFalse()
3062 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
3163 byte [ ] invalidSignature = new byte [ 256 ] ;
3264 new Random ( ) . NextBytes ( invalidSignature ) ;
33- string signatureBase64 = Convert . ToBase64String ( invalidSignature ) ;
34- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureBase64 ) ;
65+ byte [ ] signatureData = FormatKeeShareSignature ( invalidSignature ) ;
3566 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
3667 Assert . False ( result , "Signature verification should fail with invalid signature" ) ;
3768 }
@@ -45,8 +76,7 @@ public void VerifySignature_WithTamperedData_ReturnsFalse()
4576 byte [ ] originalData = Encoding . UTF8 . GetBytes ( "Original KDBX data" ) ;
4677 byte [ ] hash = SHA256 . HashData ( originalData ) ;
4778 byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
48- string signatureBase64 = Convert . ToBase64String ( signature ) ;
49- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureBase64 ) ;
79+ byte [ ] signatureData = FormatKeeShareSignature ( signature ) ;
5080 byte [ ] tamperedData = Encoding . UTF8 . GetBytes ( "Tampered KDBX data" ) ;
5181 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , tamperedData , signatureData ) ;
5282 Assert . False ( result , "Signature verification should fail when data is tampered" ) ;
@@ -62,8 +92,7 @@ public void VerifySignature_WithPemFormattedCertificate_ReturnsTrue()
6292 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
6393 byte [ ] hash = SHA256 . HashData ( testData ) ;
6494 byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
65- string signatureBase64 = Convert . ToBase64String ( signature ) ;
66- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureBase64 ) ;
95+ byte [ ] signatureData = FormatKeeShareSignature ( signature ) ;
6796 bool result = KeeShare . VerifySignatureCore ( publicKeyCertPem , testData , signatureData ) ;
6897 Assert . True ( result , "Signature verification should work with PEM formatted certificate" ) ;
6998 }
@@ -72,7 +101,7 @@ public void VerifySignature_WithPemFormattedCertificate_ReturnsTrue()
72101 public void VerifySignature_WithEmptyCertificate_ReturnsFalse ( )
73102 {
74103 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test data" ) ;
75- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "fake signature " ) ;
104+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "rsa|abcd1234 " ) ;
76105 bool result = KeeShare . VerifySignatureCore ( "" , testData , signatureData ) ;
77106 Assert . False ( result , "Signature verification should fail with empty certificate" ) ;
78107 }
@@ -83,7 +112,7 @@ public void VerifySignature_WithNullData_ReturnsFalse()
83112 using var rsa = RSA . Create ( 2048 ) ;
84113 var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
85114 var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
86- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "signature " ) ;
115+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "rsa|abcd1234 " ) ;
87116 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , null , signatureData ) ;
88117 Assert . False ( result , "Signature verification should fail with null data" ) ;
89118 }
@@ -94,21 +123,35 @@ public void VerifySignature_WithEmptyData_ReturnsFalse()
94123 using var rsa = RSA . Create ( 2048 ) ;
95124 var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
96125 var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
97- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "signature " ) ;
126+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "rsa|abcd1234 " ) ;
98127 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , new byte [ 0 ] , signatureData ) ;
99128 Assert . False ( result , "Signature verification should fail with empty data" ) ;
100129 }
101130
102131 [ Fact ]
103- public void VerifySignature_WithMalformedBase64Signature_ReturnsFalse ( )
132+ public void VerifySignature_WithMalformedHexSignature_ReturnsFalse ( )
133+ {
134+ using var rsa = RSA . Create ( 2048 ) ;
135+ var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
136+ var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
137+ byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test data" ) ;
138+ // Invalid hex characters
139+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "rsa|not-valid-hex!@#$GHIJ" ) ;
140+ bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
141+ Assert . False ( result , "Signature verification should fail with malformed hex" ) ;
142+ }
143+
144+ [ Fact ]
145+ public void VerifySignature_WithOddLengthHex_ReturnsFalse ( )
104146 {
105147 using var rsa = RSA . Create ( 2048 ) ;
106148 var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
107149 var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
108150 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test data" ) ;
109- byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "not-valid-base64!@#$" ) ;
151+ // Odd-length hex string (invalid)
152+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( "rsa|abc" ) ;
110153 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
111- Assert . False ( result , "Signature verification should fail with malformed base64 " ) ;
154+ Assert . False ( result , "Signature verification should fail with odd-length hex " ) ;
112155 }
113156
114157 [ Fact ]
@@ -120,11 +163,44 @@ public void VerifySignature_WithSignatureContainingWhitespace_ReturnsTrue()
120163 byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
121164 byte [ ] hash = SHA256 . HashData ( testData ) ;
122165 byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
123- string signatureBase64 = Convert . ToBase64String ( signature ) ;
124- string signatureWithWhitespace = $ "\r \n { signatureBase64 } \r \n ";
166+ string signatureHex = BytesToHex ( signature ) ;
167+ // Add whitespace around the signature
168+ string signatureWithWhitespace = $ "\r \n rsa|{ signatureHex } \r \n ";
125169 byte [ ] signatureData = Encoding . UTF8 . GetBytes ( signatureWithWhitespace ) ;
126170 bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
127171 Assert . True ( result , "Signature verification should handle whitespace in signature" ) ;
128172 }
173+
174+ [ Fact ]
175+ public void VerifySignature_WithUppercaseHex_ReturnsTrue ( )
176+ {
177+ using var rsa = RSA . Create ( 2048 ) ;
178+ var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
179+ var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
180+ byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
181+ byte [ ] hash = SHA256 . HashData ( testData ) ;
182+ byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
183+ // Use uppercase hex
184+ string signatureHex = BitConverter . ToString ( signature ) . Replace ( "-" , "" ) . ToUpperInvariant ( ) ;
185+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( $ "rsa|{ signatureHex } ") ;
186+ bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
187+ Assert . True ( result , "Signature verification should handle uppercase hex" ) ;
188+ }
189+
190+ [ Fact ]
191+ public void VerifySignature_WithUppercaseRsaPrefix_ReturnsTrue ( )
192+ {
193+ using var rsa = RSA . Create ( 2048 ) ;
194+ var publicKeyBytes = rsa . ExportSubjectPublicKeyInfo ( ) ;
195+ var publicKeyCert = Convert . ToBase64String ( publicKeyBytes ) ;
196+ byte [ ] testData = Encoding . UTF8 . GetBytes ( "Test KDBX data content" ) ;
197+ byte [ ] hash = SHA256 . HashData ( testData ) ;
198+ byte [ ] signature = rsa . SignHash ( hash , HashAlgorithmName . SHA256 , RSASignaturePadding . Pkcs1 ) ;
199+ string signatureHex = BytesToHex ( signature ) ;
200+ // Use uppercase "RSA|" prefix
201+ byte [ ] signatureData = Encoding . UTF8 . GetBytes ( $ "RSA|{ signatureHex } ") ;
202+ bool result = KeeShare . VerifySignatureCore ( publicKeyCert , testData , signatureData ) ;
203+ Assert . True ( result , "Signature verification should handle uppercase RSA prefix" ) ;
204+ }
129205 }
130206}
0 commit comments