@@ -279,18 +279,18 @@ private byte[] DecryptMessageInternal(byte[] encryptedBody, byte[] key, byte[] i
279
279
0x1C3AF78Eu
280
280
} ;
281
281
282
- public virtual byte [ ] DecryptVfs ( byte [ ] dbData , bool skipVerification = true )
282
+ public virtual byte [ ] DecryptVfs ( byte [ ] dbData , bool skipVerification = false )
283
283
{
284
284
var inputStream = new MemoryStream ( dbData ) ;
285
285
var inputReader = new BinaryReader ( inputStream ) ;
286
286
287
287
if ( inputReader . ReadUInt32 ( ) != VfsHeaderMagic )
288
288
throw new InvalidDataException ( "Invalid database header." ) ;
289
289
290
- return DecryptVfsInternal ( dbData , inputReader , skipVerification ) ;
290
+ return DecryptVfsInternal ( dbData , inputReader , skipVerification , ! skipVerification ? DeriveVfsPublicKey ( VfsCertConstants ) : "" ) ;
291
291
}
292
292
293
- protected byte [ ] DecryptVfsInternal ( byte [ ] dbData , BinaryReader inputReader , bool skipVerification , int headerOffset = 0 )
293
+ protected static byte [ ] DecryptVfsInternal ( byte [ ] dbData , BinaryReader inputReader , bool skipVerification , string publicKey = "" , int headerOffset = 0 )
294
294
{
295
295
const int fullHeaderSize = 0x4 + 0x4 + 0x10 + 0x10 + 0x4 + 0x10 + 0x100 ;
296
296
var headerSize = fullHeaderSize - headerOffset ;
@@ -303,27 +303,10 @@ protected byte[] DecryptVfsInternal(byte[] dbData, BinaryReader inputReader, boo
303
303
var gcmIv = inputReader . ReadBytes ( 0x10 ) ;
304
304
var gcmAdd2 = inputReader . ReadUInt32 ( ) ;
305
305
var gcmTag = inputReader . ReadBytes ( 0x10 ) ;
306
- var verifySig = inputReader . ReadBytes ( 0x100 ) ;
306
+ var signature = inputReader . ReadBytes ( 0x100 ) ;
307
307
308
308
var gcmAdd = BitConverter . GetBytes ( gcmAdd1 ) . Concat ( BitConverter . GetBytes ( gcmAdd2 ) ) . ToArray ( ) ;
309
309
310
- if ( ! skipVerification )
311
- {
312
- var rsaEncPublicKey = Encoding . UTF8 . GetString ( VfsDerivePublicKey ( ) [ ..^ 1 ] ) ;
313
- using var rsaPublicKeyStringReader = new StringReader ( rsaEncPublicKey ) ;
314
- var rsaPublicKeyPemReader = new PemReader ( rsaPublicKeyStringReader ) ;
315
- if ( rsaPublicKeyPemReader . ReadObject ( ) is not RsaKeyParameters rsaPublicKey )
316
- throw new InvalidDataException ( "Failed to parse derived VFS public key." ) ;
317
-
318
- var signer = new RsaDigestSigner ( new Sha1Digest ( ) ) ;
319
- signer . Init ( false , rsaPublicKey ) ;
320
- signer . BlockUpdate ( gcmTag , 0 , gcmTag . Length ) ;
321
- var sigResult = signer . VerifySignature ( verifySig ) ;
322
-
323
- if ( ! sigResult )
324
- throw new InvalidDataException ( "Failed to verify VFS signature." ) ;
325
- }
326
-
327
310
var encryptedLength = dbData . Length - headerSize ;
328
311
var encryptedData = new byte [ encryptedLength + gcmTag . Length ] ;
329
312
if ( inputReader . Read ( encryptedData , 0 , encryptedLength ) != encryptedLength )
@@ -333,6 +316,17 @@ protected byte[] DecryptVfsInternal(byte[] dbData, BinaryReader inputReader, boo
333
316
334
317
inputReader . Dispose ( ) ;
335
318
319
+ if ( ! skipVerification )
320
+ {
321
+ var signedData = gcmTag . Concat ( BitConverter . GetBytes ( encryptedLength - 4 ) ) . ToArray ( ) ;
322
+
323
+ var rsa = RSA . Create ( ) ;
324
+ rsa . ImportFromPem ( publicKey ) ;
325
+ var sigResult = rsa . VerifyHash ( signedData , signature , HashAlgorithmName . SHA1 , RSASignaturePadding . Pkcs1 ) ;
326
+ if ( ! sigResult )
327
+ throw new InvalidDataException ( "Failed to verify VFS signature." ) ;
328
+ }
329
+
336
330
var gcm = new GcmBlockCipher ( new AesEngine ( ) ) ;
337
331
gcm . Init ( false , new AeadParameters ( new KeyParameter ( gcmKey ) , gcmTag . Length * 8 , gcmIv , gcmAdd ) ) ;
338
332
@@ -356,12 +350,9 @@ protected byte[] DecryptVfsInternal(byte[] dbData, BinaryReader inputReader, boo
356
350
: bodyData ;
357
351
}
358
352
359
- private byte [ ] VfsDerivePublicKey ( )
353
+ protected static string DeriveVfsPublicKey ( uint [ ] encCert , ulong seed = 0x8BE53A46A921AF07 , ulong add = 0x31D7038E3C2AB8B )
360
354
{
361
- const ulong roundConstant1 = 0x5851F42D4C957F2D ;
362
- const ulong roundConstant2 = 0x31D7038E3C2AB8B ;
363
-
364
- var round = 0x8BE53A46A921AF07 ;
355
+ var round = seed ;
365
356
var result = new byte [ 0x1c4 ] ;
366
357
using var outputStream = new MemoryStream ( result ) ;
367
358
using var outputWriter = new BinaryWriter ( outputStream ) ;
@@ -370,15 +361,15 @@ private byte[] VfsDerivePublicKey()
370
361
{
371
362
for ( int i = 0 ; i < 0x1c4 / 4 ; i ++ )
372
363
{
373
- var rk = VfsCertConstants [ i ] ;
364
+ var rk = encCert [ i ] ;
374
365
var rg = ( round ^ ( round >> 18 ) ) >> 27 ;
375
366
var rv = BitOperations . RotateRight ( ( uint ) rg , ( int ) ( round >> 59 ) ) ^ rk ;
376
367
outputWriter . Write ( rv ) ;
377
368
round = TransformConstant * round + add ;
378
369
}
379
370
}
380
371
381
- return result ;
372
+ return Encoding . UTF8 . GetString ( result [ .. ^ 1 ] ) ;
382
373
}
383
374
384
375
#endregion
0 commit comments