Began building licensing wizard.
This commit is contained in:
parent
ad2f8040d8
commit
61bca1c0e7
8
.gitignore
vendored
8
.gitignore
vendored
@ -11,3 +11,11 @@
|
|||||||
/Voile.Sqlite/bin/Debug/net8.0
|
/Voile.Sqlite/bin/Debug/net8.0
|
||||||
/Voile.Sqlite/obj/Debug/net8.0
|
/Voile.Sqlite/obj/Debug/net8.0
|
||||||
/Voile.Sqlite/obj
|
/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
|
||||||
|
|||||||
@ -7,8 +7,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="10.0.1" />
|
<PackageReference Include="BouncyCastle.Cryptography" Version="2.6.2" />
|
||||||
<PackageReference Include="SQLitePCLRaw.bundle_e_sqlite3" Version="3.0.2" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
31
Sophia.Net.DRM/Sophia.Net.DRM.sln
Normal file
31
Sophia.Net.DRM/Sophia.Net.DRM.sln
Normal file
@ -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
|
||||||
350
Sophia.Net.DRM/SophiaNetDrmApi.cs
Normal file
350
Sophia.Net.DRM/SophiaNetDrmApi.cs
Normal file
@ -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<DerObjectIdentifier> usageList = new List<DerObjectIdentifier>();
|
||||||
|
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<X509CrlEntry> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
Sophia.Net.DRM/SophiaNetEntitlements.cs
Normal file
88
Sophia.Net.DRM/SophiaNetEntitlements.cs
Normal file
@ -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<byte> part = new Span<byte>(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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();*/
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,5 @@
|
|||||||
<Solution>
|
<Solution>
|
||||||
<Project Path="../skyscraper8/skyscraper8/skyscraper8.csproj" />
|
<Project Path="../skyscraper8/skyscraper8/skyscraper8.csproj" />
|
||||||
<Project Path="Voile.Sqlite/Voile.Sqlite.csproj" Id="6f554ccb-b562-4d3a-9ea3-121a4ea8b36d" DisplayName="Voile.SQLite" />
|
<Project Path="Sophia.Net.DRM/Sophia.Net.DRM.csproj" />
|
||||||
<Project Path="Voile/Voile.csproj" />
|
<Project Path="Voile/Voile.csproj" />
|
||||||
</Solution>
|
</Solution>
|
||||||
|
|||||||
265
Voile/FirstRunWizard.Designer.cs
generated
265
Voile/FirstRunWizard.Designer.cs
generated
@ -31,17 +31,28 @@
|
|||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FirstRunWizard));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FirstRunWizard));
|
||||||
pictureBox1 = new PictureBox();
|
pictureBox1 = new PictureBox();
|
||||||
tabControl1 = new TabControl();
|
tabControl1 = new TabControl();
|
||||||
tabPage1 = new TabPage();
|
tabPageWelcome = new TabPage();
|
||||||
label2 = new Label();
|
label2 = new Label();
|
||||||
label1 = new Label();
|
label1 = new Label();
|
||||||
radioButton2 = new RadioButton();
|
radioButtonAmExpert = new RadioButton();
|
||||||
radioButton1 = new RadioButton();
|
radioButtonAmBegginer = new RadioButton();
|
||||||
tabPage2 = new TabPage();
|
tabPageLicense = new TabPage();
|
||||||
button1 = new Button();
|
pictureBox2 = new PictureBox();
|
||||||
button2 = new Button();
|
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();
|
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit();
|
||||||
tabControl1.SuspendLayout();
|
tabControl1.SuspendLayout();
|
||||||
tabPage1.SuspendLayout();
|
tabPageWelcome.SuspendLayout();
|
||||||
|
tabPageLicense.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)pictureBox2).BeginInit();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// pictureBox1
|
// pictureBox1
|
||||||
@ -56,27 +67,27 @@
|
|||||||
//
|
//
|
||||||
// tabControl1
|
// tabControl1
|
||||||
//
|
//
|
||||||
tabControl1.Controls.Add(tabPage1);
|
tabControl1.Controls.Add(tabPageWelcome);
|
||||||
tabControl1.Controls.Add(tabPage2);
|
tabControl1.Controls.Add(tabPageLicense);
|
||||||
tabControl1.Location = new Point(138, 12);
|
tabControl1.Location = new Point(138, 12);
|
||||||
tabControl1.Name = "tabControl1";
|
tabControl1.Name = "tabControl1";
|
||||||
tabControl1.SelectedIndex = 0;
|
tabControl1.SelectedIndex = 0;
|
||||||
tabControl1.Size = new Size(356, 412);
|
tabControl1.Size = new Size(356, 412);
|
||||||
tabControl1.TabIndex = 1;
|
tabControl1.TabIndex = 1;
|
||||||
//
|
//
|
||||||
// tabPage1
|
// tabPageWelcome
|
||||||
//
|
//
|
||||||
tabPage1.Controls.Add(label2);
|
tabPageWelcome.Controls.Add(label2);
|
||||||
tabPage1.Controls.Add(label1);
|
tabPageWelcome.Controls.Add(label1);
|
||||||
tabPage1.Controls.Add(radioButton2);
|
tabPageWelcome.Controls.Add(radioButtonAmExpert);
|
||||||
tabPage1.Controls.Add(radioButton1);
|
tabPageWelcome.Controls.Add(radioButtonAmBegginer);
|
||||||
tabPage1.Location = new Point(4, 24);
|
tabPageWelcome.Location = new Point(4, 24);
|
||||||
tabPage1.Name = "tabPage1";
|
tabPageWelcome.Name = "tabPageWelcome";
|
||||||
tabPage1.Padding = new Padding(3);
|
tabPageWelcome.Padding = new Padding(3);
|
||||||
tabPage1.Size = new Size(348, 384);
|
tabPageWelcome.Size = new Size(348, 384);
|
||||||
tabPage1.TabIndex = 0;
|
tabPageWelcome.TabIndex = 0;
|
||||||
tabPage1.Text = "Welcome!";
|
tabPageWelcome.Text = "Welcome!";
|
||||||
tabPage1.UseVisualStyleBackColor = true;
|
tabPageWelcome.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// label2
|
// label2
|
||||||
//
|
//
|
||||||
@ -96,65 +107,161 @@
|
|||||||
label1.TabIndex = 2;
|
label1.TabIndex = 2;
|
||||||
label1.Text = "(You can change these options later!)";
|
label1.Text = "(You can change these options later!)";
|
||||||
//
|
//
|
||||||
// radioButton2
|
// radioButtonAmExpert
|
||||||
//
|
//
|
||||||
radioButton2.AutoSize = true;
|
radioButtonAmExpert.AutoSize = true;
|
||||||
radioButton2.Location = new Point(6, 271);
|
radioButtonAmExpert.Location = new Point(6, 271);
|
||||||
radioButton2.Name = "radioButton2";
|
radioButtonAmExpert.Name = "radioButtonAmExpert";
|
||||||
radioButton2.Size = new Size(299, 34);
|
radioButtonAmExpert.Size = new Size(299, 34);
|
||||||
radioButton2.TabIndex = 1;
|
radioButtonAmExpert.TabIndex = 1;
|
||||||
radioButton2.TabStop = true;
|
radioButtonAmExpert.Text = "I’m an expert. Let me choose my own database and \r\nstorage options.";
|
||||||
radioButton2.Text = "I’m an expert. Let me choose my own database and \r\nstorage options.";
|
radioButtonAmExpert.UseVisualStyleBackColor = true;
|
||||||
radioButton2.UseVisualStyleBackColor = true;
|
radioButtonAmExpert.CheckedChanged += radioButtonAmExpert_CheckedChanged;
|
||||||
//
|
//
|
||||||
// radioButton1
|
// radioButtonAmBegginer
|
||||||
//
|
//
|
||||||
radioButton1.AutoSize = true;
|
radioButtonAmBegginer.AutoSize = true;
|
||||||
radioButton1.Checked = true;
|
radioButtonAmBegginer.Location = new Point(6, 246);
|
||||||
radioButton1.Location = new Point(6, 246);
|
radioButtonAmBegginer.Name = "radioButtonAmBegginer";
|
||||||
radioButton1.Name = "radioButton1";
|
radioButtonAmBegginer.Size = new Size(298, 19);
|
||||||
radioButton1.Size = new Size(298, 19);
|
radioButtonAmBegginer.TabIndex = 0;
|
||||||
radioButton1.TabIndex = 0;
|
radioButtonAmBegginer.Text = "I’m a beginner. Set things up for me automatically. ";
|
||||||
radioButton1.TabStop = true;
|
radioButtonAmBegginer.UseVisualStyleBackColor = true;
|
||||||
radioButton1.Text = "I’m a beginner. Set things up for me automatically. ";
|
radioButtonAmBegginer.CheckedChanged += radioButtonAmBegginer_CheckedChanged;
|
||||||
radioButton1.UseVisualStyleBackColor = true;
|
|
||||||
//
|
//
|
||||||
// tabPage2
|
// tabPageLicense
|
||||||
//
|
//
|
||||||
tabPage2.Location = new Point(4, 24);
|
tabPageLicense.Controls.Add(pictureBox2);
|
||||||
tabPage2.Name = "tabPage2";
|
tabPageLicense.Controls.Add(label4);
|
||||||
tabPage2.Padding = new Padding(3);
|
tabPageLicense.Controls.Add(radioButtonNoLicense);
|
||||||
tabPage2.Size = new Size(348, 384);
|
tabPageLicense.Controls.Add(buttonLoadLicenseFile);
|
||||||
tabPage2.TabIndex = 1;
|
tabPageLicense.Controls.Add(buttonValidateLicense);
|
||||||
tabPage2.Text = "tabPage2";
|
tabPageLicense.Controls.Add(textBox1);
|
||||||
tabPage2.UseVisualStyleBackColor = true;
|
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);
|
pictureBox2.Image = Properties.Resources.SETUPAPI_18_1_32x32x4;
|
||||||
button1.Name = "button1";
|
pictureBox2.Location = new Point(127, 262);
|
||||||
button1.Size = new Size(75, 23);
|
pictureBox2.Name = "pictureBox2";
|
||||||
button1.TabIndex = 2;
|
pictureBox2.Size = new Size(32, 32);
|
||||||
button1.Text = "Next >";
|
pictureBox2.TabIndex = 7;
|
||||||
button1.UseVisualStyleBackColor = true;
|
pictureBox2.TabStop = false;
|
||||||
|
pictureBox2.Click += pictureBox2_Click;
|
||||||
//
|
//
|
||||||
// button2
|
// label4
|
||||||
//
|
//
|
||||||
button2.Enabled = false;
|
label4.AutoSize = true;
|
||||||
button2.Location = new Point(338, 430);
|
label4.Location = new Point(22, 344);
|
||||||
button2.Name = "button2";
|
label4.Name = "label4";
|
||||||
button2.Size = new Size(75, 23);
|
label4.Size = new Size(299, 30);
|
||||||
button2.TabIndex = 3;
|
label4.TabIndex = 6;
|
||||||
button2.Text = "< Back";
|
label4.Text = "(You can also change between Licensed and Shareware \r\nmode later!)";
|
||||||
button2.UseVisualStyleBackColor = true;
|
//
|
||||||
|
// 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
|
// FirstRunWizard
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(7F, 15F);
|
AutoScaleDimensions = new SizeF(7F, 15F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(502, 465);
|
ClientSize = new Size(502, 465);
|
||||||
Controls.Add(button2);
|
Controls.Add(buttonBack);
|
||||||
Controls.Add(button1);
|
Controls.Add(buttonNext);
|
||||||
Controls.Add(tabControl1);
|
Controls.Add(tabControl1);
|
||||||
Controls.Add(pictureBox1);
|
Controls.Add(pictureBox1);
|
||||||
FormBorderStyle = FormBorderStyle.FixedSingle;
|
FormBorderStyle = FormBorderStyle.FixedSingle;
|
||||||
@ -165,8 +272,11 @@
|
|||||||
Text = "Voile - First Run Wizard";
|
Text = "Voile - First Run Wizard";
|
||||||
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
|
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit();
|
||||||
tabControl1.ResumeLayout(false);
|
tabControl1.ResumeLayout(false);
|
||||||
tabPage1.ResumeLayout(false);
|
tabPageWelcome.ResumeLayout(false);
|
||||||
tabPage1.PerformLayout();
|
tabPageWelcome.PerformLayout();
|
||||||
|
tabPageLicense.ResumeLayout(false);
|
||||||
|
tabPageLicense.PerformLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)pictureBox2).EndInit();
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,13 +284,22 @@
|
|||||||
|
|
||||||
private PictureBox pictureBox1;
|
private PictureBox pictureBox1;
|
||||||
private TabControl tabControl1;
|
private TabControl tabControl1;
|
||||||
private TabPage tabPage1;
|
private TabPage tabPageWelcome;
|
||||||
private TabPage tabPage2;
|
private TabPage tabPageLicense;
|
||||||
private Button button1;
|
private Button buttonNext;
|
||||||
private Button button2;
|
private Button buttonBack;
|
||||||
private RadioButton radioButton1;
|
private RadioButton radioButtonAmBegginer;
|
||||||
private RadioButton radioButton2;
|
private RadioButton radioButtonAmExpert;
|
||||||
private Label label1;
|
private Label label1;
|
||||||
private Label label2;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -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.Collections.Generic;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
@ -7,6 +10,7 @@ using System.Linq;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
using Voile.Properties;
|
||||||
|
|
||||||
namespace Voile
|
namespace Voile
|
||||||
{
|
{
|
||||||
@ -19,8 +23,22 @@ namespace Voile
|
|||||||
}
|
}
|
||||||
|
|
||||||
private TabPage[] allPages;
|
private TabPage[] allPages;
|
||||||
public void DisplayTabPage(int target)
|
private int currentTabPage;
|
||||||
|
private Stack<int> 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<int>();
|
||||||
|
else
|
||||||
|
pastPages.Push(target);
|
||||||
|
|
||||||
if (allPages == null)
|
if (allPages == null)
|
||||||
{
|
{
|
||||||
allPages = new TabPage[tabControl1.TabPages.Count];
|
allPages = new TabPage[tabControl1.TabPages.Count];
|
||||||
@ -32,6 +50,177 @@ namespace Voile
|
|||||||
|
|
||||||
tabControl1.TabPages.Clear();
|
tabControl1.TabPages.Clear();
|
||||||
tabControl1.TabPages.Add(allPages[target]);
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -135,4 +135,17 @@ up automatically so you can start using the app right away.
|
|||||||
|
|
||||||
How would you like to continue?</value>
|
How would you like to continue?</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="label3.Text" xml:space="preserve">
|
||||||
|
<value>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.</value>
|
||||||
|
</data>
|
||||||
|
<metadata name="openFileDialogCertificate.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
|
<value>17, 17</value>
|
||||||
|
</metadata>
|
||||||
</root>
|
</root>
|
||||||
50
Voile/Properties/Resources.Designer.cs
generated
50
Voile/Properties/Resources.Designer.cs
generated
@ -100,6 +100,16 @@ namespace Voile.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap iblicense_133_1_32x32x4 {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("iblicense_133_1_32x32x4", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -110,6 +120,26 @@ namespace Voile.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap SETUPAPI_18_1_32x32x4 {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("SETUPAPI_18_1_32x32x4", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
|
||||||
|
/// </summary>
|
||||||
|
internal static byte[] sophianet_cert {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("sophianet_cert", resourceCulture);
|
||||||
|
return ((byte[])(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -120,6 +150,26 @@ namespace Voile.Properties {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap TRFFC10A_1_32x32x4 {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("TRFFC10A_1_32x32x4", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
|
/// </summary>
|
||||||
|
internal static System.Drawing.Bitmap TRFFC10C_1_32x32x4 {
|
||||||
|
get {
|
||||||
|
object obj = ResourceManager.GetObject("TRFFC10C_1_32x32x4", resourceCulture);
|
||||||
|
return ((System.Drawing.Bitmap)(obj));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -131,12 +131,27 @@
|
|||||||
<value>..\Resources\H_POINT.CUR;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>..\Resources\H_POINT.CUR;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
<comment>Mauszeiger</comment>
|
<comment>Mauszeiger</comment>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="iblicense_133_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\iblicense_133_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
<data name="inetwiz_100_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="inetwiz_100_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\inetwiz_100_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\inetwiz_100_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="SETUPAPI_18_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\SETUPAPI_18_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="sophianet_cert" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\sophianet-cert.cer;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</data>
|
||||||
<data name="technlgy" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="technlgy" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\technlgy.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\technlgy.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TRFFC10A_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\TRFFC10A_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
|
<data name="TRFFC10C_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
|
<value>..\Resources\TRFFC10C_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
|
</data>
|
||||||
<data name="URLPKR_141_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
<data name="URLPKR_141_1_32x32x4" type="System.Resources.ResXFileRef, System.Windows.Forms">
|
||||||
<value>..\Resources\URLPKR_141_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
<value>..\Resources\URLPKR_141_1_32x32x4.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
|
||||||
</data>
|
</data>
|
||||||
|
|||||||
BIN
Voile/Resources/SETUPAPI_18_1_32x32x4.png
Normal file
BIN
Voile/Resources/SETUPAPI_18_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 394 B |
BIN
Voile/Resources/TRFFC09_1_32x32x4.png
Normal file
BIN
Voile/Resources/TRFFC09_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 341 B |
BIN
Voile/Resources/TRFFC10A_1_32x32x4.png
Normal file
BIN
Voile/Resources/TRFFC10A_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 382 B |
BIN
Voile/Resources/TRFFC10B_1_32x32x4.png
Normal file
BIN
Voile/Resources/TRFFC10B_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 342 B |
BIN
Voile/Resources/TRFFC10C_1_32x32x4.png
Normal file
BIN
Voile/Resources/TRFFC10C_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 376 B |
BIN
Voile/Resources/iblicense_133_1_32x32x4.png
Normal file
BIN
Voile/Resources/iblicense_133_1_32x32x4.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 360 B |
BIN
Voile/Resources/sophianet-cert.cer
Normal file
BIN
Voile/Resources/sophianet-cert.cer
Normal file
Binary file not shown.
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\skyscraper8\skyscraper8\skyscraper8.csproj" />
|
<ProjectReference Include="..\..\skyscraper8\skyscraper8\skyscraper8.csproj" />
|
||||||
<ProjectReference Include="..\Voile.Sqlite\Voile.SQLite.csproj" />
|
<ProjectReference Include="..\Sophia.Net.DRM\Sophia.Net.DRM.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using skyscraper5.Skyscraper;
|
using Org.BouncyCastle.X509;
|
||||||
|
using skyscraper5.Skyscraper;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -47,5 +48,6 @@ namespace Voile
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Ini Ini { get; set; }
|
public Ini Ini { get; set; }
|
||||||
|
public X509Certificate SophiaNetRootCertificate { get; internal set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user