CPF/CPF.Mac/Mac/Security/SecKey.cs
2023-11-21 23:05:03 +08:00

232 lines
6.6 KiB
C#

using CPF.Mac.CoreFoundation;
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
namespace CPF.Mac.Security
{
public class SecKey : INativeObject, IDisposable
{
internal IntPtr handle;
private long BlockSize
{
get
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
return (long)SecKeyGetBlockSize(handle);
}
}
public IntPtr Handle => handle;
public SecKey(IntPtr handle)
: this(handle, owns: false)
{
}
[Preserve(Conditional = true)]
public SecKey(IntPtr handle, bool owns)
{
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security", EntryPoint = "SecKeyGetTypeID")]
public static extern int GetTypeID();
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern SecStatusCode SecKeyGeneratePair(IntPtr dictHandle, out IntPtr pubKey, out IntPtr privKey);
public static SecStatusCode GenerateKeyPair(NSDictionary parameters, out SecKey publicKey, out SecKey privateKey)
{
if (parameters == null)
{
throw new ArgumentNullException("parameters");
}
IntPtr pubKey;
IntPtr privKey;
SecStatusCode num = SecKeyGeneratePair(parameters.Handle, out pubKey, out privKey);
if (num == SecStatusCode.Success)
{
publicKey = new SecKey(pubKey, owns: true);
privateKey = new SecKey(privKey, owns: true);
return num;
}
publicKey = (privateKey = null);
return num;
}
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern IntPtr SecKeyGetBlockSize(IntPtr handle);
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern SecStatusCode SecKeyRawSign(IntPtr handle, SecPadding padding, IntPtr dataToSign, IntPtr dataToSignLen, IntPtr sig, IntPtr sigLen);
private unsafe SecStatusCode RawSign(SecPadding padding, IntPtr dataToSign, int dataToSignLen, out byte[] result)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
result = new byte[(int)SecKeyGetBlockSize(handle)];
fixed (byte* value = &result[0])
{
return SecKeyRawSign(handle, padding, dataToSign, (IntPtr)dataToSignLen, (IntPtr)(void*)value, (IntPtr)result.Length);
}
}
private unsafe SecStatusCode RawSign(SecPadding padding, byte[] dataToSign, out byte[] result)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
if (dataToSign == null)
{
throw new ArgumentNullException("dataToSign");
}
result = new byte[(int)SecKeyGetBlockSize(handle)];
fixed (byte* value = &dataToSign[0])
{
fixed (byte* value2 = &result[0])
{
return SecKeyRawSign(handle, padding, (IntPtr)(void*)value, (IntPtr)dataToSign.Length, (IntPtr)(void*)value2, (IntPtr)result.Length);
}
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern SecStatusCode SecKeyRawVerify(IntPtr handle, SecPadding padding, IntPtr signedData, IntPtr signedLen, IntPtr sign, IntPtr signLen);
public SecStatusCode RawVerify(SecPadding padding, IntPtr signedData, int signedDataLen, IntPtr signature, int signatureLen)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
return SecKeyRawVerify(handle, padding, signedData, (IntPtr)signedDataLen, signature, (IntPtr)signatureLen);
}
public unsafe SecStatusCode RawVerify(SecPadding padding, byte[] signedData, byte[] signature)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
if (signature == null)
{
throw new ArgumentNullException("signature");
}
if (signedData == null)
{
throw new ArgumentNullException("signedData");
}
fixed (byte* value2 = &signature[0])
{
fixed (byte* value = &signedData[0])
{
return SecKeyRawVerify(handle, padding, (IntPtr)(void*)value, (IntPtr)signedData.Length, (IntPtr)(void*)value2, (IntPtr)signature.Length);
}
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern SecStatusCode SecKeyEncrypt(IntPtr handle, SecPadding padding, IntPtr plainText, IntPtr playLen, IntPtr cipherText, IntPtr cipherLen);
public SecStatusCode Encrypt(SecPadding padding, IntPtr plainText, int playLen, IntPtr cipherText, int cipherLen)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
return SecKeyEncrypt(handle, padding, plainText, (IntPtr)playLen, cipherText, (IntPtr)cipherLen);
}
public unsafe SecStatusCode Encrypt(SecPadding padding, byte[] plainText, byte[] cipherText)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
if (cipherText == null)
{
throw new ArgumentNullException("cipherText");
}
if (plainText == null)
{
throw new ArgumentNullException("plainText");
}
fixed (byte* value2 = &cipherText[0])
{
fixed (byte* value = &plainText[0])
{
return SecKeyEncrypt(handle, padding, (IntPtr)(void*)value, (IntPtr)plainText.Length, (IntPtr)(void*)value2, (IntPtr)cipherText.Length);
}
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern SecStatusCode SecKeyDecrypt(IntPtr handle, SecPadding padding, IntPtr cipherText, IntPtr cipherLen, IntPtr plainText, IntPtr playLen);
public SecStatusCode Decrypt(SecPadding padding, IntPtr cipherText, int cipherLen, IntPtr plainText, int playLen)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
return SecKeyDecrypt(handle, padding, cipherText, (IntPtr)cipherLen, plainText, (IntPtr)playLen);
}
public unsafe SecStatusCode Decrypt(SecPadding padding, byte[] cipherText, byte[] plainText)
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecKey");
}
if (cipherText == null)
{
throw new ArgumentNullException("cipherText");
}
if (plainText == null)
{
throw new ArgumentNullException("plainText");
}
fixed (byte* value = &cipherText[0])
{
fixed (byte* value2 = &plainText[0])
{
return SecKeyDecrypt(handle, padding, (IntPtr)(void*)value, (IntPtr)cipherText.Length, (IntPtr)(void*)value2, (IntPtr)plainText.Length);
}
}
}
~SecKey()
{
Dispose(disposing: false);
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public virtual void Dispose(bool disposing)
{
if (handle != IntPtr.Zero)
{
CFObject.CFRelease(handle);
handle = IntPtr.Zero;
}
}
}
}