EvEnSGRIANch

Untitled

Jan 31st, 2022
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 45.48 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Security.Cryptography;
  5. using Microsoft.EntityFrameworkCore;
  6. using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
  7. using static NonCryptographicHelpers;
  8. using static options;
  9.  
  10. var rand = new Random();
  11. var watch = new Stopwatch();
  12. var fs = new FileStream("output.txt", FileMode.Create);
  13. var sw = new StreamWriter(fs);
  14. Console.SetOut(sw);
  15. for (int w = 0; w < 5; w++)
  16.     for (int exp = 3; exp < 7; exp++)
  17.     {
  18.         for (int numUsers = 10; numUsers < 40; numUsers += 10)
  19.         {
  20.             int numberOfUsers = (int)Math.Pow(10, exp);
  21.             Console.WriteLine("Control: Using no encryption");
  22.             using (var context = new UnencryptedDbContext())
  23.             {
  24.                 context.Database.EnsureDeleted();
  25.                 context.Database.EnsureCreated();
  26.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  27.                 for (int i = 0; i < numberOfUsers; i++)
  28.                 {
  29.                     context.Add(new BasicEntity
  30.                     {
  31.                         EmailAddress = $"{rand.Next()}-{rand.Next()}@example.com"
  32.                     });
  33.                 }
  34.                 Console.WriteLine("Saving changes");
  35.                 context.SaveChanges();
  36.  
  37.                 Console.WriteLine($"Adding {numUsers} users individually");
  38.                 for (int i = 0; i < numUsers; i++)
  39.                 {
  40.                     watch.Restart();
  41.                     watch.Start();
  42.                     context.Add(new BasicEntity
  43.                     {
  44.                         EmailAddress = $"{rand.Next()}-{rand.Next()}@example.com"
  45.                     });
  46.                     context.SaveChanges();
  47.                     watch.Stop();
  48.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  49.                 }
  50.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  51.                 var ids = context.BasicEntities.Take(numUsers).Select(_ => _.Id).ToArray();
  52.                 for (int j = 0; j < 2; j++)
  53.                     for (int i = 0; i < numUsers; i++)
  54.                     {
  55.                         watch.Restart();
  56.                         watch.Start();
  57.                         var u = context.BasicEntities.Find(ids[i]);
  58.                         u.EmailAddress = $"{rand.Next()}-{rand.Next()}@example.com";
  59.                         context.SaveChanges();
  60.                         watch.Stop();
  61.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  62.                     }
  63.             }
  64.             Console.WriteLine("Control: using a fixed number of buckets");
  65.  
  66.             using (var context = new BucketedEncryptedDbContext())
  67.             {
  68.                 int bucketExponent = GetBucketExponent(numberOfUsers);
  69.                 context.Database.EnsureDeleted();
  70.                 context.Database.EnsureCreated();
  71.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  72.                 for (int i = 0; i < numberOfUsers; i++)
  73.                 {
  74.                     context.Add(new BucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent));
  75.                 }
  76.                 Console.WriteLine("Saving changes");
  77.                 context.SaveChanges();
  78.  
  79.                 Console.WriteLine($"Adding {numUsers} users individually");
  80.                 for (int i = 0; i < numUsers; i++)
  81.                 {
  82.                     watch.Restart();
  83.                     watch.Start();
  84.                     BucketedEntity entity;
  85.                     bool conflict = false;
  86.                     do
  87.                     {
  88.                         entity = new BucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent);
  89.                         foreach (var other in context.BucketedEntities.Where(_ => _.BucketNo == entity.BucketNo))
  90.                         {
  91.                             if (other.EmailAddress == entity.EmailAddress)
  92.                             {
  93.                                 Console.WriteLine("ERROR: CONFLICT. RESTARTING ITERATION.");
  94.                                 conflict = true;
  95.                             }
  96.  
  97.                         }
  98.                     } while (conflict);
  99.                     context.Add(entity);
  100.                     context.SaveChanges();
  101.                     watch.Stop();
  102.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  103.                 }
  104.  
  105.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  106.                 var ids = context.BucketedEntities.Take(numUsers).Select(_ => _.Id).ToArray();
  107.                 for (int j = 0; j < 2; j++)
  108.                     for (int i = 0; i < numUsers; i++)
  109.                     {
  110.                         watch.Restart();
  111.                         watch.Start();
  112.                         var u = context.BucketedEntities.Find(ids[i]);
  113.  
  114.                         BucketedEntity entity;
  115.                         bool conflict = false;
  116.                         do
  117.                         {
  118.                             entity = new BucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent);
  119.                             foreach (var other in context.BucketedEntities.Where(_ => _.BucketNo == entity.BucketNo))
  120.                             {
  121.                                 if (other.EmailAddress == entity.EmailAddress)
  122.                                 {
  123.                                     Console.WriteLine("ERROR: CONFLICT. RESTARTING ITERATION.");
  124.                                     conflict = true;
  125.                                 }
  126.  
  127.                             }
  128.                         } while (conflict);
  129.                         u.EmailAddress = entity.EmailAddress;
  130.                         u.BucketNo = entity.BucketNo;
  131.                         context.SaveChanges();
  132.                         context.SaveChanges();
  133.                         watch.Stop();
  134.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  135.                     }
  136.             }
  137.  
  138.             Console.WriteLine("Using `SELECT COUNT(*)` for updates to BucketCount, storing BucketExponent in the entity");
  139.  
  140.             using (var context = new BucketExponentStoringDbContext())
  141.             {
  142.                 context.Database.EnsureDeleted();
  143.                 context.Database.EnsureCreated();
  144.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  145.                 for (int i = 0; i < numberOfUsers; i++)
  146.                 {
  147.                     context.Add(new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", GetBucketExponent(i)));
  148.                 }
  149.                 Console.WriteLine("Saving changes");
  150.                 context.SaveChanges();
  151.  
  152.                 Console.WriteLine($"Adding {numUsers} users individually");
  153.                 for (int i = 0; i < numUsers; i++)
  154.                 {
  155.                     watch.Restart();
  156.                     watch.Start();
  157.                     BucketExponentStoringBucketedEntity entity;
  158.                     bool conflict = false;
  159.                     var counts = context.BucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  160.                     var currentCount = context.BucketExponentStoringBucketedEntities.Count();
  161.                     do
  162.                     {
  163.                         entity = new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  164.                         var buckets = counts.Select(_ => new BucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  165.                         foreach (var b in buckets)
  166.                         {
  167.                             var others = context.BucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  168.                             foreach (var o in others)
  169.                             {
  170.                                 if (o.EmailAddress == entity.EmailAddress)
  171.                                 {
  172.                                     conflict = true;
  173.                                     break;
  174.                                 }
  175.                             }
  176.                             if (conflict) { break; }
  177.                         }
  178.                     } while (conflict);
  179.                     context.Add(entity);
  180.                     context.SaveChanges();
  181.                     watch.Stop();
  182.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  183.                 }
  184.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  185.                 var ids = context.BucketExponentStoringBucketedEntities.Take(numUsers).Select(_ => _.Id).ToArray();
  186.                 for (int j = 0; j < 2; j++)
  187.                     for (int i = 0; i < numUsers; i++)
  188.                     {
  189.                         watch.Restart();
  190.                         watch.Start();
  191.                         var u = context.BucketExponentStoringBucketedEntities.Find(ids[i]);
  192.                         BucketExponentStoringBucketedEntity entity;
  193.                         bool conflict = false;
  194.                         var counts = context.BucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  195.                         var currentCount = context.BucketExponentStoringBucketedEntities.Count();
  196.                         do
  197.                         {
  198.                             entity = new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  199.                             var buckets = counts.Select(_ => new BucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  200.                             foreach (var b in buckets)
  201.                             {
  202.                                 var others = context.BucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  203.                                 foreach (var o in others)
  204.                                 {
  205.                                     if (o.EmailAddress == entity.EmailAddress)
  206.                                     {
  207.                                         conflict = true;
  208.                                         break;
  209.                                     }
  210.                                 }
  211.                                 if (conflict) { break; }
  212.                             }
  213.                         } while (conflict);
  214.                         u.BucketExponent = entity.BucketExponent;
  215.                         u.BucketNo = entity.BucketNo;
  216.                         u.EmailAddress = entity.EmailAddress;
  217.                         context.SaveChanges();
  218.                         watch.Stop();
  219.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  220.                     }
  221.             }
  222.             Console.WriteLine("Using a summary table for updates to BucketCount, storing BucketExponent in the entity");
  223.  
  224.             using (var context = new KeyValuedBucketExponentStoringDbContext())
  225.             {
  226.                 context.Database.EnsureDeleted();
  227.                 context.Database.EnsureCreated();
  228.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  229.                 for (int i = 0; i < numberOfUsers; i++)
  230.                 {
  231.                     context.Add(new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", GetBucketExponent(i)));
  232.                 }
  233.                 context.KeyValues.Single().value = numberOfUsers;
  234.                 Console.WriteLine("Saving changes");
  235.                 context.SaveChanges();
  236.  
  237.                 Console.WriteLine($"Adding {numUsers} users individually");
  238.                 for (int i = 0; i < numUsers; i++)
  239.                 {
  240.                     watch.Restart();
  241.                     watch.Start();
  242.                     BucketExponentStoringBucketedEntity entity;
  243.                     bool conflict = false;
  244.                     var counts = context.BucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  245.                     var currentCount = context.KeyValues.Single().value;
  246.                     do
  247.                     {
  248.                         entity = new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  249.                         var buckets = counts.Select(_ => new BucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  250.                         foreach (var b in buckets)
  251.                         {
  252.                             var others = context.BucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  253.                             foreach (var o in others)
  254.                             {
  255.                                 if (o.EmailAddress == entity.EmailAddress)
  256.                                 {
  257.                                     conflict = true;
  258.                                     break;
  259.                                 }
  260.                             }
  261.                             if (conflict) { break; }
  262.                         }
  263.                     } while (conflict);
  264.                     context.Add(entity);
  265.                     context.KeyValues.Single().value++;
  266.                     context.SaveChanges();
  267.                     watch.Stop();
  268.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  269.                 }
  270.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  271.                 var ids = context.BucketExponentStoringBucketedEntities.Take(numUsers).Select(_ => _.Id).ToArray();
  272.                 for (int j = 0; j < 2; j++)
  273.                     for (int i = 0; i < numUsers; i++)
  274.                     {
  275.                         watch.Restart();
  276.                         watch.Start();
  277.                         var u = context.BucketExponentStoringBucketedEntities.Find(ids[i]);
  278.                         BucketExponentStoringBucketedEntity entity;
  279.                         bool conflict = false;
  280.                         var counts = context.BucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  281.                         var currentCount = context.KeyValues.Single().value;
  282.                         do
  283.                         {
  284.                             entity = new BucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  285.                             var buckets = counts.Select(_ => new BucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  286.                             foreach (var b in buckets)
  287.                             {
  288.                                 var others = context.BucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  289.                                 foreach (var o in others)
  290.                                 {
  291.                                     if (o.EmailAddress == entity.EmailAddress)
  292.                                     {
  293.                                         conflict = true;
  294.                                         break;
  295.                                     }
  296.                                 }
  297.                                 if (conflict) { break; }
  298.                             }
  299.                         } while (conflict);
  300.                         u.BucketExponent = entity.BucketExponent;
  301.                         u.BucketNo = entity.BucketNo;
  302.                         u.EmailAddress = entity.EmailAddress;
  303.                         context.SaveChanges();
  304.                         watch.Stop();
  305.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  306.                     }
  307.             }
  308.  
  309.             Console.WriteLine("Using autoincremented row numbers");
  310.  
  311.             using (var context = new RowCountedBucketExponentStoringDbContext())
  312.             {
  313.                 context.Database.EnsureDeleted();
  314.                 context.Database.EnsureCreated();
  315.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  316.                 for (int i = 0; i < numberOfUsers; i++)
  317.                 {
  318.                     context.Add(new RowCountedBucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", GetBucketExponent(i)));
  319.                 }
  320.                 Console.WriteLine("Saving changes");
  321.                 context.SaveChanges();
  322.  
  323.                 Console.WriteLine($"Adding {numUsers} users individually");
  324.                 for (int i = 0; i < numUsers; i++)
  325.                 {
  326.                     watch.Restart();
  327.                     watch.Start();
  328.                     RowCountedBucketExponentStoringBucketedEntity entity;
  329.                     bool conflict = false;
  330.                     var counts = context.RowCountedBucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  331.                     var currentCount = context.RowCountedBucketExponentStoringBucketedEntities.Max(_ => _.EntryNo);
  332.                     do
  333.                     {
  334.                         entity = new RowCountedBucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  335.                         var buckets = counts.Select(_ => new RowCountedBucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  336.                         foreach (var b in buckets)
  337.                         {
  338.                             var others = context.RowCountedBucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  339.                             foreach (var o in others)
  340.                             {
  341.                                 if (o.EmailAddress == entity.EmailAddress)
  342.                                 {
  343.                                     conflict = true;
  344.                                     break;
  345.                                 }
  346.                             }
  347.                             if (conflict) { break; }
  348.                         }
  349.                     } while (conflict);
  350.                     context.Add(entity);
  351.                     context.SaveChanges();
  352.                     watch.Stop();
  353.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  354.                 }
  355.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  356.                 var ids = context.RowCountedBucketExponentStoringBucketedEntities.Take(numUsers).Select(_ => _.Id).ToArray();
  357.                 for (int j = 0; j < 2; j++)
  358.                     for (int i = 0; i < numUsers; i++)
  359.                     {
  360.                         watch.Restart();
  361.                         watch.Start();
  362.                         var u = context.RowCountedBucketExponentStoringBucketedEntities.Find(ids[i]);
  363.                         RowCountedBucketExponentStoringBucketedEntity entity;
  364.                         bool conflict = false;
  365.                         var currentCount = context.RowCountedBucketExponentStoringBucketedEntities.Max(_ => _.EntryNo);
  366.                         var counts = context.RowCountedBucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  367.                         do
  368.                         {
  369.                             entity = new RowCountedBucketExponentStoringBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", currentCount);
  370.                             var buckets = counts.Select(_ => new RowCountedBucketExponentStoringBucketedEntity(entity.EmailAddress, _)).ToList();
  371.                             foreach (var b in buckets)
  372.                             {
  373.                                 var others = context.RowCountedBucketExponentStoringBucketedEntities.Where(_ => _.BucketNo == b.BucketNo && _.BucketExponent == b.BucketExponent).ToList();
  374.                                 foreach (var o in others)
  375.                                 {
  376.                                     if (o.EmailAddress == entity.EmailAddress)
  377.                                     {
  378.                                         conflict = true;
  379.                                         break;
  380.                                     }
  381.                                 }
  382.                                 if (conflict) { break; }
  383.                             }
  384.                         } while (conflict);
  385.                         u.BucketExponent = entity.BucketExponent;
  386.                         u.BucketNo = entity.BucketNo;
  387.                         u.EmailAddress = entity.EmailAddress;
  388.                         context.SaveChanges();
  389.                         watch.Stop();
  390.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  391.                     }
  392.             }
  393.  
  394.             Console.WriteLine("Using `SELECT COUNT(*)` for updates to BucketCount, updating all bucket numbers after threshold is passed");
  395.  
  396.             using (var context = new TimestampedDbContext())
  397.             {
  398.                 Console.WriteLine($"Seeding DB with {numberOfUsers} users ");
  399.                 context.Database.EnsureDeleted();
  400.                 context.Database.EnsureCreated();
  401.                 for (int i = 0; i < numberOfUsers; i++)
  402.                 {
  403.  
  404.                     int bucketExponent = GetBucketExponent(numberOfUsers);
  405.                     context.Add(new TimestampedBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent));
  406.                     context.SaveChanges();
  407.                 }
  408.                 Console.WriteLine("Saving changes");
  409.                 context.SaveChanges();
  410.  
  411.                 Console.WriteLine($"Adding {numUsers} users individually");
  412.                 for (int i = 0; i < numUsers; i++)
  413.                 {
  414.                     watch.Restart();
  415.                     watch.Start();
  416.  
  417.                     TimestampedBucketedEntity entity;
  418.                     bool conflict = false;
  419.                     var currentCount = context.TimestampedBucketedEntity.Count();
  420.                     int bucketExponent = GetBucketExponent(currentCount + 1);
  421.                     if (GetBucketExponent(currentCount) != GetBucketExponent(currentCount - 1))
  422.                     {
  423.                         foreach (var v in context.TimestampedBucketedEntity)
  424.                         {
  425.                             v.EmailAddress = v.EmailAddress;
  426.                             v.BucketNo = new BucketedEntity(v.EmailAddress, bucketExponent).BucketNo;
  427.                             v.EmailUpdated = DateTime.UtcNow;
  428.                         }
  429.                     }
  430.                     do
  431.                     {
  432.                         entity = new TimestampedBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent);
  433.                         foreach (var other in context.TimestampedBucketedEntity.Where(_ => _.BucketNo == entity.BucketNo))
  434.                         {
  435.                             if (other.EmailAddress == entity.EmailAddress)
  436.                             {
  437.                                 Console.WriteLine("ERROR: CONFLICT. RESTARTING ITERATION.");
  438.                                 conflict = true;
  439.                             }
  440.  
  441.                         }
  442.                     } while (conflict);
  443.                     context.SaveChanges();
  444.                     watch.Stop();
  445.                     Console.WriteLine($"Iteration {i} took {watch.ElapsedTicks} ticks");
  446.                 }
  447.  
  448.  
  449.                 Console.WriteLine($"Changing {numUsers} users email addresses, twice each");
  450.                 var ids = context.TimestampedBucketedEntity.Take(numUsers).Select(_ => _.Id).ToArray();
  451.                 for (int j = 0; j < 2; j++)
  452.                     for (int i = 0; i < numUsers; i++)
  453.                     {
  454.                         watch.Restart();
  455.                         watch.Start();
  456.                         var currentCount = context.TimestampedBucketedEntity.Count();
  457.                         var bucketExponent = GetBucketExponent(currentCount);
  458.                         var u = context.TimestampedBucketedEntity.Find(ids[i]);
  459.  
  460.                         TimestampedBucketedEntity entity;
  461.                         bool conflict = false;
  462.                         do
  463.                         {
  464.                             entity = new TimestampedBucketedEntity($"{rand.Next()}-{rand.Next()}@example.com", bucketExponent);
  465.                             foreach (var other in context.TimestampedBucketedEntity.Where(_ => _.BucketNo == entity.BucketNo))
  466.                             {
  467.                                 if (other.EmailAddress == entity.EmailAddress)
  468.                                 {
  469.                                     Console.WriteLine("ERROR: CONFLICT. RESTARTING ITERATION.");
  470.                                     conflict = true;
  471.                                 }
  472.  
  473.                             }
  474.                         } while (conflict);
  475.                         u.EmailAddress = entity.EmailAddress;
  476.                         u.BucketNo = entity.BucketNo;
  477.                         context.SaveChanges();
  478.                         context.SaveChanges();
  479.                         watch.Stop();
  480.                         Console.WriteLine($"Iteration {j} on user {i} took {watch.ElapsedTicks} ticks");
  481.                     }
  482.             }
  483.         }
  484.     }
  485. sw.Close();
  486.  
  487. /* RowCountedTimestampedDbContext
  488. using (var context = new RowCountedTimestampedDbContext())
  489. {
  490.     context.Database.EnsureDeleted();
  491.     context.Database.EnsureCreated();
  492.     for (int i = 0; i < 333; i++)
  493.     {
  494.         int count = 0;
  495.         try{
  496.             count = context.RowCountedTimestampedBucketedEntity.Select(_ => _.EntryNo).Max();
  497.         }catch{}
  498.         int bucketExponent = GetBucketExponent(count);
  499.         if(GetBucketExponent(count) != GetBucketExponent(count - 1)){
  500.             foreach(var v in context.RowCountedTimestampedBucketedEntity){
  501.                 v.EmailAddress = v.EmailAddress;
  502.                 v.BucketNo = new BucketedEntity(v.EmailAddress, bucketExponent).BucketNo;
  503.                 v.EmailUpdated = DateTime.UtcNow;
  504.             }
  505.         }
  506.         context.Add(new RowCountedTimestampedBucketedEntity($"{i}_{rand.Next()}@example.com", bucketExponent));
  507.         context.SaveChanges();
  508.     }
  509. }*/
  510.  
  511.  
  512. /* save to TimestampedDbContext
  513. using (var context = new TimestampedDbContext())
  514. {
  515.     context.Database.EnsureDeleted();
  516.     context.Database.EnsureCreated();
  517.     for (int i = 0; i < 333; i++)
  518.     {
  519.         int bucketExponent = GetBucketExponent(context.TimestampedBucketedEntity.Count());
  520.         var count = context.TimestampedBucketedEntity.Count();
  521.         if(GetBucketExponent(count) != GetBucketExponent(count - 1)){
  522.             foreach(var v in context.TimestampedBucketedEntity){
  523.                 v.EmailAddress = v.EmailAddress;
  524.                 v.BucketNo = new BucketedEntity(v.EmailAddress, bucketExponent).BucketNo;
  525.                 v.EmailUpdated = DateTime.UtcNow;
  526.             }
  527.         }
  528.         context.Add(new TimestampedBucketedEntity($"{i}_{rand.Next()}@example.com", bucketExponent));
  529.         context.SaveChanges();
  530.     }
  531. }
  532. */
  533.  
  534. /* Fetch from bucketexponentstoringdbcontext
  535.  
  536. using (var context = new BucketExponentStoringDbContext())
  537. using (var context2 = new BucketExponentStoringDbContext())
  538. using (var context3 = new BucketExponentStoringDbContext())
  539. {
  540.     var exponents = context3.BucketExponentStoringBucketedEntities.Select(_ => _.BucketExponent).Distinct().ToList();
  541.     foreach (var v in context.BucketExponentStoringBucketedEntities)
  542.     {
  543.         var bucketNumbers = exponents.Select(_ => new BucketedEntity(v.EmailAddress, _).BucketNo);
  544.         Console.WriteLine($"EmailAddress: {v.EmailAddress}");
  545.         Console.WriteLine($"BucketNo: {v.BucketNo}");
  546.         Console.WriteLine($"Others: {context2.BucketExponentStoringBucketedEntities.Where(_ => bucketNumbers.Contains(_.BucketNo)).Count()}");
  547.  
  548.     }
  549. }*/
  550.  
  551. // DbContexts
  552. public static class options
  553. {
  554.     public static string conn = "server=localhost;port=3306;database=tmp;uid=devuser;pwd=Pa55w0rd!";
  555.     public static ServerVersion srvvrs = ServerVersion.Parse("8.0.27-mysql");
  556. }
  557. public class UnencryptedDbContext : DbContext
  558. {
  559.     public DbSet<BasicEntity> BasicEntities { get; set; }
  560.     public UnencryptedDbContext() : base() { }
  561.  
  562.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  563.  
  564.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  565.     {
  566.         modelBuilder.Entity<BasicEntity>(e =>
  567.         {
  568.             e.HasIndex(e => e.EmailAddress)
  569.             .IsUnique();
  570.             e.Property(e => e.EmailAddress)
  571.             .IsRequired();
  572.         }
  573.         );
  574.     }
  575. }
  576. public class BasicEncryptedDbContext : DbContext
  577. {
  578.  
  579.     public DbSet<BasicEntity> BasicEntities { get; set; }
  580.     public BasicEncryptedDbContext() : base() { }
  581.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  582.  
  583.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  584.     {
  585.         modelBuilder.Entity<BasicEntity>(e =>
  586.         {
  587.             e.HasIndex(e => e.EmailAddress)
  588.             .IsUnique();
  589.             e.Property(e => e.EmailAddress)
  590.             .IsRequired().HasConversion<PersonalDataConverter>();
  591.         });
  592.     }
  593. }
  594.  
  595. public class BucketedEncryptedDbContext : DbContext
  596. {
  597.     public DbSet<BucketedEntity> BucketedEntities { get; set; }
  598.     public BucketedEncryptedDbContext() : base() { }
  599.  
  600.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  601.  
  602.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  603.     {
  604.         modelBuilder.Entity<BucketedEntity>(e =>
  605.         {
  606.             e.HasIndex(e => e.EmailAddress)
  607.             .IsUnique();
  608.             e.HasIndex(e => e.BucketNo);
  609.             e.Property(e => e.EmailAddress)
  610.             .IsRequired().HasConversion<PersonalDataConverter>();
  611.         }
  612.         );
  613.     }
  614. }
  615.  
  616.  
  617. public class RowCountedBucketExponentStoringDbContext : DbContext
  618. {
  619.     public DbSet<RowCountedBucketExponentStoringBucketedEntity> RowCountedBucketExponentStoringBucketedEntities { get; set; }
  620.     public RowCountedBucketExponentStoringDbContext() : base() { }
  621.  
  622.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  623.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  624.     {
  625.         modelBuilder.Entity<RowCountedBucketExponentStoringBucketedEntity>(e =>
  626.         {
  627.             e.HasIndex(e => e.EmailAddress)
  628.             .IsUnique();
  629.             e.HasIndex(e => e.BucketNo);
  630.             e.HasIndex(e => e.BucketExponent);
  631.  
  632.             e.HasAlternateKey(e => e.EntryNo);
  633.             e.Property(e => e.EntryNo).ValueGeneratedOnAdd();
  634.             e.Property(e => e.EmailAddress)
  635.             .IsRequired().HasConversion<PersonalDataConverter>();
  636.         }
  637.         );
  638.     }
  639. }
  640.  
  641. public class RowCountedTimestampedDbContext : DbContext
  642. {
  643.     public DbSet<RowCountedTimestampedBucketedEntity> RowCountedTimestampedBucketedEntity { get; set; }
  644.     public RowCountedTimestampedDbContext() : base() { }
  645.  
  646.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  647.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  648.     {
  649.         modelBuilder.Entity<RowCountedTimestampedBucketedEntity>(e =>
  650.         {
  651.             e.HasIndex(e => e.EmailAddress)
  652.             .IsUnique();
  653.  
  654.             e.HasAlternateKey(e => e.EntryNo);
  655.             e.Property(e => e.EntryNo).ValueGeneratedOnAdd(); e.HasIndex(e => e.BucketNo);
  656.             e.Property(e => e.EmailUpdated).ValueGeneratedOnAddOrUpdate();
  657.             e.Property(e => e.EmailAddress)
  658.             .IsRequired().HasConversion<PersonalDataConverter>();
  659.         }
  660.         );
  661.     }
  662. }
  663.  
  664. public class RowCountedBucketedDbContext : DbContext
  665. {
  666.     public DbSet<RowCountedBucketedEntity> RowCountedBucketedEntities { get; set; }
  667.     public RowCountedBucketedDbContext() : base() { }
  668.  
  669.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  670.  
  671.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  672.     {
  673.         modelBuilder.Entity<RowCountedBucketedEntity>(e =>
  674.         {
  675.             e.HasIndex(e => e.EmailAddress)
  676.             .IsUnique();
  677.             e.HasIndex(e => e.BucketNo);
  678.             e.HasAlternateKey(e => e.EntryNo);
  679.             e.Property(e => e.EntryNo).ValueGeneratedOnAdd();
  680.             e.Property(e => e.EmailAddress)
  681.             .IsRequired().HasConversion<PersonalDataConverter>();
  682.         }
  683.         );
  684.     }
  685. }
  686.  
  687. public class BucketExponentStoringDbContext : DbContext
  688. {
  689.     public DbSet<BucketExponentStoringBucketedEntity> BucketExponentStoringBucketedEntities { get; set; }
  690.     public BucketExponentStoringDbContext() : base() { }
  691.  
  692.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  693.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  694.     {
  695.         modelBuilder.Entity<BucketExponentStoringBucketedEntity>(e =>
  696.         {
  697.             e.HasIndex(e => e.EmailAddress)
  698.             .IsUnique();
  699.             e.HasIndex(e => e.BucketNo);
  700.             e.HasIndex(e => e.BucketExponent);
  701.             e.Property(e => e.EmailAddress)
  702.             .IsRequired().HasConversion<PersonalDataConverter>();
  703.         }
  704.         );
  705.     }
  706. }
  707.  
  708. public class TimestampedDbContext : DbContext
  709. {
  710.     public DbSet<TimestampedBucketedEntity> TimestampedBucketedEntity { get; set; }
  711.     public TimestampedDbContext() : base() { }
  712.  
  713.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  714.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  715.     {
  716.         modelBuilder.Entity<TimestampedBucketedEntity>(e =>
  717.         {
  718.             e.HasIndex(e => e.EmailAddress)
  719.             .IsUnique();
  720.             e.HasIndex(e => e.BucketNo);
  721.             e.Property(e => e.EmailUpdated).ValueGeneratedOnAddOrUpdate();
  722.             e.Property(e => e.EmailAddress)
  723.             .IsRequired().HasConversion<PersonalDataConverter>();
  724.         }
  725.         );
  726.     }
  727. }
  728.  
  729.  
  730. public class KeyValuedBucketExponentStoringDbContext : DbContext
  731. {
  732.     public DbSet<BucketExponentStoringBucketedEntity> BucketExponentStoringBucketedEntities { get; set; }
  733.     public DbSet<KeyValues> KeyValues { get; set; }
  734.     public KeyValuedBucketExponentStoringDbContext() : base() { }
  735.  
  736.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  737.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  738.     {
  739.         modelBuilder.Entity<KeyValues>(e =>
  740.         {
  741.             e.HasKey(k => k.Key);
  742.             e.HasData(new KeyValues
  743.             {
  744.                 Key = "UserCount",
  745.                 value = 0
  746.             });
  747.         });
  748.         modelBuilder.Entity<BucketExponentStoringBucketedEntity>(e =>
  749.         {
  750.             e.HasIndex(e => e.EmailAddress)
  751.             .IsUnique();
  752.             e.HasIndex(e => e.BucketNo);
  753.             e.HasIndex(e => e.BucketExponent);
  754.             e.Property(e => e.EmailAddress)
  755.             .IsRequired().HasConversion<PersonalDataConverter>();
  756.         }
  757.         );
  758.     }
  759. }
  760.  
  761. public class KeyValuedTimestampedDbContext : DbContext
  762. {
  763.     public DbSet<TimestampedBucketedEntity> TimestampedBucketedEntity { get; set; }
  764.  
  765.     public DbSet<KeyValues> KeyValues { get; set; }
  766.     public KeyValuedTimestampedDbContext() : base() { }
  767.  
  768.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  769.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  770.     {
  771.         modelBuilder.Entity<KeyValues>(e =>
  772.         {
  773.             e.HasKey(k => k.Key);
  774.             e.HasData(new KeyValues
  775.             {
  776.                 Key = "UserCount",
  777.                 value = 0
  778.             });
  779.         });
  780.         modelBuilder.Entity<TimestampedBucketedEntity>(e =>
  781.         {
  782.             e.HasIndex(e => e.EmailAddress)
  783.             .IsUnique();
  784.             e.HasIndex(e => e.BucketNo);
  785.             e.Property(e => e.EmailUpdated).ValueGeneratedOnAddOrUpdate();
  786.             e.Property(e => e.EmailAddress)
  787.             .IsRequired().HasConversion<PersonalDataConverter>();
  788.         }
  789.         );
  790.     }
  791. }
  792.  
  793. public class KeyValuedBucketedDbContext : DbContext
  794. {
  795.     public DbSet<BucketedEntity> BucketedEntities { get; set; }
  796.     public KeyValuedBucketedDbContext() : base() { }
  797.  
  798.     public DbSet<KeyValues> KeyValues { get; set; }
  799.     protected override void OnConfiguring(DbContextOptionsBuilder options) => options.UseMySql(conn, srvvrs);
  800.  
  801.     protected override void OnModelCreating(ModelBuilder modelBuilder)
  802.     {
  803.         modelBuilder.Entity<KeyValues>(e =>
  804.         {
  805.             e.HasKey(k => k.Key);
  806.             e.HasData(new KeyValues
  807.             {
  808.                 Key = "UserCount",
  809.                 value = 0
  810.             });
  811.         });
  812.         modelBuilder.Entity<BucketedEntity>(e =>
  813.         {
  814.             e.HasIndex(e => e.EmailAddress)
  815.             .IsUnique();
  816.             e.HasIndex(e => e.BucketNo);
  817.             e.Property(e => e.EmailAddress)
  818.             .IsRequired().HasConversion<PersonalDataConverter>();
  819.         }
  820.         );
  821.     }
  822. }
  823.  
  824. // Entities
  825. public class BasicEntity
  826. {
  827.     public Guid Id { get; set; }
  828.     public string EmailAddress { get; set; } = "[email protected]";
  829. }
  830.  
  831. public class TimestampedBucketedEntity : BucketedEntity
  832. {
  833.     public TimestampedBucketedEntity() { }
  834.     public TimestampedBucketedEntity(string emailAddress, int bucketExponent) : base(emailAddress, bucketExponent) { }
  835.     public DateTime EmailUpdated { get; set; } = DateTime.UtcNow;
  836.  
  837. }
  838.  
  839. public class BucketExponentStoringBucketedEntity : BucketedEntity
  840. {
  841.  
  842.     public BucketExponentStoringBucketedEntity() { }
  843.     public BucketExponentStoringBucketedEntity(string emailAddress, int bucketExponent) : base(emailAddress, bucketExponent) { BucketExponent = bucketExponent; }
  844.     public int BucketExponent { get; set; }
  845. }
  846.  
  847. public class BucketedEntity
  848. {
  849.     public BucketedEntity() { }
  850.     public BucketedEntity(string emailAddress, int bucketExponent)
  851.     {
  852.         BucketNo = 0;
  853.         foreach (char c in emailAddress.ToLowerInvariant())
  854.         {
  855.             BucketNo += (int)c;
  856.         }
  857.         BucketNo %= (int)Math.Pow(2, bucketExponent);
  858.         EmailAddress = emailAddress;
  859.     }
  860.     public Guid Id { get; set; }
  861.     public string EmailAddress { get; set; } = "[email protected]";
  862.     public int BucketNo { get; set; } = 0;
  863. }
  864.  
  865. public class RowCountedBasicEntity
  866. {
  867.     public int EntryNo { get; set; } = 0;
  868.     public Guid Id { get; set; }
  869.     public string EmailAddress { get; set; } = "[email protected]";
  870. }
  871.  
  872. public class RowCountedTimestampedBucketedEntity : RowCountedBucketedEntity
  873. {
  874.     public RowCountedTimestampedBucketedEntity() { }
  875.     public RowCountedTimestampedBucketedEntity(string emailAddress, int bucketExponent) : base(emailAddress, bucketExponent) { }
  876.     public DateTime EmailUpdated { get; set; } = DateTime.UtcNow;
  877.  
  878. }
  879.  
  880. public class RowCountedBucketExponentStoringBucketedEntity : RowCountedBucketedEntity
  881. {
  882.  
  883.     public RowCountedBucketExponentStoringBucketedEntity() { }
  884.     public RowCountedBucketExponentStoringBucketedEntity(string emailAddress, int bucketExponent) : base(emailAddress, bucketExponent) { BucketExponent = bucketExponent; }
  885.     public int BucketExponent { get; set; }
  886. }
  887.  
  888. public class RowCountedBucketedEntity
  889. {
  890.     public RowCountedBucketedEntity() { }
  891.     public RowCountedBucketedEntity(string emailAddress, int bucketExponent)
  892.     {
  893.         BucketNo = 0;
  894.         foreach (char c in emailAddress.ToLowerInvariant())
  895.         {
  896.             BucketNo += (int)c;
  897.         }
  898.         BucketNo %= (int)Math.Pow(2, bucketExponent);
  899.         EmailAddress = emailAddress;
  900.     }
  901.     public Guid Id { get; set; }
  902.     public string EmailAddress { get; set; } = "[email protected]";
  903.     public int BucketNo { get; set; } = 0;
  904.     public int EntryNo { get; set; } = 0;
  905. }
  906.  
  907. public class KeyValues
  908. {
  909.     public string Key { get; set; }
  910.     public int value { get; set; }
  911. }
  912.  
  913. // Conversions
  914. internal static class TupleExtensions
  915. {
  916.     public static string ToBase64String(this (string s, byte[] b) input)
  917.     {
  918.         return Convert.ToBase64String(input.b) + " " + input.s;
  919.     }
  920. }
  921. internal static class ArrayExtensions
  922. {
  923.     public static string AesDecrypt(this string[] arr)
  924.     {
  925.         return AesEncryptionHelper.AesDecrypt(arr[1], Key.key, Convert
  926.             .FromBase64String(arr[0]));
  927.     }
  928. }
  929. public class PersonalDataConverter : ValueConverter<string, string>
  930. {
  931.     private const StringSplitOptions Sso =
  932.         StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries;
  933.     public PersonalDataConverter() : base(
  934.         cleartext => (AesEncryptionHelper.AesEncrypt(cleartext, Key.key, null))
  935.             .ToBase64String(),
  936.         ciphertext => ciphertext
  937.             .Split(" ", Sso)
  938.             .AesDecrypt()
  939.       , default
  940.     )
  941.     { }
  942. }
  943.  
  944. // non cryptographic hash functions
  945. public static class NonCryptographicHelpers
  946. {
  947.     public static int GetBucketExponent(int userCount)
  948.     {
  949.         if (userCount < 1) { return 1; }
  950.         return Math.Max((int)Math.Floor(Math.Log2(userCount)) - 3, 1);
  951.     }
  952. }
  953.  
  954. // Encryption
  955. public static class Key
  956. {
  957.     public static byte[] key = {
  958.         (byte) 33,
  959.         (byte) 40,
  960.         (byte) 212,
  961.         (byte) 209,
  962.         (byte) 219,
  963.         (byte) 205,
  964.         (byte) 88,
  965.         (byte) 100,
  966.         (byte) 20,
  967.         (byte) 23,
  968.         (byte) 131,
  969.         (byte) 149,
  970.         (byte) 104,
  971.         (byte) 200,
  972.         (byte) 215,
  973.         (byte) 17,
  974.         (byte) 36,
  975.         (byte) 102,
  976.         (byte) 106,
  977.         (byte) 19,
  978.         (byte) 165,
  979.         (byte) 234,
  980.         (byte) 163,
  981.         (byte) 139,
  982.         (byte) 133,
  983.         (byte) 63,
  984.         (byte) 139,
  985.         (byte) 249,
  986.         (byte) 224,
  987.         (byte) 41,
  988.         (byte) 186,
  989.         (byte) 209,
  990.     };
  991. }
  992.  
  993.  
  994. public static class AesEncryptionHelper
  995. {
  996.     /// <summary>
  997.     /// Encrypt the given secret using AES
  998.     /// </summary>
  999.     /// <param name="secret">plaintext to encrypt</param>
  1000.     /// <param name="key">The secret key to use to encrypt</param>
  1001.     /// <param name="IV">Optional initialization vector to use</param>
  1002.     /// <returns>A tuple containing the base64 encoded, encrypted ciphertext, and the initialization vector used.</returns>
  1003.     /// <exception cref="ArgumentException">Key or IV is incorrect length</exception>
  1004.     public static (string ciphertext, byte[] IV) AesEncrypt(string secret, in byte[] key, in byte[]? IV = null)
  1005.     {
  1006.         using (var aes = Aes.Create())
  1007.         {
  1008.             if (key.Length != aes.Key.Length)
  1009.             {
  1010.                 throw new ArgumentException("key length incorrect");
  1011.             }
  1012.             if (IV != null && IV.Length != aes.IV.Length)
  1013.             {
  1014.                 throw new ArgumentException("IV length incorrect");
  1015.             }
  1016.             aes.Key = key;
  1017.             if (IV != null)
  1018.             {
  1019.                 aes.IV = IV;
  1020.             }
  1021.             var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
  1022.             using (MemoryStream msEncrypt = new MemoryStream())
  1023.             {
  1024.                 using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
  1025.                 {
  1026.                     using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
  1027.                     {
  1028.                         swEncrypt.Write(secret);
  1029.                     }
  1030.                     return (Convert.ToBase64String(msEncrypt.ToArray()), aes.IV);
  1031.                 }
  1032.             }
  1033.         }
  1034.     }
  1035.     /// <summary>
  1036.     /// Decrypt the result of <see cref="AesEncrypt"/>
  1037.     /// </summary>
  1038.     /// <param name="secret">The base64 encoded, aes encrypted ciphertext</param>
  1039.     /// <param name="key">The secret key used to encrypt the secret</param>
  1040.     /// <param name="IV">The initialization vector used to encrypt the secret</param>
  1041.     /// <returns>The decrypted plaintext</returns>
  1042.     /// <exception cref="CryptographicException">Key or IV is incorrect length</exception>
  1043.     /// <exception cref="ArgumentNullException"/>
  1044.     /// <exception cref="FormatException">Secret is not a valid base 64 string </exception>
  1045.     public static string AesDecrypt(string secret, in byte[] key, in byte[] IV)
  1046.     {
  1047.         using (Aes aesAlg = Aes.Create())
  1048.         {
  1049.             aesAlg.Key = key;
  1050.             aesAlg.IV = IV;
  1051.  
  1052.             // Create a decryptor to perform the stream transform.
  1053.             ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
  1054.  
  1055.             // Create the streams used for decryption.
  1056.             using (MemoryStream msDecrypt = new MemoryStream(Convert.FromBase64String(secret)))
  1057.             {
  1058.                 using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
  1059.                 {
  1060.                     using (StreamReader srDecrypt = new StreamReader(csDecrypt))
  1061.                     {
  1062.  
  1063.                         // Read the decrypted bytes from the decrypting stream
  1064.                         // and place them in a string.
  1065.                         return srDecrypt.ReadToEnd();
  1066.                     }
  1067.                 }
  1068.             }
  1069.         }
  1070.     }
  1071. }
Add Comment
Please, Sign In to add comment