RSA encryption

     

Scenario:

Create a RSA public/private key for parties to communicate securely.

Solution:



Example: If Ram and Shyam wants to share messages securely they would use below algorithm RSA
  1. Generate Keys

  2. --It uses 3 numbers. 
    
    -p: which is a large prime number
    
    -q: which is a large prime number. 
    
    -e: An exponent, which is small, odd and coprime (1<e<(p-1)*(q-1)).
    Steps: 1. N = p * q. This is half public key 2. e = 1 <e <(p-1)*(q-1). It could be 3. This is other half of public key 3. d (mod inverse) = (d * e) % N = 1. The d is the private key. 4. The receiver will distribute, #1 and #2 and keep 3 secret.
    Ex: Ram will select p and q to start with. p = 11 q = 17 N = p * q = 11 * 17 = 187. e = 1 < e < (11-1) * (17-1) = 170 = 3 d = 321 = 1(160) = 107 Public Key = (3, 187) - This is shared with Shyam. Private Key = (107,187) - This is stored secretly by Ram.

Diffie and Hellman Key exchange

    

Scenario:

Create a shared encryption key for parties to communicate securely.

Solution:

A Symmetric encryption uses a single key shared between two entities while asymmetric encryption uses a pair of public key and a private key to encrypt and decrypt messages when communicating.

Diffie and Hellman [D & H] - Uses an asymmetric algorithm used to establish a shared secret for a symmetric key algorithm.

Entropy  - We need to make the key as big a possible, so it is near impossible to break, like 2048 bits or 4096 bits. 


