From 61bca1c0e7d93df49e38f53409ef257ec06d8613 Mon Sep 17 00:00:00 2001 From: feyris-tan <4116042+feyris-tan@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:07:31 +0100 Subject: [PATCH] Began building licensing wizard. --- .gitignore | 8 + .../Sophia.Net.DRM.csproj | 3 +- Sophia.Net.DRM/Sophia.Net.DRM.sln | 31 ++ Sophia.Net.DRM/SophiaNetDrmApi.cs | 350 ++++++++++++++++++ Sophia.Net.DRM/SophiaNetEntitlements.cs | 88 +++++ Voile.Sqlite/Class1.cs | 16 - Voile.slnx | 2 +- Voile/FirstRunWizard.Designer.cs | 265 +++++++++---- Voile/FirstRunWizard.cs | 195 +++++++++- Voile/FirstRunWizard.resx | 13 + Voile/Properties/Resources.Designer.cs | 50 +++ Voile/Properties/Resources.resx | 15 + Voile/Resources/SETUPAPI_18_1_32x32x4.png | Bin 0 -> 394 bytes Voile/Resources/TRFFC09_1_32x32x4.png | Bin 0 -> 341 bytes Voile/Resources/TRFFC10A_1_32x32x4.png | Bin 0 -> 382 bytes Voile/Resources/TRFFC10B_1_32x32x4.png | Bin 0 -> 342 bytes Voile/Resources/TRFFC10C_1_32x32x4.png | Bin 0 -> 376 bytes Voile/Resources/iblicense_133_1_32x32x4.png | Bin 0 -> 360 bytes Voile/Resources/sophianet-cert.cer | Bin 0 -> 2602 bytes Voile/Voile.csproj | 2 +- Voile/VoileContext.cs | 4 +- 21 files changed, 945 insertions(+), 97 deletions(-) rename Voile.Sqlite/Voile.SQLite.csproj => Sophia.Net.DRM/Sophia.Net.DRM.csproj (60%) create mode 100644 Sophia.Net.DRM/Sophia.Net.DRM.sln create mode 100644 Sophia.Net.DRM/SophiaNetDrmApi.cs create mode 100644 Sophia.Net.DRM/SophiaNetEntitlements.cs delete mode 100644 Voile.Sqlite/Class1.cs create mode 100644 Voile/Resources/SETUPAPI_18_1_32x32x4.png create mode 100644 Voile/Resources/TRFFC09_1_32x32x4.png create mode 100644 Voile/Resources/TRFFC10A_1_32x32x4.png create mode 100644 Voile/Resources/TRFFC10B_1_32x32x4.png create mode 100644 Voile/Resources/TRFFC10C_1_32x32x4.png create mode 100644 Voile/Resources/iblicense_133_1_32x32x4.png create mode 100644 Voile/Resources/sophianet-cert.cer diff --git a/.gitignore b/.gitignore index c4721f7..263141f 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,11 @@ /Voile.Sqlite/bin/Debug/net8.0 /Voile.Sqlite/obj/Debug/net8.0 /Voile.Sqlite/obj +/Sophia.Net.DRM/.vs/ProjectEvaluation +/Sophia.Net.DRM/.vs/Sophia.Net.DRM/CopilotIndices/17.14.1431.25910 +/Sophia.Net.DRM/.vs/Sophia.Net.DRM/DesignTimeBuild +/Sophia.Net.DRM/.vs/Sophia.Net.DRM/FileContentIndex +/Sophia.Net.DRM/.vs/Sophia.Net.DRM/v17 +/Sophia.Net.DRM/bin/Debug/net8.0 +/Sophia.Net.DRM/obj/Debug/net8.0 +/Sophia.Net.DRM/obj diff --git a/Voile.Sqlite/Voile.SQLite.csproj b/Sophia.Net.DRM/Sophia.Net.DRM.csproj similarity index 60% rename from Voile.Sqlite/Voile.SQLite.csproj rename to Sophia.Net.DRM/Sophia.Net.DRM.csproj index aa499ab..7867787 100644 --- a/Voile.Sqlite/Voile.SQLite.csproj +++ b/Sophia.Net.DRM/Sophia.Net.DRM.csproj @@ -7,8 +7,7 @@ - - + diff --git a/Sophia.Net.DRM/Sophia.Net.DRM.sln b/Sophia.Net.DRM/Sophia.Net.DRM.sln new file mode 100644 index 0000000..66643b3 --- /dev/null +++ b/Sophia.Net.DRM/Sophia.Net.DRM.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36705.20 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sophia.Net.DRM", "Sophia.Net.DRM.csproj", "{30741C45-1A9C-4151-883F-B11965EE376A}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sophia.Net.DRM.Tool", "..\Sophia.Net.DRM.Tool\Sophia.Net.DRM.Tool.csproj", "{B9D739C2-128B-42E0-8079-406105FB2C67}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {30741C45-1A9C-4151-883F-B11965EE376A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {30741C45-1A9C-4151-883F-B11965EE376A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {30741C45-1A9C-4151-883F-B11965EE376A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {30741C45-1A9C-4151-883F-B11965EE376A}.Release|Any CPU.Build.0 = Release|Any CPU + {B9D739C2-128B-42E0-8079-406105FB2C67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9D739C2-128B-42E0-8079-406105FB2C67}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9D739C2-128B-42E0-8079-406105FB2C67}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9D739C2-128B-42E0-8079-406105FB2C67}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {43A39C7F-8F28-4007-A6F1-81F50765BEF0} + EndGlobalSection +EndGlobal diff --git a/Sophia.Net.DRM/SophiaNetDrmApi.cs b/Sophia.Net.DRM/SophiaNetDrmApi.cs new file mode 100644 index 0000000..4ae94b3 --- /dev/null +++ b/Sophia.Net.DRM/SophiaNetDrmApi.cs @@ -0,0 +1,350 @@ +using System.Text; +using Org.BouncyCastle.Asn1; +using Org.BouncyCastle.Crypto.Prng; +using Org.BouncyCastle.Math; +using Org.BouncyCastle.Security; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Digests; +using Org.BouncyCastle.Crypto.Generators; +using Org.BouncyCastle.Crypto.Operators; +using Org.BouncyCastle.Crypto.Signers; +using Org.BouncyCastle.OpenSsl; +using Org.BouncyCastle.Pkcs; +using Org.BouncyCastle.X509.Extension; +using X509Certificate = Org.BouncyCastle.X509.X509Certificate; + +namespace Sophia.Net.DRM +{ + public static class SophiaNetDrmApi + { + + public static X509Certificate CreateSelfSignedCertificate(string commonName, AsymmetricCipherKeyPair keyPair, string sophiaNetExtension = null, bool addSophiaNetPurpose = false) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + SecureRandom random = new SecureRandom(randomGenerator); + + //When acting as a certificate authority, use a proper serial number here - as an argument to this function! + BigInteger serial = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); + + X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); + certificateGenerator.SetSerialNumber(serial); + + X509Name subjectDn = new X509Name(String.Format("CN={0}", commonName)); + X509Name issuerDn = subjectDn; + certificateGenerator.SetSubjectDN(subjectDn); + certificateGenerator.SetIssuerDN(issuerDn); + certificateGenerator.SetPublicKey(keyPair.Public); + + DateTime notBefore = DateTime.Now.Date; + DateTime notAfter = notBefore.AddYears(100); + certificateGenerator.SetNotBefore(notBefore); + certificateGenerator.SetNotAfter(notAfter); + + certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(false)); + + + AsymmetricCipherKeyPair subjectKeyPair = keyPair; + AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; + + SubjectKeyIdentifier subjectKeyIdentifier = X509ExtensionUtilities.CreateSubjectKeyIdentifier(keyPair.Public); + certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, subjectKeyIdentifier); + + AuthorityKeyIdentifier authorityKeyIdentifier = X509ExtensionUtilities.CreateAuthorityKeyIdentifier(issuerKeyPair.Public); + certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier); + + if (!string.IsNullOrEmpty(sophiaNetExtension)) + { + DerObjectIdentifier derObjectIdentifier = new DerObjectIdentifier("1.3.6.1.3.545127833961986897372532.1"); + certificateGenerator.AddExtension(derObjectIdentifier, false, System.Text.Encoding.UTF8.GetBytes("sophia.net self-signed certificate")); + } + + List usageList = new List(); + usageList.Add(KeyPurposeID.id_kp_serverAuth); + usageList.Add(KeyPurposeID.id_kp_codeSigning); + if (addSophiaNetPurpose) + { + DerObjectIdentifier doi = new DerObjectIdentifier("1.3.6.1.3.545127833961986897372532.2"); + usageList.Add(doi); + } + + certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(usageList.ToArray())); + + const string signatureAlgorithm = "SHA256WithRSA"; + Asn1SignatureFactory asn1SignatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerKeyPair.Private, random); + X509Certificate x509Certificate = certificateGenerator.Generate(asn1SignatureFactory); + return x509Certificate; + } + + public static AsymmetricCipherKeyPair GenerateKeyPair(int strength = 9216, SecureRandom random = null) + { + if (random == null) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + random = new SecureRandom(randomGenerator); + } + KeyGenerationParameters keyGenerationParameters = new KeyGenerationParameters(random, strength); + + RsaKeyPairGenerator rsaKeyPairGenerator = new RsaKeyPairGenerator(); + rsaKeyPairGenerator.Init(keyGenerationParameters); + return rsaKeyPairGenerator.GenerateKeyPair(); + } + + public static byte[] ExportPrivateKey(AsymmetricCipherKeyPair keypair) + { + MemoryStream memoryStream = new MemoryStream(); + StreamWriter streamWriter = new StreamWriter(memoryStream); + PemWriter pemWriter = new PemWriter(streamWriter); + pemWriter.WriteObject(keypair.Private); + streamWriter.Flush(); + memoryStream.Flush(); + return memoryStream.ToArray(); + } + + public static byte[] ExportPublicKey(AsymmetricCipherKeyPair keypair) + { + MemoryStream memoryStream = new MemoryStream(); + StreamWriter streamWriter = new StreamWriter(memoryStream); + PemWriter pemWriter = new PemWriter(streamWriter); + pemWriter.WriteObject(keypair.Public); + streamWriter.Flush(); + memoryStream.Flush(); + return memoryStream.ToArray(); + } + + public static AsymmetricCipherKeyPair ImportKeyPairFromPrivateKey(byte[] privateBytes) + { + MemoryStream memoryStream = new MemoryStream(privateBytes); + StreamReader streamReader = new StreamReader(memoryStream); + PemReader pemReader = new PemReader(streamReader); + object privateKey = pemReader.ReadObject(); + + AsymmetricCipherKeyPair result = privateKey as AsymmetricCipherKeyPair; + return result; + } + + public static byte[] ExportCertificate(X509Certificate certificate) + { + return certificate.GetEncoded(); + } + + public static byte[] ExportCertificateAsPkcs12(AsymmetricKeyParameter privateKey, string password, params X509Certificate[] certificate) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + SecureRandom random = new SecureRandom(randomGenerator); + + Pkcs12StoreBuilder builder = new Pkcs12StoreBuilder(); + Pkcs12Store store = builder.Build(); + + string[] friendlyNames = new string[certificate.Length]; + X509CertificateEntry[] certificateEntries = new X509CertificateEntry[certificate.Length]; + for (int i = 0; i < certificate.Length; i++) + { + friendlyNames[i] = certificate[i].SubjectDN.ToString(); + certificateEntries[i] = new X509CertificateEntry(certificate[i]); + } + + store.SetCertificateEntry(friendlyNames[0], certificateEntries[0]); + store.SetKeyEntry(friendlyNames[0], new AsymmetricKeyEntry(privateKey), certificateEntries); + + MemoryStream ms = new MemoryStream(); + store.Save(ms, password.ToCharArray(), random); + return ms.ToArray(); + } + + public static X509Certificate CreateRootCertificate(string commonName, AsymmetricCipherKeyPair keyPair) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + SecureRandom random = new SecureRandom(randomGenerator); + + //When issuing child certificates, use a proper serial number here - as an argument to this function! + BigInteger serial = BigIntegers.CreateRandomInRange(BigInteger.One, BigInteger.ValueOf(Int64.MaxValue), random); + + X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); + certificateGenerator.SetSerialNumber(serial); + + X509Name subjectDn = new X509Name(String.Format("CN={0}", commonName)); + X509Name issuerDn = subjectDn; + certificateGenerator.SetSubjectDN(subjectDn); + certificateGenerator.SetIssuerDN(issuerDn); + certificateGenerator.SetPublicKey(keyPair.Public); + + DateTime notBefore = DateTime.Now.Date; + DateTime notAfter = notBefore.AddYears(100); + certificateGenerator.SetNotBefore(notBefore); + certificateGenerator.SetNotAfter(notAfter); + + //BasicConstraints basicConstraints = new BasicConstraints(true); + //certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(true)); + certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(2)); + + AsymmetricCipherKeyPair subjectKeyPair = keyPair; + AsymmetricCipherKeyPair issuerKeyPair = subjectKeyPair; + + SubjectKeyIdentifier subjectKeyIdentifier = X509ExtensionUtilities.CreateSubjectKeyIdentifier(keyPair.Public); + certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier.Id, false, subjectKeyIdentifier); + + AuthorityKeyIdentifier authorityKeyIdentifier = X509ExtensionUtilities.CreateAuthorityKeyIdentifier(issuerKeyPair.Public); + certificateGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier.Id, false, authorityKeyIdentifier); + + const string signatureAlgorithm = "SHA256WithRSA"; + Asn1SignatureFactory asn1SignatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerKeyPair.Private, random); + X509Certificate x509Certificate = certificateGenerator.Generate(asn1SignatureFactory); + return x509Certificate; + + } + + public static X509Certificate CreateChildCertificate(string commonName, X509Certificate issuerCert, AsymmetricCipherKeyPair issuerPrivateKey, AsymmetricKeyParameter childPublicKey, long serialNumber, string sophiaNetExtensionValue) + { + return CreateChildCertificate(commonName, issuerCert, issuerPrivateKey, childPublicKey, serialNumber, Encoding.UTF8.GetBytes(sophiaNetExtensionValue)); + } + + public static X509Certificate CreateChildCertificate(string commonName, X509Certificate issuerCert, AsymmetricCipherKeyPair issuerPrivateKey, AsymmetricKeyParameter childPublicKey, long serialNumber, SophiaNetEntitlementCollection entitlements) + { + byte[] serialize = entitlements.Serialize(); + return CreateChildCertificate(commonName, issuerCert, issuerPrivateKey, childPublicKey, serialNumber, serialize); + } + + public static X509Certificate CreateChildCertificate(string commonName, X509Certificate issuerCert, AsymmetricCipherKeyPair issuerPrivateKey, AsymmetricKeyParameter childPublicKey, long serialNumber, byte[] sophiaNetExtensionValue) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + SecureRandom random = new SecureRandom(randomGenerator); + + BigInteger serial = BigInteger.ValueOf(serialNumber); + + X509Name subjectDn = new X509Name(String.Format("CN={0}", commonName)); + + DateTime notBefore = DateTime.Now.Date; + DateTime notAfter = issuerCert.NotAfter; + + DerObjectIdentifier sophiaNetExtensionId = new DerObjectIdentifier("1.3.6.1.3.545127833961986897372532.1"); + + X509V3CertificateGenerator certificateGenerator = new X509V3CertificateGenerator(); + certificateGenerator.SetSerialNumber(serial); + certificateGenerator.SetSubjectDN(subjectDn); + certificateGenerator.SetIssuerDN(issuerCert.SubjectDN); + certificateGenerator.SetPublicKey(childPublicKey); + certificateGenerator.SetNotBefore(notBefore); + certificateGenerator.SetNotAfter(notAfter); + certificateGenerator.AddExtension(X509Extensions.BasicConstraints.Id, true, new BasicConstraints(false)); + certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage.Id, false, new ExtendedKeyUsage(KeyPurposeID.id_kp_clientAuth)); + certificateGenerator.AddExtension(sophiaNetExtensionId, false, sophiaNetExtensionValue); + + const string signatureAlgorithm = "SHA256WithRSA"; + Asn1SignatureFactory asn1SignatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerPrivateKey.Private, random); + X509Certificate x509Certificate = certificateGenerator.Generate(asn1SignatureFactory); + return x509Certificate; + } + + public static X509Certificate ImportCertificate(byte[] encoded) + { + X509Certificate result = new X509Certificate(encoded); + return result; + } + + public static bool ValidateCertificateChain(X509Certificate child, X509Certificate issuer) + { + try + { + child.Verify(issuer.GetPublicKey()); + return true; + } + catch (Exception e) + { + return false; + } + } + + public static X509Crl CreateCertificateRevocationList(X509Certificate issuer, AsymmetricCipherKeyPair issuerPrivateKey, params long[] revokedSerials) + { + CryptoApiRandomGenerator randomGenerator = new CryptoApiRandomGenerator(); + SecureRandom random = new SecureRandom(randomGenerator); + + long notAfterSeconds = issuer.NotAfter.Ticks / TimeSpan.TicksPerSecond; + long nowSeconds = DateTime.Now.Ticks / TimeSpan.TicksPerSecond; + long secondsDifference = notAfterSeconds - nowSeconds; + if (secondsDifference > Int32.MaxValue) + secondsDifference = Int32.MaxValue; + long _30days = new TimeSpan(30, 0, 0, 0).Ticks / TimeSpan.TicksPerSecond; + + int max = (int)secondsDifference; + int min = (int)_30days; + int updateDelayInt = random.Next(min, max); + TimeSpan updateDelayTimespan = TimeSpan.FromSeconds(updateDelayInt); + + X509V2CrlGenerator crlGenerator = new X509V2CrlGenerator(); + crlGenerator.SetIssuerDN(issuer.IssuerDN); + crlGenerator.SetThisUpdate(DateTime.Now); + crlGenerator.SetNextUpdate(DateTime.Now + updateDelayTimespan); + crlGenerator.AddExtension(X509Extensions.AuthorityKeyIdentifier, false, X509ExtensionUtilities.CreateAuthorityKeyIdentifier(issuer)); + crlGenerator.AddExtension(X509Extensions.CrlNumber, false, new CrlNumber(BigInteger.One)); + + foreach (long revokedSerial in revokedSerials) + { + crlGenerator.AddCrlEntry(BigInteger.ValueOf(revokedSerial),DateTime.Now, CrlReason.PrivilegeWithdrawn); + } + + const string signatureAlgorithm = "SHA256WithRSA"; + Asn1SignatureFactory signatureFactory = new Asn1SignatureFactory(signatureAlgorithm, issuerPrivateKey.Private, random); + X509Crl crl = crlGenerator.Generate(signatureFactory); + return crl; + } + + public static byte[] ExportCrl(X509Crl crl) + { + return crl.GetEncoded(); + } + + public static X509Crl ImportCrl(byte[] buffer) + { + X509Crl result = new X509Crl(buffer); + return result; + } + + public static bool ValidateCertificateAgainstCrl(X509Certificate certificate, X509Crl crl) + { + BigInteger mySerial = certificate.SerialNumber; + ISet x509CrlEntries = crl.GetRevokedCertificates(); + foreach (X509CrlEntry entry in x509CrlEntries) + { + BigInteger entrySerial = entry.SerialNumber; + if (entrySerial.Equals(mySerial)) + return false; + } + + return true; + } + + public static byte[] GetSophiaNetExtensionFromCertificate(X509Certificate cert) + { + DerObjectIdentifier sophiaNetExtensionId = new DerObjectIdentifier("1.3.6.1.3.545127833961986897372532.1"); + X509Extension x509Extension = cert.GetExtension(sophiaNetExtensionId); + Asn1OctetString octetString = x509Extension.Value; + Stream octetStream = octetString.Parser.GetOctetStream(); + Asn1InputStream asn1Reader = new Asn1InputStream(octetStream); + DerOctetString readObject = (DerOctetString)asn1Reader.ReadObject(); + byte[] result = readObject.GetOctets(); + return result; + } + + public static byte[] SignFile(byte[] toBeSigned, AsymmetricKeyParameter privateKey) + { + RsaDigestSigner signer = new RsaDigestSigner(new Sha256Digest()); + signer.Init(true, privateKey); + signer.BlockUpdate(toBeSigned, 0, toBeSigned.Length); + return signer.GenerateSignature(); + } + + public static bool ValidateSignedFile(byte[] signed, byte[] signature, AsymmetricKeyParameter publicKey) + { + RsaDigestSigner signer = new RsaDigestSigner(new Sha256Digest()); + signer.Init(false, publicKey); + signer.BlockUpdate(signed, 0, signed.Length); + + bool isValid = signer.VerifySignature(signature); + return isValid; + } + } +} diff --git a/Sophia.Net.DRM/SophiaNetEntitlements.cs b/Sophia.Net.DRM/SophiaNetEntitlements.cs new file mode 100644 index 0000000..7103b53 --- /dev/null +++ b/Sophia.Net.DRM/SophiaNetEntitlements.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Sophia.Net.DRM +{ + public class SophiaNetEntitlementCollection + { + public SophiaNetEntitlementCollection(params Guid[] guids) + { + _backend = new Guid[guids.Length]; + Array.Copy(guids,0,_backend,0, guids.Length); + } + + public SophiaNetEntitlementCollection(byte[] buffer) + { + _backend = new Guid[buffer.Length / 16]; + for (int i = 0; i < buffer.Length; i += 16) + { + Span part = new Span(buffer, i, 16); + _backend[i / 16] = new Guid(part); + } + } + + public byte[] Serialize() + { + byte[] outBuffer = new byte[_backend.Length * 16]; + for (int i = 0; i < _backend.Length; i++) + { + byte[] iBuffer = _backend[i].ToByteArray(); + Array.Copy(iBuffer, 0, outBuffer, i * 16, 16); + } + + return outBuffer; + } + + private Guid[] _backend; + + public bool HasEntitlement(Guid check) + { + for (int i = 0; i < _backend.Length; i++) + { + if (_backend[i].Equals(check)) + return true; + } + return false; + } + + protected bool Equals(SophiaNetEntitlementCollection that) + { + if (this._backend.Length != that._backend.Length) + return false; + + for (int i = 0; i < this._backend.Length; i++) + { + Guid mine = this._backend[i]; + Guid theirs = that._backend[i]; + if (!mine.Equals(theirs)) + return false; + } + + return true; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != this.GetType()) + return false; + return Equals((SophiaNetEntitlementCollection)obj); + } + + public override int GetHashCode() + { + long result = 0; + for (int i = 0; i < _backend.Length; i++) + { + result += _backend[i].GetHashCode(); + } + return (int)result; + } + } +} diff --git a/Voile.Sqlite/Class1.cs b/Voile.Sqlite/Class1.cs deleted file mode 100644 index 5fc054e..0000000 --- a/Voile.Sqlite/Class1.cs +++ /dev/null @@ -1,16 +0,0 @@ -//using Microsoft.Data.Sqlite; - -namespace Voile.Sqlite -{ - public class Class1 - { - public void Run() - { - /*SqliteConnectionStringBuilder scsb = new SqliteConnectionStringBuilder(); - scsb.DataSource = "blyat.db"; - SqliteConnection sc = new SqliteConnection(scsb.ConnectionString); - sc.Open();*/ - - } - } -} diff --git a/Voile.slnx b/Voile.slnx index 443eaeb..ed7b54a 100644 --- a/Voile.slnx +++ b/Voile.slnx @@ -1,5 +1,5 @@ - + diff --git a/Voile/FirstRunWizard.Designer.cs b/Voile/FirstRunWizard.Designer.cs index b7ff3f8..a7840a4 100644 --- a/Voile/FirstRunWizard.Designer.cs +++ b/Voile/FirstRunWizard.Designer.cs @@ -31,17 +31,28 @@ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FirstRunWizard)); pictureBox1 = new PictureBox(); tabControl1 = new TabControl(); - tabPage1 = new TabPage(); + tabPageWelcome = new TabPage(); label2 = new Label(); label1 = new Label(); - radioButton2 = new RadioButton(); - radioButton1 = new RadioButton(); - tabPage2 = new TabPage(); - button1 = new Button(); - button2 = new Button(); + radioButtonAmExpert = new RadioButton(); + radioButtonAmBegginer = new RadioButton(); + tabPageLicense = new TabPage(); + pictureBox2 = new PictureBox(); + label4 = new Label(); + radioButtonNoLicense = new RadioButton(); + buttonLoadLicenseFile = new Button(); + buttonValidateLicense = new Button(); + textBox1 = new TextBox(); + radioButtonHasLicense = new RadioButton(); + label3 = new Label(); + buttonNext = new Button(); + buttonBack = new Button(); + openFileDialogCertificate = new OpenFileDialog(); ((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit(); tabControl1.SuspendLayout(); - tabPage1.SuspendLayout(); + tabPageWelcome.SuspendLayout(); + tabPageLicense.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)pictureBox2).BeginInit(); SuspendLayout(); // // pictureBox1 @@ -56,27 +67,27 @@ // // tabControl1 // - tabControl1.Controls.Add(tabPage1); - tabControl1.Controls.Add(tabPage2); + tabControl1.Controls.Add(tabPageWelcome); + tabControl1.Controls.Add(tabPageLicense); tabControl1.Location = new Point(138, 12); tabControl1.Name = "tabControl1"; tabControl1.SelectedIndex = 0; tabControl1.Size = new Size(356, 412); tabControl1.TabIndex = 1; // - // tabPage1 + // tabPageWelcome // - tabPage1.Controls.Add(label2); - tabPage1.Controls.Add(label1); - tabPage1.Controls.Add(radioButton2); - tabPage1.Controls.Add(radioButton1); - tabPage1.Location = new Point(4, 24); - tabPage1.Name = "tabPage1"; - tabPage1.Padding = new Padding(3); - tabPage1.Size = new Size(348, 384); - tabPage1.TabIndex = 0; - tabPage1.Text = "Welcome!"; - tabPage1.UseVisualStyleBackColor = true; + tabPageWelcome.Controls.Add(label2); + tabPageWelcome.Controls.Add(label1); + tabPageWelcome.Controls.Add(radioButtonAmExpert); + tabPageWelcome.Controls.Add(radioButtonAmBegginer); + tabPageWelcome.Location = new Point(4, 24); + tabPageWelcome.Name = "tabPageWelcome"; + tabPageWelcome.Padding = new Padding(3); + tabPageWelcome.Size = new Size(348, 384); + tabPageWelcome.TabIndex = 0; + tabPageWelcome.Text = "Welcome!"; + tabPageWelcome.UseVisualStyleBackColor = true; // // label2 // @@ -96,65 +107,161 @@ label1.TabIndex = 2; label1.Text = "(You can change these options later!)"; // - // radioButton2 + // radioButtonAmExpert // - radioButton2.AutoSize = true; - radioButton2.Location = new Point(6, 271); - radioButton2.Name = "radioButton2"; - radioButton2.Size = new Size(299, 34); - radioButton2.TabIndex = 1; - radioButton2.TabStop = true; - radioButton2.Text = "I’m an expert. Let me choose my own database and \r\nstorage options."; - radioButton2.UseVisualStyleBackColor = true; + radioButtonAmExpert.AutoSize = true; + radioButtonAmExpert.Location = new Point(6, 271); + radioButtonAmExpert.Name = "radioButtonAmExpert"; + radioButtonAmExpert.Size = new Size(299, 34); + radioButtonAmExpert.TabIndex = 1; + radioButtonAmExpert.Text = "I’m an expert. Let me choose my own database and \r\nstorage options."; + radioButtonAmExpert.UseVisualStyleBackColor = true; + radioButtonAmExpert.CheckedChanged += radioButtonAmExpert_CheckedChanged; // - // radioButton1 + // radioButtonAmBegginer // - radioButton1.AutoSize = true; - radioButton1.Checked = true; - radioButton1.Location = new Point(6, 246); - radioButton1.Name = "radioButton1"; - radioButton1.Size = new Size(298, 19); - radioButton1.TabIndex = 0; - radioButton1.TabStop = true; - radioButton1.Text = "I’m a beginner. Set things up for me automatically. "; - radioButton1.UseVisualStyleBackColor = true; + radioButtonAmBegginer.AutoSize = true; + radioButtonAmBegginer.Location = new Point(6, 246); + radioButtonAmBegginer.Name = "radioButtonAmBegginer"; + radioButtonAmBegginer.Size = new Size(298, 19); + radioButtonAmBegginer.TabIndex = 0; + radioButtonAmBegginer.Text = "I’m a beginner. Set things up for me automatically. "; + radioButtonAmBegginer.UseVisualStyleBackColor = true; + radioButtonAmBegginer.CheckedChanged += radioButtonAmBegginer_CheckedChanged; // - // tabPage2 + // tabPageLicense // - tabPage2.Location = new Point(4, 24); - tabPage2.Name = "tabPage2"; - tabPage2.Padding = new Padding(3); - tabPage2.Size = new Size(348, 384); - tabPage2.TabIndex = 1; - tabPage2.Text = "tabPage2"; - tabPage2.UseVisualStyleBackColor = true; + tabPageLicense.Controls.Add(pictureBox2); + tabPageLicense.Controls.Add(label4); + tabPageLicense.Controls.Add(radioButtonNoLicense); + tabPageLicense.Controls.Add(buttonLoadLicenseFile); + tabPageLicense.Controls.Add(buttonValidateLicense); + tabPageLicense.Controls.Add(textBox1); + tabPageLicense.Controls.Add(radioButtonHasLicense); + tabPageLicense.Controls.Add(label3); + tabPageLicense.Location = new Point(4, 24); + tabPageLicense.Name = "tabPageLicense"; + tabPageLicense.Padding = new Padding(3); + tabPageLicense.Size = new Size(348, 384); + tabPageLicense.TabIndex = 1; + tabPageLicense.Text = "License"; + tabPageLicense.UseVisualStyleBackColor = true; // - // button1 + // pictureBox2 // - button1.Location = new Point(419, 430); - button1.Name = "button1"; - button1.Size = new Size(75, 23); - button1.TabIndex = 2; - button1.Text = "Next >"; - button1.UseVisualStyleBackColor = true; + pictureBox2.Image = Properties.Resources.SETUPAPI_18_1_32x32x4; + pictureBox2.Location = new Point(127, 262); + pictureBox2.Name = "pictureBox2"; + pictureBox2.Size = new Size(32, 32); + pictureBox2.TabIndex = 7; + pictureBox2.TabStop = false; + pictureBox2.Click += pictureBox2_Click; // - // button2 + // label4 // - button2.Enabled = false; - button2.Location = new Point(338, 430); - button2.Name = "button2"; - button2.Size = new Size(75, 23); - button2.TabIndex = 3; - button2.Text = "< Back"; - button2.UseVisualStyleBackColor = true; + label4.AutoSize = true; + label4.Location = new Point(22, 344); + label4.Name = "label4"; + label4.Size = new Size(299, 30); + label4.TabIndex = 6; + label4.Text = "(You can also change between Licensed and Shareware \r\nmode later!)"; + // + // radioButtonNoLicense + // + radioButtonNoLicense.AutoSize = true; + radioButtonNoLicense.Location = new Point(6, 307); + radioButtonNoLicense.Name = "radioButtonNoLicense"; + radioButtonNoLicense.Size = new Size(309, 34); + radioButtonNoLicense.TabIndex = 5; + radioButtonNoLicense.Text = "No license yet — I’d like to use the shareware version, \r\nor request a license later."; + radioButtonNoLicense.UseVisualStyleBackColor = true; + radioButtonNoLicense.CheckedChanged += radioButtonNoLicense_CheckedChanged; + // + // buttonLoadLicenseFile + // + buttonLoadLicenseFile.Enabled = false; + buttonLoadLicenseFile.Location = new Point(246, 262); + buttonLoadLicenseFile.Name = "buttonLoadLicenseFile"; + buttonLoadLicenseFile.Size = new Size(75, 39); + buttonLoadLicenseFile.TabIndex = 4; + buttonLoadLicenseFile.Text = "Load License File"; + buttonLoadLicenseFile.UseVisualStyleBackColor = true; + buttonLoadLicenseFile.Click += buttonLoadLicenseFile_Click; + // + // buttonValidateLicense + // + buttonValidateLicense.Enabled = false; + buttonValidateLicense.Location = new Point(165, 262); + buttonValidateLicense.Name = "buttonValidateLicense"; + buttonValidateLicense.Size = new Size(75, 39); + buttonValidateLicense.TabIndex = 3; + buttonValidateLicense.Text = "Validate License"; + buttonValidateLicense.UseVisualStyleBackColor = true; + buttonValidateLicense.Click += buttonValidateLicense_Click; + // + // textBox1 + // + textBox1.Enabled = false; + textBox1.Location = new Point(17, 233); + textBox1.Name = "textBox1"; + textBox1.Size = new Size(304, 23); + textBox1.TabIndex = 2; + // + // radioButtonHasLicense + // + radioButtonHasLicense.AutoSize = true; + radioButtonHasLicense.Location = new Point(3, 208); + radioButtonHasLicense.Name = "radioButtonHasLicense"; + radioButtonHasLicense.Size = new Size(189, 19); + radioButtonHasLicense.TabIndex = 1; + radioButtonHasLicense.Text = "Yes, I have a license file to load."; + radioButtonHasLicense.UseVisualStyleBackColor = true; + radioButtonHasLicense.CheckedChanged += radioButton3_CheckedChanged; + // + // label3 + // + label3.AutoSize = true; + label3.Location = new Point(6, 3); + label3.Name = "label3"; + label3.Size = new Size(337, 120); + label3.TabIndex = 0; + label3.Text = resources.GetString("label3.Text"); + // + // buttonNext + // + buttonNext.Enabled = false; + buttonNext.Location = new Point(419, 430); + buttonNext.Name = "buttonNext"; + buttonNext.Size = new Size(75, 23); + buttonNext.TabIndex = 2; + buttonNext.Text = "Next >"; + buttonNext.UseVisualStyleBackColor = true; + buttonNext.Click += buttonNext_Click; + // + // buttonBack + // + buttonBack.Enabled = false; + buttonBack.Location = new Point(338, 430); + buttonBack.Name = "buttonBack"; + buttonBack.Size = new Size(75, 23); + buttonBack.TabIndex = 3; + buttonBack.Text = "< Back"; + buttonBack.UseVisualStyleBackColor = true; + // + // openFileDialogCertificate + // + openFileDialogCertificate.DefaultExt = "cer"; + openFileDialogCertificate.FileName = "openFileDialog1"; + openFileDialogCertificate.Filter = "X.509 Certificate (*.cer)|*.cer"; + openFileDialogCertificate.Title = "Open Voile License File"; // // FirstRunWizard // AutoScaleDimensions = new SizeF(7F, 15F); AutoScaleMode = AutoScaleMode.Font; ClientSize = new Size(502, 465); - Controls.Add(button2); - Controls.Add(button1); + Controls.Add(buttonBack); + Controls.Add(buttonNext); Controls.Add(tabControl1); Controls.Add(pictureBox1); FormBorderStyle = FormBorderStyle.FixedSingle; @@ -165,8 +272,11 @@ Text = "Voile - First Run Wizard"; ((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit(); tabControl1.ResumeLayout(false); - tabPage1.ResumeLayout(false); - tabPage1.PerformLayout(); + tabPageWelcome.ResumeLayout(false); + tabPageWelcome.PerformLayout(); + tabPageLicense.ResumeLayout(false); + tabPageLicense.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)pictureBox2).EndInit(); ResumeLayout(false); } @@ -174,13 +284,22 @@ private PictureBox pictureBox1; private TabControl tabControl1; - private TabPage tabPage1; - private TabPage tabPage2; - private Button button1; - private Button button2; - private RadioButton radioButton1; - private RadioButton radioButton2; + private TabPage tabPageWelcome; + private TabPage tabPageLicense; + private Button buttonNext; + private Button buttonBack; + private RadioButton radioButtonAmBegginer; + private RadioButton radioButtonAmExpert; private Label label1; private Label label2; + private Label label3; + private RadioButton radioButtonHasLicense; + private RadioButton radioButtonNoLicense; + private Button buttonLoadLicenseFile; + private Button buttonValidateLicense; + private TextBox textBox1; + private Label label4; + private PictureBox pictureBox2; + private OpenFileDialog openFileDialogCertificate; } } \ No newline at end of file diff --git a/Voile/FirstRunWizard.cs b/Voile/FirstRunWizard.cs index 9c190dc..965002f 100644 --- a/Voile/FirstRunWizard.cs +++ b/Voile/FirstRunWizard.cs @@ -1,4 +1,7 @@ -using System; +using Org.BouncyCastle.Utilities; +using Org.BouncyCastle.X509; +using Sophia.Net.DRM; +using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; @@ -7,6 +10,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using Voile.Properties; namespace Voile { @@ -19,8 +23,22 @@ namespace Voile } private TabPage[] allPages; - public void DisplayTabPage(int target) + private int currentTabPage; + private Stack pastPages; + + private bool beginnerMode; + private FileInfo licenceCertificateFileInfo; + private byte[] licenseBuffer; + private int licenseState; + private X509Certificate licenseCertificate; + + public void DisplayTabPage(int target, bool isGoingBack = false) { + if (pastPages == null) + pastPages = new Stack(); + else + pastPages.Push(target); + if (allPages == null) { allPages = new TabPage[tabControl1.TabPages.Count]; @@ -29,9 +47,180 @@ namespace Voile allPages[i] = tabControl1.TabPages[i]; } } - + tabControl1.TabPages.Clear(); tabControl1.TabPages.Add(allPages[target]); + currentTabPage = target; + RefreshView(); + } + + void RefreshView() + { + buttonBack.Enabled = false; + buttonNext.Enabled = false; + + if (pastPages != null) + { + if (pastPages.Count > 0) + { + buttonBack.Enabled = true; + } + } + + switch (currentTabPage) + { + case 0: + beginnerMode = radioButtonAmBegginer.Checked; + buttonNext.Enabled = radioButtonAmBegginer.Checked || radioButtonAmExpert.Checked; + break; + case 1: + buttonValidateLicense.Enabled = ((licenceCertificateFileInfo != null) & radioButtonHasLicense.Checked); + buttonLoadLicenseFile.Enabled = radioButtonHasLicense.Checked; + pictureBox2.Visible = radioButtonHasLicense.Checked; + if (pictureBox2.Visible) + { + switch(licenseState) + { + case 0: //Noch nichts geladen. + pictureBox2.Image = Resources.SETUPAPI_18_1_32x32x4; //Fragezeichen + break; + case 1: //Root cert konnte nicht geladen werden. + case 2: //Lizenz file konnte nicht geladen werden. + case 3: //Lizenzzertifikat wurde nicht von sophia.net ausgestellt. + case 4: //Lizennzertifikat enthält keine sophia.net extensions + case 5: //sophia.net extension ist leer + case 7: //sophia.net extension hat ungültige länge + pictureBox2.Image = Resources.TRFFC10C_1_32x32x4; //rote Ampel + break; + case 6: //gültige lizenz + pictureBox2.Image = Resources.TRFFC10A_1_32x32x4; //grüne Ampel + break; + case 8: + default: + pictureBox2.Image = Resources.iblicense_133_1_32x32x4; //Ausrufezeichen + licenseState = 8; + break; + } + } + break; + default: + MessageBox.Show("Could not find handler for the current tab page."); + return; + } + } + + private void radioButton3_CheckedChanged(object sender, EventArgs e) + { + RefreshView(); + } + + private void radioButtonAmBegginer_CheckedChanged(object sender, EventArgs e) + { + RefreshView(); + } + + private void radioButtonAmExpert_CheckedChanged(object sender, EventArgs e) + { + RefreshView(); + } + + private void radioButtonNoLicense_CheckedChanged(object sender, EventArgs e) + { + RefreshView(); + } + + private void pictureBox2_Click(object sender, EventArgs e) + { + + } + + private void buttonNext_Click(object sender, EventArgs e) + { + if (currentTabPage == 0) + { + DisplayTabPage(1); + } + } + + private void buttonLoadLicenseFile_Click(object sender, EventArgs e) + { + if (openFileDialogCertificate.ShowDialog() == DialogResult.OK) + { + licenceCertificateFileInfo = new FileInfo(openFileDialogCertificate.FileName); + licenseBuffer = File.ReadAllBytes(licenceCertificateFileInfo.FullName); + textBox1.Text = licenceCertificateFileInfo.FullName; + licenseState = 0; + pictureBox2.Image = Resources.SETUPAPI_18_1_32x32x4; + } + RefreshView(); + } + + private void buttonValidateLicense_Click(object sender, EventArgs e) + { + VoileContext voileContext = VoileContext.GetContext(); + + if (voileContext.SophiaNetRootCertificate == null) + { + try + { + byte[] sophianetCertBuffer = Resources.sophianet_cert; + voileContext.SophiaNetRootCertificate = SophiaNetDrmApi.ImportCertificate(sophianetCertBuffer); + } + catch (Exception ex) + { + licenseState = 1; + RefreshView(); + return; + } + } + + try + { + licenseCertificate = SophiaNetDrmApi.ImportCertificate(licenseBuffer); + } + catch (Exception f) + { + licenseState = 2; + RefreshView(); + return; + } + + bool certificateChainValid = SophiaNetDrmApi.ValidateCertificateChain(licenseCertificate, voileContext.SophiaNetRootCertificate); + if (!certificateChainValid) + { + licenseState = 3; + RefreshView(); + return; + } + + byte[] sophiaNetExtensionBuffer; + try + { + sophiaNetExtensionBuffer = SophiaNetDrmApi.GetSophiaNetExtensionFromCertificate(licenseCertificate); + } + catch (Exception g) + { + licenseState = 4; + RefreshView(); + return; + } + + if (sophiaNetExtensionBuffer.Length == 0) + { + licenseState = 5; + RefreshView(); + return; + } + if (sophiaNetExtensionBuffer.Length % 16 != 0) + { + licenseState = 7; + RefreshView(); + return; + } + + licenseState = 6; + RefreshView(); + return; } } } diff --git a/Voile/FirstRunWizard.resx b/Voile/FirstRunWizard.resx index 55878d3..d12d1bf 100644 --- a/Voile/FirstRunWizard.resx +++ b/Voile/FirstRunWizard.resx @@ -135,4 +135,17 @@ up automatically so you can start using the app right away. How would you like to continue? + + Before we continue, let’s take a moment to set up your license. + +Voile is available as shareware, which means you can use it +for free for personal, non‑commercial projects. If you’re using +Voile in a professional setting — or if you’d simply like +to support the ongoing development — you can activate +a license. Some advanced features also become available +once a license is installed. + + + 17, 17 + \ No newline at end of file diff --git a/Voile/Properties/Resources.Designer.cs b/Voile/Properties/Resources.Designer.cs index 3a403f7..4c7e1e6 100644 --- a/Voile/Properties/Resources.Designer.cs +++ b/Voile/Properties/Resources.Designer.cs @@ -100,6 +100,16 @@ namespace Voile.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap iblicense_133_1_32x32x4 { + get { + object obj = ResourceManager.GetObject("iblicense_133_1_32x32x4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -110,6 +120,26 @@ namespace Voile.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap SETUPAPI_18_1_32x32x4 { + get { + object obj = ResourceManager.GetObject("SETUPAPI_18_1_32x32x4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Byte[]. + /// + internal static byte[] sophianet_cert { + get { + object obj = ResourceManager.GetObject("sophianet_cert", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// @@ -120,6 +150,26 @@ namespace Voile.Properties { } } + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap TRFFC10A_1_32x32x4 { + get { + object obj = ResourceManager.GetObject("TRFFC10A_1_32x32x4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap TRFFC10C_1_32x32x4 { + get { + object obj = ResourceManager.GetObject("TRFFC10C_1_32x32x4", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// diff --git a/Voile/Properties/Resources.resx b/Voile/Properties/Resources.resx index 3d643ce..ebe4724 100644 --- a/Voile/Properties/Resources.resx +++ b/Voile/Properties/Resources.resx @@ -131,12 +131,27 @@ ..\Resources\H_POINT.CUR;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Mauszeiger + + ..\Resources\iblicense_133_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\inetwiz_100_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\SETUPAPI_18_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\sophianet-cert.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\technlgy.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + ..\Resources\TRFFC10A_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\TRFFC10C_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\URLPKR_141_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/Voile/Resources/SETUPAPI_18_1_32x32x4.png b/Voile/Resources/SETUPAPI_18_1_32x32x4.png new file mode 100644 index 0000000000000000000000000000000000000000..6804e38c19c35d611909231e1d54e3d8bfb25bc3 GIT binary patch literal 394 zcmV;50d@X~P)544hu>za9UKKkGdR>bgiftb3C*#t5CEv;_?sJos*+zw`tL0C%rb`cFH&rG;b$ zZoD_7y{BzTQX-;3QOMC3hZc=c#Lvh#Nw{NZ>&m*~gZvN{FW{EkU9;<)Qi{(Ckjbwi zN-6FRCn<}VCclaxxxfFb0Fpbo8i9|=&rz6(KRC%dm0Usk@{viv#|6w@K!Gon op@MWP9^sSAiu8BuCrY*>-1Q~V=^$2J$b@YbT##bx31b|!soUJ`#Q=&R3 zaE03gbN#R{sobh%QUGD%el||NPDzx-ycY&E*BTy=nSiMSfVe^#=6OyXtFG-;+G+&U z$mNpPt?v{ctnXT|gniecMMk;H4~U7PE;tu#9NhcP|aW_ z3x_gb_`D1lU`jy8U;*jbpbb_tYxi65h+z?n^%j|SOQJnBgp4R%1905->#rl-JYmNF zsaSi1C?>Z;7FHibT?8!}@ii>-t@uBKs0Y89f%}6f5>O@28s3ss8|vrewB5D{9b7~v zKS{nk5s64^jiz59;_Qh?L?+_qh=^isy}c&a8EAosC=0p^+)C}0-4syYk66d{2T?@a z05)St0L;Rn43uU8?1Ekgs0KtN>Vj=E)r^WUAU|eC#OQ$hCzd&emB@ECh!sI8=I##V ci73Z=0>y4C4_gn8Q& o3W62C^Ib9lD(2n7@F3`TU(1V1;L3-Vg#Z8m07*qoM6N<$g4FDd6#xJL literal 0 HcmV?d00001 diff --git a/Voile/Resources/TRFFC10C_1_32x32x4.png b/Voile/Resources/TRFFC10C_1_32x32x4.png new file mode 100644 index 0000000000000000000000000000000000000000..85e5c8e4af5dc47e1dde5731b6d37a4aee61cb9c GIT binary patch literal 376 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 - + diff --git a/Voile/VoileContext.cs b/Voile/VoileContext.cs index 95a3953..7987cdc 100644 --- a/Voile/VoileContext.cs +++ b/Voile/VoileContext.cs @@ -1,4 +1,5 @@ -using skyscraper5.Skyscraper; +using Org.BouncyCastle.X509; +using skyscraper5.Skyscraper; using System; using System.Collections.Generic; using System.Linq; @@ -47,5 +48,6 @@ namespace Voile } public Ini Ini { get; set; } + public X509Certificate SophiaNetRootCertificate { get; internal set; } } }