-
Notifications
You must be signed in to change notification settings - Fork 80
Expand file tree
/
Copy pathProgram.cs
More file actions
104 lines (80 loc) · 4.1 KB
/
Program.cs
File metadata and controls
104 lines (80 loc) · 4.1 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
namespace AesGcmEncryption
{
public class Program
{
public static void Main()
{
var plaintextBytes = new byte[8192];
RandomNumberGenerator.Fill(plaintextBytes);
var plaintext = Convert.ToBase64String(plaintextBytes);
var key = new byte[32];
RandomNumberGenerator.Fill(key);
var (ciphertext, nonce, tag) = EncryptWithNet(plaintext, key);
// var (ciphertext, nonce, tag) = EncryptWithBouncyCastle(plaintext, key);
var decryptedPlaintext = DecryptWithNet(ciphertext, nonce, tag, key);
// var decryptedPlaintext = DecryptWithBouncyCastle(ciphertext, nonce, tag, key);
if (decryptedPlaintext.Equals(plaintext)) Console.WriteLine("Decryption succesful!");
else Console.WriteLine("Error!");
}
private static (byte[] ciphertext, byte[] nonce, byte[] tag) EncryptWithNet(string plaintext, byte[] key)
{
using (var aes = new AesGcm(key))
{
var nonce = new byte[AesGcm.NonceByteSizes.MaxSize];
RandomNumberGenerator.Fill(nonce);
var tag = new byte[AesGcm.TagByteSizes.MaxSize];
var plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
var ciphertext = new byte[plaintextBytes.Length];
aes.Encrypt(nonce, plaintextBytes, ciphertext, tag);
return (ciphertext, nonce, tag);
}
}
private static string DecryptWithNet(byte[] ciphertext, byte[] nonce, byte[] tag, byte[] key)
{
using (var aes = new AesGcm(key))
{
var plaintextBytes = new byte[ciphertext.Length];
aes.Decrypt(nonce, ciphertext, tag, plaintextBytes);
return Encoding.UTF8.GetString(plaintextBytes);
}
}
private static (byte[] ciphertext, byte[] nonce, byte[] tag) EncryptWithBouncyCastle(string plaintext, byte[] key)
{
const int nonceLength = 12; // in bytes
const int tagLength = 16; // in bytes
var nonce = new byte[nonceLength];
RandomNumberGenerator.Fill(nonce);
var plaintextBytes = Encoding.UTF8.GetBytes(plaintext);
var bouncyCastleCiphertext = new byte[plaintextBytes.Length + tagLength];
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), tagLength * 8, nonce);
cipher.Init(true, parameters);
var offset = cipher.ProcessBytes(plaintextBytes, 0, plaintextBytes.Length, bouncyCastleCiphertext, 0);
cipher.DoFinal(bouncyCastleCiphertext, offset);
// Bouncy Castle includes the authentication tag in the ciphertext
var ciphertext = new byte[plaintextBytes.Length];
var tag = new byte[tagLength];
Buffer.BlockCopy(bouncyCastleCiphertext, 0, ciphertext, 0, plaintextBytes.Length);
Buffer.BlockCopy(bouncyCastleCiphertext, plaintextBytes.Length, tag, 0, tagLength);
return (ciphertext, nonce, tag);
}
private static string DecryptWithBouncyCastle(byte[] ciphertext, byte[] nonce, byte[] tag, byte[] key)
{
var plaintextBytes = new byte[ciphertext.Length];
var cipher = new GcmBlockCipher(new AesEngine());
var parameters = new AeadParameters(new KeyParameter(key), tag.Length * 8, nonce);
cipher.Init(false, parameters);
var bouncyCastleCiphertext = ciphertext.Concat(tag).ToArray();
var offset = cipher.ProcessBytes(bouncyCastleCiphertext, 0, bouncyCastleCiphertext.Length, plaintextBytes, 0);
cipher.DoFinal(plaintextBytes, offset);
return Encoding.UTF8.GetString(plaintextBytes);
}
}
}