lib_unity_purchase/Runtime/Security/RSAPubKey.cs

92 lines
3.2 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using LipingShare.LCLib.Asn1Processor;
using System.Security.Cryptography;
namespace UnityEngine.Purchasing.Security
{
internal class RSAKey
{
public RSACryptoServiceProvider rsa { get; private set; }
public RSAKey(Asn1Node n)
{
rsa = ParseNode(n);
}
public RSAKey(byte[] data)
{
using (var stm = new System.IO.MemoryStream(data))
{
Asn1Parser parser = new Asn1Parser();
parser.LoadData(stm);
rsa = ParseNode(parser.RootNode);
}
}
/**
* Public verification of a message
*/
public bool VerifySha1(byte[] message, byte[] signature)
{
var sha1hash = new SHA1Managed();
var msgHash = sha1hash.ComputeHash(message);
// The data is already hashed so we don't need to specify a hashing algorithm.
return rsa.VerifyHash(msgHash, null, signature);
}
public bool VerifySha256(byte[] message, byte[] signature)
{
var sha256hash = new SHA256Managed();
var msgHash = sha256hash.ComputeHash(message);
// The data is already hashed so we don't need to specify a hashing algorithm.
return rsa.VerifyHash(msgHash, CryptoConfig.MapNameToOID("SHA256"), signature);
}
/**
* Parses an DER encoded RSA public key:
* It will only try to get the mod and the exponent
*/
private RSACryptoServiceProvider ParseNode(Asn1Node n)
{
if ((n.Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE &&
n.ChildNodeCount == 2 &&
(n.GetChildNode(0).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.SEQUENCE &&
(n.GetChildNode(0).GetChildNode(0).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.OBJECT_IDENTIFIER &&
n.GetChildNode(0).GetChildNode(0).GetDataStr(false) == "1.2.840.113549.1.1.1" &&
(n.GetChildNode(1).Tag & Asn1Tag.TAG_MASK) == Asn1Tag.BIT_STRING)
{
var seq = n.GetChildNode(1).GetChildNode(0);
if (seq.ChildNodeCount == 2)
{
byte[] data = seq.GetChildNode(0).Data;
byte[] rawMod = new byte[data.Length - 1];
System.Array.Copy(data, 1, rawMod, 0, data.Length - 1);
var modulus = System.Convert.ToBase64String(rawMod);
var exponent = System.Convert.ToBase64String(seq.GetChildNode(1).Data);
var result = new RSACryptoServiceProvider();
result.FromXmlString(ToXML(modulus, exponent));
return result;
}
}
throw new InvalidRSAData();
}
private string ToXML(string modulus, string exponent)
{
return "<RSAKeyValue><Modulus>" + modulus + "</Modulus>" +
"<Exponent>" + exponent + "</Exponent></RSAKeyValue>";
}
}
/// <summary>
/// An IAP Security exception indicating some invalid data parsing an RSA node.
/// </summary>
public class InvalidRSAData : IAPSecurityException { }
}