mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add Mono compatibility for RSA-PSS
This commit is contained in:
parent
9c3ddf11fb
commit
d29f7b27a7
2 changed files with 73 additions and 1 deletions
62
src/LibHac/Compat.cs
Normal file
62
src/LibHac/Compat.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
#if NETFRAMEWORK
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace LibHac
|
||||
{
|
||||
internal class Compat
|
||||
{
|
||||
public static bool IsMono { get; } = Type.GetType("Mono.Runtime") != null;
|
||||
|
||||
public static bool Rsa2048PssVerifyMono(byte[] data, byte[] signature, byte[] modulus)
|
||||
{
|
||||
const int rsaLen = 0x100;
|
||||
const int digestLen = 0x20;
|
||||
|
||||
const int hashOffset = rsaLen - digestLen - 1;
|
||||
const int saltOffset = hashOffset - digestLen;
|
||||
const int padEnd = saltOffset - 1;
|
||||
|
||||
SHA256 sha = SHA256.Create();
|
||||
var message = new byte[rsaLen];
|
||||
|
||||
BigInteger decInt = BigInteger.ModPow(Crypto.GetBigInteger(signature), new BigInteger(65537), Crypto.GetBigInteger(modulus));
|
||||
byte[] decBytes = decInt.ToByteArray();
|
||||
|
||||
if (decBytes[0] != 0xBC) return false;
|
||||
|
||||
Array.Reverse(decBytes);
|
||||
Array.Copy(decBytes, 0, message, message.Length - decBytes.Length, decBytes.Length);
|
||||
|
||||
var hashBuf = new byte[0x24];
|
||||
Array.Copy(message, hashOffset, hashBuf, 0, digestLen);
|
||||
|
||||
ref byte seed = ref hashBuf[0x23];
|
||||
|
||||
for (int i = 0; i < hashOffset; i += 0x20)
|
||||
{
|
||||
Util.XorArrays(message.AsSpan(i, digestLen), sha.ComputeHash(hashBuf));
|
||||
seed++;
|
||||
}
|
||||
|
||||
message[0] &= 0x7F;
|
||||
|
||||
if (!Util.IsEmpty(message.AsSpan(0, padEnd)) || message[padEnd] != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var prefix = new byte[8];
|
||||
byte[] digest = sha.ComputeHash(data);
|
||||
|
||||
sha.TransformBlock(prefix, 0, prefix.Length, null, 0);
|
||||
sha.TransformBlock(digest, 0, digestLen, null, 0);
|
||||
sha.TransformFinalBlock(message, saltOffset, digestLen);
|
||||
|
||||
return Util.SpansEqual(hashBuf.AsSpan(0, 0x20), sha.Hash);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -94,7 +94,7 @@ namespace LibHac
|
|||
}
|
||||
}
|
||||
|
||||
private static BigInteger GetBigInteger(byte[] bytes)
|
||||
internal static BigInteger GetBigInteger(byte[] bytes)
|
||||
{
|
||||
var signPadded = new byte[bytes.Length + 1];
|
||||
Buffer.BlockCopy(bytes, 0, signPadded, 1, bytes.Length);
|
||||
|
@ -156,6 +156,15 @@ namespace LibHac
|
|||
|
||||
public static Validity Rsa2048PssVerify(byte[] data, byte[] signature, byte[] modulus)
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
if (true)
|
||||
{
|
||||
return Compat.Rsa2048PssVerifyMono(data, signature, modulus)
|
||||
? Validity.Valid
|
||||
: Validity.Invalid;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_RSA_CNG
|
||||
using (RSA rsa = new RSACng())
|
||||
#else
|
||||
|
@ -172,6 +181,7 @@ namespace LibHac
|
|||
|
||||
public static byte[] DecryptTitleKey(byte[] titleKeyblock, RSAParameters rsaParams)
|
||||
{
|
||||
// todo: Does this work on Mono?
|
||||
#if USE_RSA_CNG
|
||||
RSA rsa = new RSACng();
|
||||
#else
|
||||
|
|
Loading…
Reference in a new issue