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

154 lines
3.3 KiB
C#

using CPF.Mac.CoreFoundation;
using CPF.Mac.Foundation;
using CPF.Mac.ObjCRuntime;
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;
namespace CPF.Mac.Security
{
public class SecCertificate : INativeObject, IDisposable
{
internal IntPtr handle;
public string SubjectSummary
{
get
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecCertificate");
}
IntPtr obj = SecCertificateCopySubjectSummary(handle);
string result = CFString.FetchString(obj);
CFObject.CFRelease(obj);
return result;
}
}
public NSData DerData
{
get
{
if (handle == IntPtr.Zero)
{
throw new ObjectDisposedException("SecCertificate");
}
IntPtr value = SecCertificateCopyData(handle);
if (value == IntPtr.Zero)
{
throw new ArgumentException("Not a valid certificate");
}
return new NSData(value);
}
}
public IntPtr Handle => handle;
internal SecCertificate(IntPtr handle)
: this(handle, owns: false)
{
}
[Preserve(Conditional = true)]
internal SecCertificate(IntPtr handle, bool owns)
{
if (handle == IntPtr.Zero)
{
throw new Exception("Invalid handle");
}
this.handle = handle;
if (!owns)
{
CFObject.CFRetain(handle);
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security", EntryPoint = "SecCertificateGetTypeID")]
public static extern int GetTypeID();
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern IntPtr SecCertificateCreateWithData(IntPtr allocator, IntPtr cfData);
public SecCertificate(NSData data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
Initialize(data);
}
public SecCertificate(byte[] data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
using (NSData data2 = NSData.FromArray(data))
{
Initialize(data2);
}
}
public SecCertificate(X509Certificate certificate)
{
if (certificate == null)
{
throw new ArgumentNullException("certificate");
}
using (NSData data = NSData.FromArray(certificate.Export(X509ContentType.Cert)))
{
Initialize(data);
}
}
public SecCertificate(X509Certificate2 certificate)
{
if (certificate == null)
{
throw new ArgumentNullException("certificate");
}
using (NSData data = NSData.FromArray(certificate.RawData))
{
Initialize(data);
}
}
private void Initialize(NSData data)
{
handle = SecCertificateCreateWithData(IntPtr.Zero, data.Handle);
if (handle == IntPtr.Zero)
{
throw new ArgumentException("Not a valid DER-encoded X.509 certificate");
}
}
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern IntPtr SecCertificateCopySubjectSummary(IntPtr cert);
[DllImport("/System/Library/Frameworks/Security.framework/Security")]
private static extern IntPtr SecCertificateCopyData(IntPtr cert);
~SecCertificate()
{
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;
}
}
}
}