Example: If Ram and Shyam wants to share messages securely they would use below algorithm by D & H to encrypt the keys
  1. Generate Keys

  2. --It uses 2 numbers. 
    
    -g: which is general number, which typically would be small
    
    -n: Large number, either 2048 or 4096 bits. 
    
    Each entity needs to have a secret. So for 2 parties, they would have secret each.
    
    g^secret MOD(n)
    
    Ex: Ram and Shyam in our example has to choose g & n. Lets say they agree upon:
    
    g = 5
    n = 11
    
    Then they select secret for themselves. Ram picks x = 2 and Shyam x = 4.
    
    Now;
    
    Ram's public key = 5^2 MOD(11) = 3
    
    Shyam's public key = 5^4 MOD(11) = 9
    
    Time for key exchange
    
    Ram => Shyam = Key: 3
    
    Shyam => ram = Key: 9
    
    As MODis one way function. So for example if you know that a square function 
    has output 9, then you can figure out the input would be 3. But if any one 
    gets hold of Shyam's key and they know its result of MOD function, 
    but they can figure out its the result of 5^4 MOD(11) as 9 could be MOD of 13MOD4 
    or 21MOD12 and so on. Here offcourse due to small numbers hacker can run a 
    loop to brute force figure i tout but with 4096 bits number it would 
    take may be millions of years ;)
    
    Now both side use one another public key and their secret (private key)
     to come up with shared key. So:
    
    Ram => 9 (Shyam's public key)^2 MOD 11 = 4
    
    Shyam => 3 (Ram's public key)^4 = 4
    
    Both come to same shared key that is 4. Now each one of them will use 4 to encrypt a message to send to one another.

  3. JavaScript
  4. const g = 5;
    const n = 11;
    
    const ramSecret = 2;
    const shyamSecret = 4;
    
    const publickey = (secret)=> Math.pow(g,secret) % n;
    
    const ramPublicKey = publickey(ramSecret);
    const shyamPublicKey = publickey(shyamSecret);
    
    console.log("Ram's Key",ramPublicKey);
    console.log("Shyam's Key",shyamPublicKey);
    
    const sharedKey = (publickey,secretKey) => {
        return Math.pow(publickey,secretKey) % n
    }
    
    const ramSharedKey = sharedKey(shyamPublicKey,ramSecret);
    const shyamSharedKey = sharedKey(ramPublicKey,shyamSecret);
    
    console.log("Ram's Shared Key",ramSharedKey);
    console.log("Shyam's Shared Key",shyamSharedKey);

Design Pattern - Structural - Composite

   

Scenario:

Create a Product which could be individually sold or as a bundle.

Solution:

This pattern composes the objects into tree structures to represent part-whole hierarchies.

Example: Product which can be created singularly or as a composite (bundle).
  1. Product

  2.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    using System.Text;
    
    namespace TestProject
    {
        public abstract class Product
        {
            public string Name { get; set; }
            public int Price { get; set; }
    
            protected Product(string name, int price)
            {
                Name = name;
                Price = price;
            }
    
            public abstract void Add(Product product);
            public abstract void Delete(Product product);
            public abstract string GetProductDetails();
        }
    
        public class BundleSku : Product
        {
            private readonly List<Product> _skus = new();
    
            public BundleSku(string name, int price) : base(name, price)
            {
            }
    
            public override void Add(Product product)
            {
                _skus.Add(product);
            }
    
            public override void Delete(Product product)
            {
                _skus.Remove(product);
            }
    
            public override string GetProductDetails()
            {
                var details = new StringBuilder();
                for (var i = 0; i < _skus.Count; i++)
                {
                    details.Append(_skus[i].GetProductDetails());
    
                    details.Append(_skus.Count != i + 1 ? " and " : ".");
    
                    details.Append("\n");
                }
                return details.ToString();
            }
        }
    
        public class Sku : Product
        {
            public Sku(string name, int price) : base(name, price)
            {
            }
    
            public override void Add(Product product)
            {
                throw new NotImplementedException();
            }
    
            public override void Delete(Product product)
            {
                throw new NotImplementedException();
            }
    
            public override string GetProductDetails()
            {
                return $"{Name} @ ${Price}";
            }
        }
    }

  3. Create skus and then add them to bundle.
  4.  

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    var sku1 = new Sku("IPhone 14", 10000);
    var sku2 = new Sku("Screen Guard", 200);
    var sku3 = new Sku("Case", 1000);
    var bundleSku = new BundleSku("Iphone 14 bundle", 11200);
    
    bundleSku.Add(sku1);
    bundleSku.Add(sku2);
    bundleSku.Add(sku3);
    
    Console.WriteLine($"{bundleSku.Name} comes with: " +
                      $"{bundleSku.GetProductDetails()}The total price of bundle is: ${bundleSku.Price}.");
    Console.ReadLine();

Design Pattern - Structural - Facade

   

Scenario:

Create a e-Retail Checkout.

Solution:

This pattern hides the complexities of the larger system and provides a simpler interface to the client. 

Example: The Checkout, involves multiple steps to move the Order ahead, but through Facade we expose only Checkout.TryProcess method to the client and hiding the complexity.
  1. Checkout 

  2. 1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    namespace TestProject
    {
        public class Shopper
        {
            public int Id { get; set; }
            public string? Name { get; set; }
            public string? Address { get; set; }
        }
    
        public class OrderService
        {
            public bool TryCreateOrder(string order, out Guid? orderId)
            {
                orderId = Guid.NewGuid();
                return true;
            }
        }
    
        public class ValidationService
        {
            public bool IsAddressValid(string? address)
            {
                return true;
            }
        }
    
        public class FraudService
        {
            public bool IsShopperLegit(Shopper shopper)
            {
                return true;
            }
        }
    
        public class Checkout
        {
            public bool TryProcess(string order, Shopper shopper, out Guid? orderId)
            {
                var orderService = new OrderService();
                var fraudService = new FraudService();
                var validationService = new ValidationService();
                if (validationService.IsAddressValid(shopper.Address))
                {
                    Console.WriteLine("Shopper address is valid");
    
                    if (fraudService.IsShopperLegit(shopper))
                    {
                        Console.WriteLine("Shopper passed Fraud");
                    }
    
                    if (orderService.TryCreateOrder(order, out orderId))
                    {
                        Console.WriteLine($"Order created. Order ID: {orderId}");
    
                        return true;
                    }
                }
    
                orderId = null;
                return false;
            }
        }
    }

  3. Call Checkout/TrProcess which internally does validation, fraud check and order creation and if all successful returns the orderId.

  4. var checkout = new Checkout();
    Console.WriteLine(checkout.TryProcess("order details", new Shopper
    {
        Address = "Test",
        Name = "Ram"
    }, out var orderId)
        ? $"Order Created Successfully"
        : $"Order Creation Failed");
    Console.ReadLine();
    

Design Pattern - Structural - Adapter

   

Scenario:

Create a converter adapter to transform data format between two different interfaces.

Solution:

This pattern allows interface of an existing class to be used by other interface.

Example: Another api returns xml data and our processor supports json or any other format, then create and adapter which would do the transformation from the incoming to what we expect.
  1. Converter

  2.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    using System.Xml.Linq;
    using System.Xml.Serialization;
    using Newtonsoft.Json;
    
    namespace TestProject
    {
        public interface IConverter<T>
        {
            T XmlToJson(string data);
        }
    
        public interface ICustomerApi
        {
            string GetCustomer(int customerId);
        }
    
        public class Converter<T> : IConverter<T> where T : class
        {
            public T XmlToJson(string data)
            {
                var doc = XDocument.Parse(data);
                doc.Descendants().Attributes().Where(x=> x.IsNamespaceDeclaration).Remove();
                dynamic json = JsonConvert.SerializeXNode(doc);
                return JsonConvert.DeserializeObject<T>(json);
            }
        }
    
        public class CustomerResult
        {
            public Customer? Customer { get; set; }
        }
    
        public class Customer
        {
            public int Id { get; set; }
            public string? Name { get; set; }
        }
        public class CustomerApi : ICustomerApi
        {
            public string GetCustomer(int customerId)
            {
                var customer = new Customer();
    
                if (customerId == 1)
                {
                    customer = new Customer
                    {
                        Id = customerId,
                        Name = "Ram"
                    };
                }
                else if (customerId == 2)
                {
                    customer = new Customer
                    {
                        Id = customerId,
                        Name = "Shyam"
                    };
                }
    
                //return JsonConvert.SerializeObject(customer);
    
                var serializer = new XmlSerializer(typeof(Customer));
    
                using var writer = new StringWriter();
    
                serializer.Serialize(writer, customer);
    
                return writer.ToString();
            }
        }
    }

  3. Get data from CustomerApi and transform it to Json through adapter.
  4.  
    1
    2
    3
    4
    5
    6
    7
    var customer = new CustomerApi();
    
    var data = JsonConvert.DeserializeObject<Customer>(customer.GetCustomer(1));
    
    Console.WriteLine($"Customer Id: {data.Id}, Name: {data.Name} ");
    
    Console.ReadLine();

Design Pattern - Structural - AbstractFactory

  

Scenario:

Create a Student factory to get student object by the school and department.

Solution:

This pattern provides to encapsulate individual factories.

Example: StudentFactory to create students based on the school and the department they study in
  1. StudentFactory 

  2. 1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    namespace TestProject
    {
        public interface IStudent
        {
            List<string> Courses();
        }
    
        public class UclaComputerScienceSchool : IStudent
        {
            public List<string> Courses()
            {
                return new List<string>() { "C#" };
            }
        }
    
        public class UclaMechanicalEngineeringSchool : IStudent
        {
            public List<string> Courses()
            {
                return new List<string>() { "Mechanics" };
            }
        }
    
        public class BoothFinanceSchool : IStudent
        {
            public List<string> Courses()
            {
                return new List<string>() { "StockMarkets" };
            }
        }
        public class BoothPolicySchool : IStudent
        {
            public List<string> Courses()
            {
                return new List<string>() { "Governance" };
            }
        }
    
        public abstract class StudentFactory
        {
            public abstract IStudent? GetStudent(string department);
    
            public static StudentFactory CreateStudentFactory(string school)
            {
                if (school.Equals("ucla", StringComparison.InvariantCultureIgnoreCase))
                {
                    return new UclaStudentFactory();
                }
                else
                {
                    return new BoothStudentFactory();
                }
            }
        }
    
        public class BoothStudentFactory : StudentFactory
        {
            public override IStudent? GetStudent(string department)
            {
                if (department.Equals("finance", StringComparison.InvariantCultureIgnoreCase))
                {
                    return new BoothFinanceSchool();
                }
                else if (department.Equals("policy"))
                {
                    return new BoothPolicySchool();
                }
    
                return null;
            }
        }
    
        public class UclaStudentFactory : StudentFactory
        {
            public override IStudent? GetStudent(string department)
            {
                if (department.Equals("computerscience", StringComparison.InvariantCultureIgnoreCase))
                {
                    return new UclaComputerScienceSchool();
                }
                else if (department.Equals("mechanical"))
                {
                    return new UclaMechanicalEngineeringSchool();
                }
    
                return null;
            }
        }
    }

  3. Create students and get courses they study in based on school and department they have picked.
  4.  
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    StudentFactory studentFactory = null;
    IStudent? student = null;
    
    studentFactory = StudentFactory.CreateStudentFactory("ucla");
    
    Console.WriteLine($"Student's School is {studentFactory.GetType().Name}");
    
    student = studentFactory.GetStudent("computerscience");
    
    Console.WriteLine($"Student's Stream is {student.GetType().Name}");
    
    var courses = student.Courses();
    
    foreach (var course in courses)
    {
        Console.WriteLine($"Courses Taken:{course}");
    }
    
    Console.ReadLine();

Design Pattern - Creational - Factory

 

Scenario:

Create a Redis Cache factory.

Solution:

Creational Pattern for the creation of objects. So the Factory creates the objects required so its delegating the "new" to factory from the caller.

Example: Redis Cache factory which creates the objects of RedisCacheClient based on configurations
  1. RedisCacheFactory and the RedisCache

  2.  
    1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    namespace TestProject
    {
        public interface IRedisCache
        {
            void Push(Dictionary<string, string> data);
        }
    
        public class RedisCache : IRedisCache
        {
            public void Push(Dictionary<string, string> data)
            {
                // Push to Redis
            }
        }
    
        public class RedisCacheFactory
        {
            private static readonly Dictionary<Tuple<Type, string>, IRedisCache?> _clientCache;
            public RedisCacheFactory()
            {
    
            }
            public static IRedisCache? GetCacheClient(Type dataType, string serviceName)
            {
                return InternalGetCacheClient(dataType, serviceName);
            }
    
            private static IRedisCache? InternalGetCacheClient(Type dataType, string serviceName)
            {
                var cacheKey = new Tuple<Type, string>(dataType, serviceName);
    
                if (_clientCache.TryGetValue(cacheKey, out var client))
                {
                    return client;
                }
    
                var type = (typeof(RedisCache)).MakeGenericType(dataType);
                client =
                    (IRedisCache)
                    Activator.CreateInstance(type, serviceName)!;
    
                _clientCache[cacheKey] = client;
    
                return client;
            }
        }
    }

  3. Push the Log to Redis through the client created & returned by the factory

  4.  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    namespace TestProject
    {
        public class Caller
        {
            public void PushData(Dictionary<string, string> data)
            {
                var type = Type.GetType("TestProject.ApiLog");
                var redisClient = RedisCacheFactory.GetCacheClient(type, "api");
    
                var dictionary = new Dictionary<string, string>();
                dictionary.Add("logapi", "{Request}");
                redisClient.Push(dictionary);
            }
        }
    }

Move Github Sub Repository back to main repo

 -- delete .gitmodules git rm --cached MyProject/Core git commit -m 'Remove myproject_core submodule' rm -rf MyProject/Core git remo...