public void CacheLocationsTest() { var config = new DecryptConfig(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom).IsTrue(); config.CacheLocations = new CertificateCacheLocation[0]; config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory).IsFalse(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store).IsFalse(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom).IsFalse(); config.CacheLocations = new[] { CertificateCacheLocation.Memory }; config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store).IsFalse(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom).IsFalse(); config.CacheLocations = new[] { CertificateCacheLocation.Memory, CertificateCacheLocation.Custom, CertificateCacheLocation.Store }; config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom).IsTrue(); config.CacheLocations = new[] { CertificateCacheLocation.Memory, CertificateCacheLocation.Store, CertificateCacheLocation.Store }; config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store).IsTrue(); config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom).IsFalse(); }
/// <summary> /// ホスト名からサーバー証明書を取得 /// </summary> /// <param name="host">ホスト名</param> /// <param name="config">復号化設定</param> /// <returns>サーバー証明書</returns> public static X509Certificate2 GetServerCertificate(string host, DecryptConfig config) { X509Certificate2 root; if ((root = config.RootCertificateResolver(config.CertificateStore)) == null) { throw new RootCertificateNotFoundException(); } var cacheResolvers = config.CacheLocations .Select(x => { switch (x) { case CertificateCacheLocation.Memory: return(h => onMemoryCache.TryGetValue(h, out var cached) ? cached : null); case CertificateCacheLocation.Store: return(h => config.CertificateStore.FindServerCertificate(h, root)); case CertificateCacheLocation.Custom: return(config.ServerCertificateCacheResolver); default: return(h => null); } }); X509Certificate2 cert = null; var semaphore = hostLock.GetOrAdd(host, new SemaphoreSlim(1, 1)); try { // 同時に同じホストの処理が実行されると重複した証明書が作成されてしまう semaphore.Wait(); if (cacheResolvers.All(x => (cert = x?.Invoke(host)) == null)) { cert = config.CertificateFactory.CreateServerCertificate(host, root); if (config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Memory)) { onMemoryCache.TryAdd(host, cert); } if (config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Store)) { config.CertificateStore.InstallToPersonalStore(cert); } if (config.CacheLocationFlags.HasFlag(CertificateCacheLocation.Custom)) { config.InvokeServerCertificateCreated(config.CertificateFactory, cert); } } } finally { hostLock.TryRemove(host, out var _); semaphore.Release(); } return(cert); }
public void FacadeTest() { var rootStore = new X509TestStore(); var myStore = new X509TestStore(); var store = new CertificateStore { StoreFactory = name => name == StoreName.Root ? rootStore : name == StoreName.My ? myStore : null }; var config = new DecryptConfig { CertificateFactory = new BouncyCastleCertificateFactory(), CertificateStore = store, }; Assert.Throws <RootCertificateNotFoundException>( () => CertificateStoreFacade.GetServerCertificate($"host", config)); store.InstallToRootStore(CertificateUtil.CreateRootCertificate()); var bag = new ConcurrentBag <X509Certificate2>(); // パラレルで100個要求してもホスト10種のみ作成される Parallel.For(0, 100, i => { var num = i / 10; bag.Add(CertificateStoreFacade.GetServerCertificate($"host{num}", config)); }); var result = bag.ToArray(); result.Length.Is(100); CertificateStoreFacade.onMemoryCache.Count.Is(10); myStore.Certificates.Count.Is(10); var certs = CertificateStoreFacade.onMemoryCache.Values.OrderBy(x => x.Subject).ToArray(); for (int i = 0; i < 10; i++) { certs[i].Subject.Is($"CN=host{i}"); } }
bool DoDecrypt(ITrack track, string serverCert) { var config = new DecryptConfig(Filename, track.GetTrackType(), track.Id, Config.License, null, track.InitDataB64, serverCert); string encryptedName = track.GetFilename(Filename, false, false); string decryptedName = track.GetFilename(Filename, true, false); Cleanup.Add(track.GetFilename(Filename, true, false)); int retries = 0; while (retries < 10) { Decrypter decrypt = new Decrypter(config); var challenge = decrypt.GetChallenge(); string licenseB64 = Client.GetLicense(challenge); if (licenseB64 == null) { retries++; continue; } if (!decrypt.UpdateLicense(licenseB64)) { retries++; continue; } decrypt.StartProcess(); if (File.Exists(encryptedName) && File.Exists(decryptedName) && !Config.SkipCleanup) { File.Delete(encryptedName); } return(true); } return(false); }