├── docs ├── styles │ ├── main.css │ ├── main.js │ ├── search-worker.js │ └── docfx.css ├── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.ttf │ ├── glyphicons-halflings-regular.woff │ └── glyphicons-halflings-regular.woff2 ├── logo.svg ├── search-stopwords.json ├── manifest.json ├── api │ └── Cryptography.html ├── xrefmap.yml └── index.html ├── toc.yml ├── src ├── Cryptography.snk ├── Cryptography.Benchmarks │ ├── Program.cs │ ├── Cryptography.Benchmarks.csproj │ ├── AeadBenchmark.cs │ └── Libsodium.cs ├── Cryptography.Samples │ ├── Cryptography.Samples.csproj │ └── Program.cs ├── Cryptography.Tests │ ├── Hex.cs │ ├── Vector.cs │ ├── Cryptography.Tests.csproj │ ├── Vectors │ │ ├── counter-wrap.json │ │ ├── aes-128-gcm-siv.json │ │ └── aes-256-gcm-siv.json │ └── AesGcmSivTest.cs ├── Cryptography │ ├── Cryptography.csproj │ ├── AesGcmSiv.Encrypt.cs │ ├── AesGcmSiv.Polyval.cs │ └── AesGcmSiv.Decrypt.cs └── Cryptography.sln ├── .gitignore ├── azure-pipelines.yml ├── docfx.json ├── LICENSE ├── README.md └── index.md /docs/styles/main.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /toc.yml: -------------------------------------------------------------------------------- 1 | - name: API Reference 2 | href: api/ 3 | -------------------------------------------------------------------------------- /docs/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/docs/favicon.ico -------------------------------------------------------------------------------- /src/Cryptography.snk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/src/Cryptography.snk -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/docs/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/docs/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/docs/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /docs/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/HEAD/docs/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /docs/styles/main.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information. 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Visual Studio Code 2 | .vscode 3 | 4 | # Build results 5 | [Bb]in/ 6 | [Oo]bj/ 7 | 8 | # BenchmarkDotNet 9 | **/BenchmarkDotNet.Artifacts/* 10 | 11 | # DocFX 12 | /api 13 | -------------------------------------------------------------------------------- /src/Cryptography.Benchmarks/Program.cs: -------------------------------------------------------------------------------- 1 | using BenchmarkDotNet.Running; 2 | 3 | namespace Cryptography.Benchmarks 4 | { 5 | public class Program 6 | { 7 | public static void Main(string[] args) 8 | { 9 | BenchmarkRunner.Run(); 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/Cryptography.Samples/Cryptography.Samples.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Hex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Cryptography.Tests 4 | { 5 | internal static class Hex 6 | { 7 | public static string Encode(byte[] raw) 8 | { 9 | return BitConverter.ToString(raw).Replace("-", String.Empty).ToLowerInvariant(); 10 | } 11 | 12 | public static byte[] Decode(string hex) 13 | { 14 | byte[] raw = new byte[hex.Length / 2]; 15 | 16 | for (int i = 0; i < raw.Length; ++i) 17 | { 18 | raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16); 19 | } 20 | 21 | return raw; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Vector.cs: -------------------------------------------------------------------------------- 1 | namespace Cryptography.Tests 2 | { 3 | internal class Vector 4 | { 5 | public byte[] Plaintext; 6 | public byte[] Aad; 7 | public byte[] Key; 8 | public byte[] Nonce; 9 | public byte[] RecordAuthenticationKey; 10 | public byte[] RecordEncryptionKey; 11 | public byte[] PolyvalInput; 12 | public byte[] PolyvalResult; 13 | public byte[] PolyvalResultXorNonce; 14 | public byte[] PolyvalResultXorNonceMasked; 15 | public byte[] Tag; 16 | public byte[] InitialCounter; 17 | public byte[] Result; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | pool: 2 | vmImage: 'Ubuntu 16.04' 3 | 4 | variables: 5 | buildConfiguration: 'release' 6 | 7 | trigger: 8 | branches: 9 | include: 10 | - master 11 | 12 | steps: 13 | - task: DotNetCoreInstaller@0 14 | inputs: 15 | version: '3.0.100-alpha1-009640' 16 | 17 | - script: dotnet build --configuration $(buildConfiguration) src/Cryptography.sln 18 | displayName: 'dotnet build $(buildConfiguration)' 19 | 20 | - task: DotNetCoreCLI@2 21 | inputs: 22 | command: test 23 | projects: '**/*Tests/*.csproj' 24 | arguments: '--configuration $(buildConfiguration)' 25 | -------------------------------------------------------------------------------- /src/Cryptography.Benchmarks/Cryptography.Benchmarks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | latest 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /docfx.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": [ 3 | { 4 | "src": [ 5 | { 6 | "files": [ 7 | "src/Cryptography/**.csproj" 8 | ] 9 | } 10 | ], 11 | "dest": "api" 12 | } 13 | ], 14 | "build": { 15 | "content": [ 16 | { 17 | "files": [ 18 | "api/**.yml" 19 | ] 20 | }, 21 | { 22 | "files": [ 23 | "index.md", 24 | "toc.yml" 25 | ] 26 | } 27 | ], 28 | "resource": [ 29 | { 30 | "files": [ 31 | "aes-gcm-siv.svg" 32 | ] 33 | } 34 | ], 35 | "dest": "docs", 36 | "template": [ 37 | "statictoc" 38 | ], 39 | "markdownEngineName": "markdig" 40 | } 41 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Nemanja Mijailovic 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Cryptography.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | true 6 | false 7 | latest 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /docs/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | Created by Docfx 9 | 10 | 12 | 15 | 21 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/Cryptography.Samples/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace Cryptography.Samples 6 | { 7 | public class Program 8 | { 9 | public static void Main(string[] args) 10 | { 11 | // Plaintext to encrypt. 12 | var plaintext = "I'm cooking MC's like a pound of bacon"; 13 | 14 | // Create a 32-byte key. 15 | var key = new byte[32]; 16 | RandomNumberGenerator.Fill(key); 17 | 18 | // Create a 12-byte nonce. 19 | var nonce = new byte[12]; 20 | RandomNumberGenerator.Fill(nonce); 21 | 22 | // Create a new AesGcmSiv instance. It implements the IDisposable 23 | // interface, so it's best to create it inside using statement. 24 | using (var siv = new AesGcmSiv(key)) 25 | { 26 | // If the message is string, convert it to byte array first. 27 | var bytes = Encoding.UTF8.GetBytes(plaintext); 28 | 29 | // Encrypt the message. 30 | var ciphertext = new byte[bytes.Length]; 31 | var tag = new byte[16]; 32 | siv.Encrypt(nonce, bytes, ciphertext, tag); 33 | 34 | // To decrypt the message, call the Decrypt method with the 35 | // ciphertext and the same nonce that you generated previously. 36 | siv.Decrypt(nonce, ciphertext, tag, bytes); 37 | 38 | // If the message was originally string, 39 | // convert if from byte array to string. 40 | plaintext = Encoding.UTF8.GetString(bytes); 41 | 42 | // Print the decrypted message to the standard output. 43 | Console.WriteLine(plaintext); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/search-stopwords.json: -------------------------------------------------------------------------------- 1 | [ 2 | "a", 3 | "able", 4 | "about", 5 | "across", 6 | "after", 7 | "all", 8 | "almost", 9 | "also", 10 | "am", 11 | "among", 12 | "an", 13 | "and", 14 | "any", 15 | "are", 16 | "as", 17 | "at", 18 | "be", 19 | "because", 20 | "been", 21 | "but", 22 | "by", 23 | "can", 24 | "cannot", 25 | "could", 26 | "dear", 27 | "did", 28 | "do", 29 | "does", 30 | "either", 31 | "else", 32 | "ever", 33 | "every", 34 | "for", 35 | "from", 36 | "get", 37 | "got", 38 | "had", 39 | "has", 40 | "have", 41 | "he", 42 | "her", 43 | "hers", 44 | "him", 45 | "his", 46 | "how", 47 | "however", 48 | "i", 49 | "if", 50 | "in", 51 | "into", 52 | "is", 53 | "it", 54 | "its", 55 | "just", 56 | "least", 57 | "let", 58 | "like", 59 | "likely", 60 | "may", 61 | "me", 62 | "might", 63 | "most", 64 | "must", 65 | "my", 66 | "neither", 67 | "no", 68 | "nor", 69 | "not", 70 | "of", 71 | "off", 72 | "often", 73 | "on", 74 | "only", 75 | "or", 76 | "other", 77 | "our", 78 | "own", 79 | "rather", 80 | "said", 81 | "say", 82 | "says", 83 | "she", 84 | "should", 85 | "since", 86 | "so", 87 | "some", 88 | "than", 89 | "that", 90 | "the", 91 | "their", 92 | "them", 93 | "then", 94 | "there", 95 | "these", 96 | "they", 97 | "this", 98 | "tis", 99 | "to", 100 | "too", 101 | "twas", 102 | "us", 103 | "wants", 104 | "was", 105 | "we", 106 | "were", 107 | "what", 108 | "when", 109 | "where", 110 | "which", 111 | "while", 112 | "who", 113 | "whom", 114 | "why", 115 | "will", 116 | "with", 117 | "would", 118 | "yet", 119 | "you", 120 | "your" 121 | ] 122 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Vectors/counter-wrap.json: -------------------------------------------------------------------------------- 1 | { 2 | "vectors": [ 3 | { 4 | "plaintext": "000000000000000000000000000000004db923dc793ee6497c76dcc03a98e108", 5 | "aad": "", 6 | "key": "0000000000000000000000000000000000000000000000000000000000000000", 7 | "nonce": "000000000000000000000000", 8 | "record_authentication_key": "dc95c078a24089895275f3d86b4fb868", 9 | "record_encryption_key": "779b38d15bffb63d39d6e9ae76a9b2f375d11b0e3a68c422845c7d4690fa594f", 10 | "polyval_input": "000000000000000000000000000000004db923dc793ee6497c76dcc03a98e10800000000000000000001000000000000", 11 | "polyval_result": "7367cdb411b730128dd56e8edc0eff56", 12 | "polyval_result_xor_nonce": "7367cdb411b730128dd56e8edc0eff56", 13 | "polyval_result_xor_nonce_masked": "7367cdb411b730128dd56e8edc0eff56", 14 | "tag": "ffffffff000000000000000000000000", 15 | "initial_counter": "ffffffff000000000000000000000080", 16 | "result": "f3f80f2cf0cb2dd9c5984fcda908456cc537703b5ba70324a6793a7bf218d3eaffffffff000000000000000000000000" 17 | }, 18 | { 19 | "plaintext": "eb3640277c7ffd1303c7a542d02d3e4c0000000000000000", 20 | "aad": "", 21 | "key": "0000000000000000000000000000000000000000000000000000000000000000", 22 | "nonce": "000000000000000000000000", 23 | "record_authentication_key": "dc95c078a24089895275f3d86b4fb868", 24 | "record_encryption_key": "779b38d15bffb63d39d6e9ae76a9b2f375d11b0e3a68c422845c7d4690fa594f", 25 | "polyval_input": "eb3640277c7ffd1303c7a542d02d3e4c000000000000000000000000000000000000000000000000c000000000000000", 26 | "polyval_result": "7367cdb411b730128dd56e8edc0eff56", 27 | "polyval_result_xor_nonce": "7367cdb411b730128dd56e8edc0eff56", 28 | "polyval_result_xor_nonce_masked": "7367cdb411b730128dd56e8edc0eff56", 29 | "tag": "ffffffff000000000000000000000000", 30 | "initial_counter": "ffffffff000000000000000000000080", 31 | "result": "18ce4f0b8cb4d0cac65fea8f79257b20888e53e72299e56dffffffff000000000000000000000000" 32 | } 33 | ] 34 | } -------------------------------------------------------------------------------- /src/Cryptography/Cryptography.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.0 5 | true 6 | latest 7 | true 8 | AES-GCM-SIV 9 | AES-GCM-SIV 10 | 0.3.2 11 | 0.3.2.0 12 | Nemanja Mijailovic 13 | https://github.com/Metalnem/aes-gcm-siv.git 14 | git 15 | true 16 | true 17 | $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb 18 | https://raw.githubusercontent.com/Metalnem/aes-gcm-siv/master/LICENSE 19 | .NET Core 3.0 implementation of AES-GCM-SIV nonce misuse-resistant authenticated encryption. Fastest available authenticated encryption library for .NET, with the encryption/decryption rate of roughly 8 Gbps/core. Implemented using .NET Core 3.0 platform intrinsics. 20 | false 21 | Copyright © 2018, Nemanja Mijailovic 22 | crypto cryptography security encryption aes aes-gcm-siv aead simd intrinsics 23 | 24 | 25 | 26 | true 27 | ..\Cryptography.snk 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/Cryptography.Benchmarks/AeadBenchmark.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Cryptography; 2 | using BenchmarkDotNet.Attributes; 3 | using BenchmarkDotNet.Configs; 4 | 5 | namespace Cryptography.Benchmarks 6 | { 7 | [CategoriesColumn] 8 | [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] 9 | [MarkdownExporter] 10 | public class AeadBenchmark 11 | { 12 | private byte[] key; 13 | private byte[] nonce; 14 | private byte[] plaintext; 15 | private byte[] ciphertext; 16 | private byte[] tag; 17 | private byte[] empty; 18 | 19 | private byte[] ciphertextGcm; 20 | private byte[] ciphertextSiv; 21 | private byte[] tagGcm; 22 | private byte[] tagSiv; 23 | 24 | private AesGcm gcm; 25 | private AesGcmSiv siv; 26 | 27 | [Params(128, 1024, 4096, 8192)] 28 | public int Size { get; set; } 29 | 30 | [GlobalSetup] 31 | public void GlobalSetup() 32 | { 33 | key = new byte[32]; 34 | nonce = new byte[12]; 35 | plaintext = new byte[Size]; 36 | ciphertext = new byte[Size]; 37 | tag = new byte[16]; 38 | empty = new byte[0]; 39 | 40 | ciphertextGcm = new byte[Size]; 41 | ciphertextSiv = new byte[Size]; 42 | tagGcm = new byte[16]; 43 | tagSiv = new byte[16]; 44 | 45 | gcm = new AesGcm(key); 46 | siv = new AesGcmSiv(key); 47 | 48 | gcm.Encrypt(nonce, plaintext, ciphertextGcm, tagGcm); 49 | siv.Encrypt(nonce, plaintext, ciphertextSiv, tagSiv); 50 | } 51 | 52 | [BenchmarkCategory("Encryption"), Benchmark(Baseline = true, Description = "AES-GCM")] 53 | public void BenchmarkAesGcmNativeEncryption() => gcm.Encrypt(nonce, plaintext, ciphertext, tag); 54 | 55 | [BenchmarkCategory("Encryption"), Benchmark(Description = "AES-GCM-SIV")] 56 | public void BenchmarkAesGcmSivEncryption() => siv.Encrypt(nonce, plaintext, ciphertext, tag); 57 | 58 | [BenchmarkCategory("Decryption"), Benchmark(Baseline = true, Description = "AES-GCM")] 59 | public void BenchmarkAesGcmNativeDecryption() => gcm.Decrypt(nonce, ciphertextGcm, tagGcm, plaintext); 60 | 61 | [BenchmarkCategory("Decryption"), Benchmark(Description = "AES-GCM-SIV")] 62 | public void BenchmarkAesGcmSivDecryption() => siv.Decrypt(nonce, ciphertextSiv, tagSiv, plaintext); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /docs/styles/search-worker.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | importScripts('lunr.min.js'); 3 | 4 | var lunrIndex; 5 | 6 | var stopWords = null; 7 | var searchData = {}; 8 | 9 | lunr.tokenizer.seperator = /[\s\-\.]+/; 10 | 11 | var stopWordsRequest = new XMLHttpRequest(); 12 | stopWordsRequest.open('GET', '../search-stopwords.json'); 13 | stopWordsRequest.onload = function () { 14 | if (this.status != 200) { 15 | return; 16 | } 17 | stopWords = JSON.parse(this.responseText); 18 | buildIndex(); 19 | } 20 | stopWordsRequest.send(); 21 | 22 | var searchDataRequest = new XMLHttpRequest(); 23 | 24 | searchDataRequest.open('GET', '../index.json'); 25 | searchDataRequest.onload = function () { 26 | if (this.status != 200) { 27 | return; 28 | } 29 | searchData = JSON.parse(this.responseText); 30 | 31 | buildIndex(); 32 | 33 | postMessage({ e: 'index-ready' }); 34 | } 35 | searchDataRequest.send(); 36 | 37 | onmessage = function (oEvent) { 38 | var q = oEvent.data.q; 39 | var hits = lunrIndex.search(q); 40 | var results = []; 41 | hits.forEach(function (hit) { 42 | var item = searchData[hit.ref]; 43 | results.push({ 'href': item.href, 'title': item.title, 'keywords': item.keywords }); 44 | }); 45 | postMessage({ e: 'query-ready', q: q, d: results }); 46 | } 47 | 48 | function buildIndex() { 49 | if (stopWords !== null && !isEmpty(searchData)) { 50 | lunrIndex = lunr(function () { 51 | this.pipeline.remove(lunr.stopWordFilter); 52 | this.ref('href'); 53 | this.field('title', { boost: 50 }); 54 | this.field('keywords', { boost: 20 }); 55 | 56 | for (var prop in searchData) { 57 | if (searchData.hasOwnProperty(prop)) { 58 | this.add(searchData[prop]); 59 | } 60 | } 61 | 62 | var docfxStopWordFilter = lunr.generateStopWordFilter(stopWords); 63 | lunr.Pipeline.registerFunction(docfxStopWordFilter, 'docfxStopWordFilter'); 64 | this.pipeline.add(docfxStopWordFilter); 65 | this.searchPipeline.add(docfxStopWordFilter); 66 | }); 67 | } 68 | } 69 | 70 | function isEmpty(obj) { 71 | if(!obj) return true; 72 | 73 | for (var prop in obj) { 74 | if (obj.hasOwnProperty(prop)) 75 | return false; 76 | } 77 | 78 | return true; 79 | } 80 | })(); 81 | -------------------------------------------------------------------------------- /docs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "homepages": [], 3 | "source_base_path": "/Users/Metalnem/Projects/aes-gcm-siv", 4 | "xrefmap": "xrefmap.yml", 5 | "files": [ 6 | { 7 | "type": "Resource", 8 | "source_relative_path": "aes-gcm-siv.svg", 9 | "output": { 10 | "resource": { 11 | "relative_path": "aes-gcm-siv.svg" 12 | } 13 | }, 14 | "is_incremental": false, 15 | "version": "" 16 | }, 17 | { 18 | "type": "ManagedReference", 19 | "source_relative_path": "api/Cryptography.AesGcmSiv.yml", 20 | "output": { 21 | ".html": { 22 | "relative_path": "api/Cryptography.AesGcmSiv.html", 23 | "hash": "sSFyZYi1ZmLcj1Q6X0TaIA==" 24 | } 25 | }, 26 | "is_incremental": true, 27 | "version": "" 28 | }, 29 | { 30 | "type": "ManagedReference", 31 | "source_relative_path": "api/Cryptography.yml", 32 | "output": { 33 | ".html": { 34 | "relative_path": "api/Cryptography.html", 35 | "hash": "As9gur98EnzD5kklEA1kfQ==" 36 | } 37 | }, 38 | "is_incremental": true, 39 | "version": "" 40 | }, 41 | { 42 | "type": "Conceptual", 43 | "source_relative_path": "index.md", 44 | "output": { 45 | ".html": { 46 | "relative_path": "index.html", 47 | "hash": "RIB8HjD3OzEIXAOcvfjiPQ==" 48 | } 49 | }, 50 | "is_incremental": false, 51 | "version": "" 52 | } 53 | ], 54 | "incremental_info": [ 55 | { 56 | "status": { 57 | "can_incremental": true, 58 | "incrementalPhase": "build" 59 | }, 60 | "processors": { 61 | "TocDocumentProcessor": { 62 | "can_incremental": false, 63 | "details": "Processor TocDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", 64 | "incrementalPhase": "build" 65 | }, 66 | "ManagedReferenceDocumentProcessor": { 67 | "can_incremental": true, 68 | "incrementalPhase": "build" 69 | }, 70 | "ConceptualDocumentProcessor": { 71 | "can_incremental": true, 72 | "incrementalPhase": "build" 73 | }, 74 | "ResourceDocumentProcessor": { 75 | "can_incremental": false, 76 | "details": "Processor ResourceDocumentProcessor cannot support incremental build because the processor doesn't implement ISupportIncrementalDocumentProcessor interface.", 77 | "incrementalPhase": "build" 78 | } 79 | } 80 | }, 81 | { 82 | "status": { 83 | "can_incremental": true, 84 | "details": "Can support incremental post processing.", 85 | "incrementalPhase": "postProcessing" 86 | }, 87 | "processors": {} 88 | } 89 | ], 90 | "version_info": {}, 91 | "groups": [ 92 | { 93 | "xrefmap": "xrefmap.yml" 94 | } 95 | ] 96 | } -------------------------------------------------------------------------------- /src/Cryptography.Benchmarks/Libsodium.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Security.Cryptography; 4 | 5 | namespace Cryptography.Benchmarks 6 | { 7 | internal static class Libsodium 8 | { 9 | private const string Name = "libsodium"; 10 | 11 | static Libsodium() 12 | { 13 | if (sodium_init() == -1) 14 | { 15 | throw new CryptographicException("Failed to initialize libsodium."); 16 | } 17 | } 18 | 19 | [DllImport(Name, CallingConvention = CallingConvention.Cdecl)] 20 | private static extern int sodium_init(); 21 | 22 | [DllImport(Name, CallingConvention = CallingConvention.Cdecl)] 23 | private static extern int crypto_aead_aes256gcm_encrypt_detached( 24 | ref byte c, 25 | ref byte mac, 26 | out long maclen_p, 27 | ref byte m, 28 | long mlen, 29 | ref byte ad, 30 | long adlen, 31 | IntPtr nsec, 32 | ref byte npub, 33 | ref byte k 34 | ); 35 | 36 | [DllImport(Name, CallingConvention = CallingConvention.Cdecl)] 37 | public static extern int crypto_aead_aes256gcm_decrypt_detached( 38 | ref byte m, 39 | IntPtr nsec, 40 | ref byte c, 41 | long clen, 42 | ref byte mac, 43 | ref byte ad, 44 | long adlen, 45 | ref byte npub, 46 | ref byte k 47 | ); 48 | 49 | public static void Encrypt( 50 | ReadOnlySpan key, 51 | ReadOnlySpan nonce, 52 | ReadOnlySpan plaintext, 53 | Span ciphertext, 54 | Span tag, 55 | ReadOnlySpan associatedData) 56 | { 57 | int result = Libsodium.crypto_aead_aes256gcm_encrypt_detached( 58 | ref MemoryMarshal.GetReference(ciphertext), 59 | ref MemoryMarshal.GetReference(tag), 60 | out long length, 61 | ref MemoryMarshal.GetReference(plaintext), 62 | plaintext.Length, 63 | ref MemoryMarshal.GetReference(associatedData), 64 | associatedData.Length, 65 | IntPtr.Zero, 66 | ref MemoryMarshal.GetReference(nonce), 67 | ref MemoryMarshal.GetReference(key) 68 | ); 69 | 70 | if (result != 0) 71 | { 72 | throw new CryptographicException("Encryption failed."); 73 | } 74 | } 75 | 76 | public static void Decrypt( 77 | ReadOnlySpan key, 78 | ReadOnlySpan nonce, 79 | ReadOnlySpan associatedData, 80 | ReadOnlySpan ciphertext, 81 | ReadOnlySpan tag, 82 | Span plaintext) 83 | { 84 | int result = Libsodium.crypto_aead_aes256gcm_decrypt_detached( 85 | ref MemoryMarshal.GetReference(plaintext), 86 | IntPtr.Zero, 87 | ref MemoryMarshal.GetReference(ciphertext), 88 | ciphertext.Length, 89 | ref MemoryMarshal.GetReference(tag), 90 | ref MemoryMarshal.GetReference(associatedData), 91 | associatedData.Length, 92 | ref MemoryMarshal.GetReference(nonce), 93 | ref MemoryMarshal.GetReference(key) 94 | ); 95 | 96 | if (result != 0) 97 | { 98 | throw new CryptographicException("Decryption failed."); 99 | } 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/Cryptography.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography", "Cryptography\Cryptography.csproj", "{8F38D33E-171D-4978-B18F-E94CDE02E956}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography.Tests", "Cryptography.Tests\Cryptography.Tests.csproj", "{75B856F7-93B5-4DDB-AD27-8D036F4BF80F}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography.Benchmarks", "Cryptography.Benchmarks\Cryptography.Benchmarks.csproj", "{CE440BD7-D818-4283-A251-938BDA748DAA}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Cryptography.Samples", "Cryptography.Samples\Cryptography.Samples.csproj", "{76AC8172-4EFB-485F-B741-0CC093A07004}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Debug|x64 = Debug|x64 18 | Debug|x86 = Debug|x86 19 | Release|Any CPU = Release|Any CPU 20 | Release|x64 = Release|x64 21 | Release|x86 = Release|x86 22 | EndGlobalSection 23 | GlobalSection(SolutionProperties) = preSolution 24 | HideSolutionNode = FALSE 25 | EndGlobalSection 26 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 27 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 28 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|Any CPU.Build.0 = Debug|Any CPU 29 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|x64.ActiveCfg = Debug|Any CPU 30 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|x64.Build.0 = Debug|Any CPU 31 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|x86.ActiveCfg = Debug|Any CPU 32 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Debug|x86.Build.0 = Debug|Any CPU 33 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|Any CPU.ActiveCfg = Release|Any CPU 34 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|Any CPU.Build.0 = Release|Any CPU 35 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|x64.ActiveCfg = Release|Any CPU 36 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|x64.Build.0 = Release|Any CPU 37 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|x86.ActiveCfg = Release|Any CPU 38 | {8F38D33E-171D-4978-B18F-E94CDE02E956}.Release|x86.Build.0 = Release|Any CPU 39 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 40 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|Any CPU.Build.0 = Debug|Any CPU 41 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|x64.ActiveCfg = Debug|Any CPU 42 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|x64.Build.0 = Debug|Any CPU 43 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|x86.ActiveCfg = Debug|Any CPU 44 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Debug|x86.Build.0 = Debug|Any CPU 45 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|Any CPU.ActiveCfg = Release|Any CPU 46 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|Any CPU.Build.0 = Release|Any CPU 47 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|x64.ActiveCfg = Release|Any CPU 48 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|x64.Build.0 = Release|Any CPU 49 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|x86.ActiveCfg = Release|Any CPU 50 | {75B856F7-93B5-4DDB-AD27-8D036F4BF80F}.Release|x86.Build.0 = Release|Any CPU 51 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 52 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|Any CPU.Build.0 = Debug|Any CPU 53 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|x64.ActiveCfg = Debug|Any CPU 54 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|x64.Build.0 = Debug|Any CPU 55 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|x86.ActiveCfg = Debug|Any CPU 56 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Debug|x86.Build.0 = Debug|Any CPU 57 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|Any CPU.ActiveCfg = Release|Any CPU 58 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|Any CPU.Build.0 = Release|Any CPU 59 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|x64.ActiveCfg = Release|Any CPU 60 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|x64.Build.0 = Release|Any CPU 61 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|x86.ActiveCfg = Release|Any CPU 62 | {CE440BD7-D818-4283-A251-938BDA748DAA}.Release|x86.Build.0 = Release|Any CPU 63 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 64 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|Any CPU.Build.0 = Debug|Any CPU 65 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|x64.ActiveCfg = Debug|Any CPU 66 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|x64.Build.0 = Debug|Any CPU 67 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|x86.ActiveCfg = Debug|Any CPU 68 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Debug|x86.Build.0 = Debug|Any CPU 69 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|Any CPU.ActiveCfg = Release|Any CPU 70 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|Any CPU.Build.0 = Release|Any CPU 71 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|x64.ActiveCfg = Release|Any CPU 72 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|x64.Build.0 = Release|Any CPU 73 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|x86.ActiveCfg = Release|Any CPU 74 | {76AC8172-4EFB-485F-B741-0CC093A07004}.Release|x86.Build.0 = Release|Any CPU 75 | EndGlobalSection 76 | EndGlobal 77 | -------------------------------------------------------------------------------- /docs/api/Cryptography.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Namespace Cryptography 9 | 10 | 11 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 |
28 | 29 | 57 | 58 | 65 |
66 | 126 | 127 |
128 |
129 | 138 |
139 |
140 | 141 | 142 | 143 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /docs/xrefmap.yml: -------------------------------------------------------------------------------- 1 | ### YamlMime:XRefMap 2 | sorted: true 3 | references: 4 | - uid: Cryptography 5 | name: Cryptography 6 | href: api/Cryptography.html 7 | commentId: N:Cryptography 8 | fullName: Cryptography 9 | nameWithType: Cryptography 10 | - uid: Cryptography.AesGcmSiv 11 | name: AesGcmSiv 12 | href: api/Cryptography.AesGcmSiv.html 13 | commentId: T:Cryptography.AesGcmSiv 14 | fullName: Cryptography.AesGcmSiv 15 | nameWithType: AesGcmSiv 16 | - uid: Cryptography.AesGcmSiv.#ctor(System.Byte[]) 17 | name: AesGcmSiv(Byte[]) 18 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv__ctor_System_Byte___ 19 | commentId: M:Cryptography.AesGcmSiv.#ctor(System.Byte[]) 20 | name.vb: AesGcmSiv(Byte()) 21 | fullName: Cryptography.AesGcmSiv.AesGcmSiv(System.Byte[]) 22 | fullName.vb: Cryptography.AesGcmSiv.AesGcmSiv(System.Byte()) 23 | nameWithType: AesGcmSiv.AesGcmSiv(Byte[]) 24 | nameWithType.vb: AesGcmSiv.AesGcmSiv(Byte()) 25 | - uid: Cryptography.AesGcmSiv.#ctor(System.ReadOnlySpan{System.Byte}) 26 | name: AesGcmSiv(ReadOnlySpan) 27 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv__ctor_System_ReadOnlySpan_System_Byte__ 28 | commentId: M:Cryptography.AesGcmSiv.#ctor(System.ReadOnlySpan{System.Byte}) 29 | name.vb: AesGcmSiv(ReadOnlySpan(Of Byte)) 30 | fullName: Cryptography.AesGcmSiv.AesGcmSiv(System.ReadOnlySpan) 31 | fullName.vb: Cryptography.AesGcmSiv.AesGcmSiv(System.ReadOnlySpan(Of System.Byte)) 32 | nameWithType: AesGcmSiv.AesGcmSiv(ReadOnlySpan) 33 | nameWithType.vb: AesGcmSiv.AesGcmSiv(ReadOnlySpan(Of Byte)) 34 | - uid: Cryptography.AesGcmSiv.#ctor* 35 | name: AesGcmSiv 36 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv__ctor_ 37 | commentId: Overload:Cryptography.AesGcmSiv.#ctor 38 | isSpec: "True" 39 | fullName: Cryptography.AesGcmSiv.AesGcmSiv 40 | nameWithType: AesGcmSiv.AesGcmSiv 41 | - uid: Cryptography.AesGcmSiv.Decrypt(System.Byte[],System.Byte[],System.Byte[],System.Byte[],System.Byte[]) 42 | name: Decrypt(Byte[], Byte[], Byte[], Byte[], Byte[]) 43 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Decrypt_System_Byte___System_Byte___System_Byte___System_Byte___System_Byte___ 44 | commentId: M:Cryptography.AesGcmSiv.Decrypt(System.Byte[],System.Byte[],System.Byte[],System.Byte[],System.Byte[]) 45 | name.vb: Decrypt(Byte(), Byte(), Byte(), Byte(), Byte()) 46 | fullName: Cryptography.AesGcmSiv.Decrypt(System.Byte[], System.Byte[], System.Byte[], System.Byte[], System.Byte[]) 47 | fullName.vb: Cryptography.AesGcmSiv.Decrypt(System.Byte(), System.Byte(), System.Byte(), System.Byte(), System.Byte()) 48 | nameWithType: AesGcmSiv.Decrypt(Byte[], Byte[], Byte[], Byte[], Byte[]) 49 | nameWithType.vb: AesGcmSiv.Decrypt(Byte(), Byte(), Byte(), Byte(), Byte()) 50 | - uid: Cryptography.AesGcmSiv.Decrypt(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.Span{System.Byte},System.ReadOnlySpan{System.Byte}) 51 | name: Decrypt(ReadOnlySpan, ReadOnlySpan, ReadOnlySpan, Span, ReadOnlySpan) 52 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Decrypt_System_ReadOnlySpan_System_Byte__System_ReadOnlySpan_System_Byte__System_ReadOnlySpan_System_Byte__System_Span_System_Byte__System_ReadOnlySpan_System_Byte__ 53 | commentId: M:Cryptography.AesGcmSiv.Decrypt(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.Span{System.Byte},System.ReadOnlySpan{System.Byte}) 54 | name.vb: Decrypt(ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), Span(Of Byte), ReadOnlySpan(Of Byte)) 55 | fullName: Cryptography.AesGcmSiv.Decrypt(System.ReadOnlySpan, System.ReadOnlySpan, System.ReadOnlySpan, System.Span, System.ReadOnlySpan) 56 | fullName.vb: Cryptography.AesGcmSiv.Decrypt(System.ReadOnlySpan(Of System.Byte), System.ReadOnlySpan(Of System.Byte), System.ReadOnlySpan(Of System.Byte), System.Span(Of System.Byte), System.ReadOnlySpan(Of System.Byte)) 57 | nameWithType: AesGcmSiv.Decrypt(ReadOnlySpan, ReadOnlySpan, ReadOnlySpan, Span, ReadOnlySpan) 58 | nameWithType.vb: AesGcmSiv.Decrypt(ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), Span(Of Byte), ReadOnlySpan(Of Byte)) 59 | - uid: Cryptography.AesGcmSiv.Decrypt* 60 | name: Decrypt 61 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Decrypt_ 62 | commentId: Overload:Cryptography.AesGcmSiv.Decrypt 63 | isSpec: "True" 64 | fullName: Cryptography.AesGcmSiv.Decrypt 65 | nameWithType: AesGcmSiv.Decrypt 66 | - uid: Cryptography.AesGcmSiv.Dispose 67 | name: Dispose() 68 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Dispose 69 | commentId: M:Cryptography.AesGcmSiv.Dispose 70 | fullName: Cryptography.AesGcmSiv.Dispose() 71 | nameWithType: AesGcmSiv.Dispose() 72 | - uid: Cryptography.AesGcmSiv.Dispose* 73 | name: Dispose 74 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Dispose_ 75 | commentId: Overload:Cryptography.AesGcmSiv.Dispose 76 | isSpec: "True" 77 | fullName: Cryptography.AesGcmSiv.Dispose 78 | nameWithType: AesGcmSiv.Dispose 79 | - uid: Cryptography.AesGcmSiv.Encrypt(System.Byte[],System.Byte[],System.Byte[],System.Byte[],System.Byte[]) 80 | name: Encrypt(Byte[], Byte[], Byte[], Byte[], Byte[]) 81 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Encrypt_System_Byte___System_Byte___System_Byte___System_Byte___System_Byte___ 82 | commentId: M:Cryptography.AesGcmSiv.Encrypt(System.Byte[],System.Byte[],System.Byte[],System.Byte[],System.Byte[]) 83 | name.vb: Encrypt(Byte(), Byte(), Byte(), Byte(), Byte()) 84 | fullName: Cryptography.AesGcmSiv.Encrypt(System.Byte[], System.Byte[], System.Byte[], System.Byte[], System.Byte[]) 85 | fullName.vb: Cryptography.AesGcmSiv.Encrypt(System.Byte(), System.Byte(), System.Byte(), System.Byte(), System.Byte()) 86 | nameWithType: AesGcmSiv.Encrypt(Byte[], Byte[], Byte[], Byte[], Byte[]) 87 | nameWithType.vb: AesGcmSiv.Encrypt(Byte(), Byte(), Byte(), Byte(), Byte()) 88 | - uid: Cryptography.AesGcmSiv.Encrypt(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.Span{System.Byte},System.Span{System.Byte},System.ReadOnlySpan{System.Byte}) 89 | name: Encrypt(ReadOnlySpan, ReadOnlySpan, Span, Span, ReadOnlySpan) 90 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Encrypt_System_ReadOnlySpan_System_Byte__System_ReadOnlySpan_System_Byte__System_Span_System_Byte__System_Span_System_Byte__System_ReadOnlySpan_System_Byte__ 91 | commentId: M:Cryptography.AesGcmSiv.Encrypt(System.ReadOnlySpan{System.Byte},System.ReadOnlySpan{System.Byte},System.Span{System.Byte},System.Span{System.Byte},System.ReadOnlySpan{System.Byte}) 92 | name.vb: Encrypt(ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), Span(Of Byte), Span(Of Byte), ReadOnlySpan(Of Byte)) 93 | fullName: Cryptography.AesGcmSiv.Encrypt(System.ReadOnlySpan, System.ReadOnlySpan, System.Span, System.Span, System.ReadOnlySpan) 94 | fullName.vb: Cryptography.AesGcmSiv.Encrypt(System.ReadOnlySpan(Of System.Byte), System.ReadOnlySpan(Of System.Byte), System.Span(Of System.Byte), System.Span(Of System.Byte), System.ReadOnlySpan(Of System.Byte)) 95 | nameWithType: AesGcmSiv.Encrypt(ReadOnlySpan, ReadOnlySpan, Span, Span, ReadOnlySpan) 96 | nameWithType.vb: AesGcmSiv.Encrypt(ReadOnlySpan(Of Byte), ReadOnlySpan(Of Byte), Span(Of Byte), Span(Of Byte), ReadOnlySpan(Of Byte)) 97 | - uid: Cryptography.AesGcmSiv.Encrypt* 98 | name: Encrypt 99 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_Encrypt_ 100 | commentId: Overload:Cryptography.AesGcmSiv.Encrypt 101 | isSpec: "True" 102 | fullName: Cryptography.AesGcmSiv.Encrypt 103 | nameWithType: AesGcmSiv.Encrypt 104 | - uid: Cryptography.AesGcmSiv.IsSupported 105 | name: IsSupported 106 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_IsSupported 107 | commentId: P:Cryptography.AesGcmSiv.IsSupported 108 | fullName: Cryptography.AesGcmSiv.IsSupported 109 | nameWithType: AesGcmSiv.IsSupported 110 | - uid: Cryptography.AesGcmSiv.IsSupported* 111 | name: IsSupported 112 | href: api/Cryptography.AesGcmSiv.html#Cryptography_AesGcmSiv_IsSupported_ 113 | commentId: Overload:Cryptography.AesGcmSiv.IsSupported 114 | isSpec: "True" 115 | fullName: Cryptography.AesGcmSiv.IsSupported 116 | nameWithType: AesGcmSiv.IsSupported 117 | -------------------------------------------------------------------------------- /src/Cryptography/AesGcmSiv.Encrypt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Intrinsics; 3 | using System.Runtime.Intrinsics.X86; 4 | using Aes = System.Runtime.Intrinsics.X86.Aes; 5 | 6 | namespace Cryptography 7 | { 8 | public unsafe partial class AesGcmSiv 9 | { 10 | // Encrypt4 encrypts ptLen bytes from pt to ct using the expanded key from ks. 11 | // It processes 4 blocks of data in parallel (if the size of the input is not 12 | // divisible by 64, the remainder blocks are handled separately). The initial 13 | // counter is constructed from the given tag as required by AES-GCM-SIV. 14 | private static void Encrypt4(byte* pt, int ptLen, byte* ct, byte* tag, byte* ks) 15 | { 16 | if (ptLen == 0) 17 | { 18 | return; 19 | } 20 | 21 | int blocks = Math.DivRem(ptLen, 16, out int remainder16); 22 | int remainder16Pos = ptLen - remainder16; 23 | int remainder4 = blocks % 4; 24 | int remainder4Pos = blocks - remainder4; 25 | 26 | var orMask = Sse.StaticCast(Sse2.SetVector128(0x80000000, 0, 0, 0)); 27 | var ctr = Sse2.Or(Sse2.LoadVector128(tag), orMask); 28 | 29 | var one = Sse2.SetVector128(0, 0, 0, 1); 30 | var two = Sse2.SetVector128(0, 0, 0, 2); 31 | 32 | for (int i = 0; i < remainder4Pos; i += 4) 33 | { 34 | var tmp0 = ctr; 35 | var tmp1 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 36 | var tmp2 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), two)); 37 | var tmp3 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp2), one)); 38 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp2), two)); 39 | 40 | var key = Sse2.LoadVector128(ks); 41 | tmp0 = Sse2.Xor(tmp0, key); 42 | tmp1 = Sse2.Xor(tmp1, key); 43 | tmp2 = Sse2.Xor(tmp2, key); 44 | tmp3 = Sse2.Xor(tmp3, key); 45 | 46 | for (int j = 1; j < 14; ++j) 47 | { 48 | key = Sse2.LoadVector128(&ks[j * 16]); 49 | tmp0 = Aes.Encrypt(tmp0, key); 50 | tmp1 = Aes.Encrypt(tmp1, key); 51 | tmp2 = Aes.Encrypt(tmp2, key); 52 | tmp3 = Aes.Encrypt(tmp3, key); 53 | } 54 | 55 | key = Sse2.LoadVector128(&ks[14 * 16]); 56 | tmp0 = Aes.EncryptLast(tmp0, key); 57 | tmp1 = Aes.EncryptLast(tmp1, key); 58 | tmp2 = Aes.EncryptLast(tmp2, key); 59 | tmp3 = Aes.EncryptLast(tmp3, key); 60 | 61 | tmp0 = Sse2.Xor(tmp0, Sse2.LoadVector128(&pt[(i + 0) * 16])); 62 | tmp1 = Sse2.Xor(tmp1, Sse2.LoadVector128(&pt[(i + 1) * 16])); 63 | tmp2 = Sse2.Xor(tmp2, Sse2.LoadVector128(&pt[(i + 2) * 16])); 64 | tmp3 = Sse2.Xor(tmp3, Sse2.LoadVector128(&pt[(i + 3) * 16])); 65 | 66 | Sse2.Store(&ct[(i + 0) * 16], tmp0); 67 | Sse2.Store(&ct[(i + 1) * 16], tmp1); 68 | Sse2.Store(&ct[(i + 2) * 16], tmp2); 69 | Sse2.Store(&ct[(i + 3) * 16], tmp3); 70 | } 71 | 72 | for (int i = 0; i < remainder4; ++i) 73 | { 74 | var tmp = ctr; 75 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 76 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(ks)); 77 | 78 | for (int j = 1; j < 14; ++j) 79 | { 80 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[j * 16])); 81 | } 82 | 83 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 84 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(&pt[(remainder4Pos + i) * 16])); 85 | Sse2.Store(&ct[(remainder4Pos + i) * 16], tmp); 86 | } 87 | 88 | if (remainder16 != 0) 89 | { 90 | byte* b = stackalloc byte[16]; 91 | new Span(pt + remainder16Pos, remainder16).CopyTo(new Span(b, 16)); 92 | var tmp = Sse2.Xor(ctr, Sse2.LoadVector128(ks)); 93 | 94 | for (int j = 1; j < 14; ++j) 95 | { 96 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[j * 16])); 97 | } 98 | 99 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 100 | Sse2.Store(b, Sse2.Xor(tmp, Sse2.LoadVector128(b))); 101 | 102 | new Span(b, remainder16).CopyTo(new Span(ct + remainder16Pos, remainder16)); 103 | } 104 | } 105 | 106 | // Encrypt8 encrypts ptLen bytes from pt to ct using the expanded key from ks. 107 | // It processes 8 blocks of data in parallel (if the size of the input is not 108 | // divisible by 128, the remainder blocks are handled separately). The initial 109 | // counter is constructed from the given tag as required by AES-GCM-SIV. 110 | private static void Encrypt8(byte* pt, int ptLen, byte* ct, byte* tag, byte* ks) 111 | { 112 | if (ptLen == 0) 113 | { 114 | return; 115 | } 116 | 117 | int blocks = Math.DivRem(ptLen, 16, out int remainder16); 118 | int remainder16Pos = ptLen - remainder16; 119 | int remainder8 = blocks % 8; 120 | int remainder8Pos = blocks - remainder8; 121 | 122 | var orMask = Sse.StaticCast(Sse2.SetVector128(0x80000000, 0, 0, 0)); 123 | var ctr = Sse2.Or(Sse2.LoadVector128(tag), orMask); 124 | 125 | var one = Sse2.SetVector128(0, 0, 0, 1); 126 | var two = Sse2.SetVector128(0, 0, 0, 2); 127 | 128 | for (int i = 0; i < remainder8Pos; i += 8) 129 | { 130 | var tmp0 = ctr; 131 | var tmp1 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 132 | var tmp2 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), two)); 133 | var tmp3 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp2), one)); 134 | var tmp4 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp2), two)); 135 | var tmp5 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp4), one)); 136 | var tmp6 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp4), two)); 137 | var tmp7 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp6), one)); 138 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(tmp6), two)); 139 | 140 | var key = Sse2.LoadVector128(ks); 141 | tmp0 = Sse2.Xor(tmp0, key); 142 | tmp1 = Sse2.Xor(tmp1, key); 143 | tmp2 = Sse2.Xor(tmp2, key); 144 | tmp3 = Sse2.Xor(tmp3, key); 145 | tmp4 = Sse2.Xor(tmp4, key); 146 | tmp5 = Sse2.Xor(tmp5, key); 147 | tmp6 = Sse2.Xor(tmp6, key); 148 | tmp7 = Sse2.Xor(tmp7, key); 149 | 150 | for (int j = 1; j < 14; ++j) 151 | { 152 | key = Sse2.LoadVector128(&ks[j * 16]); 153 | tmp0 = Aes.Encrypt(tmp0, key); 154 | tmp1 = Aes.Encrypt(tmp1, key); 155 | tmp2 = Aes.Encrypt(tmp2, key); 156 | tmp3 = Aes.Encrypt(tmp3, key); 157 | tmp4 = Aes.Encrypt(tmp4, key); 158 | tmp5 = Aes.Encrypt(tmp5, key); 159 | tmp6 = Aes.Encrypt(tmp6, key); 160 | tmp7 = Aes.Encrypt(tmp7, key); 161 | } 162 | 163 | key = Sse2.LoadVector128(&ks[14 * 16]); 164 | tmp0 = Aes.EncryptLast(tmp0, key); 165 | tmp1 = Aes.EncryptLast(tmp1, key); 166 | tmp2 = Aes.EncryptLast(tmp2, key); 167 | tmp3 = Aes.EncryptLast(tmp3, key); 168 | tmp4 = Aes.EncryptLast(tmp4, key); 169 | tmp5 = Aes.EncryptLast(tmp5, key); 170 | tmp6 = Aes.EncryptLast(tmp6, key); 171 | tmp7 = Aes.EncryptLast(tmp7, key); 172 | 173 | tmp0 = Sse2.Xor(tmp0, Sse2.LoadVector128(&pt[(i + 0) * 16])); 174 | tmp1 = Sse2.Xor(tmp1, Sse2.LoadVector128(&pt[(i + 1) * 16])); 175 | tmp2 = Sse2.Xor(tmp2, Sse2.LoadVector128(&pt[(i + 2) * 16])); 176 | tmp3 = Sse2.Xor(tmp3, Sse2.LoadVector128(&pt[(i + 3) * 16])); 177 | tmp4 = Sse2.Xor(tmp4, Sse2.LoadVector128(&pt[(i + 4) * 16])); 178 | tmp5 = Sse2.Xor(tmp5, Sse2.LoadVector128(&pt[(i + 5) * 16])); 179 | tmp6 = Sse2.Xor(tmp6, Sse2.LoadVector128(&pt[(i + 6) * 16])); 180 | tmp7 = Sse2.Xor(tmp7, Sse2.LoadVector128(&pt[(i + 7) * 16])); 181 | 182 | Sse2.Store(&ct[(i + 0) * 16], tmp0); 183 | Sse2.Store(&ct[(i + 1) * 16], tmp1); 184 | Sse2.Store(&ct[(i + 2) * 16], tmp2); 185 | Sse2.Store(&ct[(i + 3) * 16], tmp3); 186 | Sse2.Store(&ct[(i + 4) * 16], tmp4); 187 | Sse2.Store(&ct[(i + 5) * 16], tmp5); 188 | Sse2.Store(&ct[(i + 6) * 16], tmp6); 189 | Sse2.Store(&ct[(i + 7) * 16], tmp7); 190 | } 191 | 192 | for (int i = 0; i < remainder8; ++i) 193 | { 194 | var tmp = ctr; 195 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 196 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(ks)); 197 | 198 | for (int j = 1; j < 14; ++j) 199 | { 200 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[j * 16])); 201 | } 202 | 203 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 204 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(&pt[(remainder8Pos + i) * 16])); 205 | Sse2.Store(&ct[(remainder8Pos + i) * 16], tmp); 206 | } 207 | 208 | if (remainder16 != 0) 209 | { 210 | byte* b = stackalloc byte[16]; 211 | new Span(pt + remainder16Pos, remainder16).CopyTo(new Span(b, 16)); 212 | var tmp = Sse2.Xor(ctr, Sse2.LoadVector128(ks)); 213 | 214 | for (int j = 1; j < 14; ++j) 215 | { 216 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[j * 16])); 217 | } 218 | 219 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 220 | Sse2.Store(b, Sse2.Xor(tmp, Sse2.LoadVector128(b))); 221 | 222 | new Span(b, remainder16).CopyTo(new Span(ct + remainder16Pos, remainder16)); 223 | } 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AES-GCM-SIV 2 | 3 | [![NuGet][nuget-shield]][nuget-link] 4 | [![Build Status][build-shield]][build-link] 5 | [![Blazing Fast][speed-shield]][speed-link] 6 | [![API Docs][docs-shield]][docs-link] 7 | [![License][license-shield]][license-link] 8 | 9 | .NET Core 3.0 implementation of [AES-GCM-SIV] nonce misuse-resistant authenticated 10 | encryption, defined in [draft-irtf-cfrg-gcmsiv-08]. Fastest available authenticated 11 | encryption library for .NET, with the encryption/decryption rate of roughly 8 Gbps/core. 12 | Implemented using .NET Core 3.0 platform intrinsics. 13 | 14 | ![](aes-gcm-siv.svg) 15 | 16 | [nuget-shield]: https://img.shields.io/nuget/v/AES-GCM-SIV.svg 17 | [nuget-link]: https://www.nuget.org/packages/AES-GCM-SIV 18 | [build-shield]: https://dev.azure.com/metalnem/aes-gcm-siv/_apis/build/status/Metalnem.aes-gcm-siv 19 | [build-link]: https://dev.azure.com/metalnem/aes-gcm-siv/_build/latest?definitionId=1 20 | [speed-shield]: https://img.shields.io/badge/speed-blazing%20%F0%9F%94%A5-brightgreen.svg 21 | [speed-link]: https://twitter.com/acdlite/status/974390255393505280 22 | [docs-shield]: https://img.shields.io/badge/docs-API-orange.svg?style=flat 23 | [docs-link]: https://metalnem.github.io/aes-gcm-siv/api/Cryptography.AesGcmSiv.html 24 | [license-shield]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat 25 | [license-link]: https://github.com/metalnem/aes-gcm-siv/blob/master/LICENSE 26 | [AES-GCM-SIV]: https://eprint.iacr.org/2017/168.pdf 27 | [draft-irtf-cfrg-gcmsiv-08]: https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-08 28 | 29 | ## Usage 30 | 31 | ```csharp 32 | // Plaintext to encrypt. 33 | var plaintext = "I'm cooking MC's like a pound of bacon"; 34 | 35 | // Create a 32-byte key. 36 | var key = new byte[32]; 37 | RandomNumberGenerator.Fill(key); 38 | 39 | // Create a 12-byte nonce. 40 | var nonce = new byte[12]; 41 | RandomNumberGenerator.Fill(nonce); 42 | 43 | // Create a new AesGcmSiv instance. It implements the IDisposable 44 | // interface, so it's best to create it inside using statement. 45 | using (var siv = new AesGcmSiv(key)) 46 | { 47 | // If the message is string, convert it to byte array first. 48 | var bytes = Encoding.UTF8.GetBytes(plaintext); 49 | 50 | // Encrypt the message. 51 | var ciphertext = new byte[bytes.Length]; 52 | var tag = new byte[16]; 53 | siv.Encrypt(nonce, bytes, ciphertext, tag); 54 | 55 | // To decrypt the message, call the Decrypt method with the 56 | // ciphertext and the same nonce that you generated previously. 57 | siv.Decrypt(nonce, ciphertext, tag, bytes); 58 | 59 | // If the message was originally string, 60 | // convert if from byte array to string. 61 | plaintext = Encoding.UTF8.GetString(bytes); 62 | 63 | // Print the decrypted message to the standard output. 64 | Console.WriteLine(plaintext); 65 | } 66 | ``` 67 | 68 | ## Installation 69 | 70 | ``` 71 | > dotnet add package AES-GCM-SIV --version 0.3.2 72 | ``` 73 | 74 | ## Acknowledgements 75 | 76 | This implementation is based on the [C intrinsics code] written by Shay Gueron. 77 | 78 | [C intrinsics code]: https://github.com/Shay-Gueron/AES-GCM-SIV 79 | 80 | ## Resources 81 | 82 | [AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption](https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-08) 83 | [AES-GCM-SIV: Specification and Analysis](https://eprint.iacr.org/2017/168.pdf) 84 | [Webpage for the AES-GCM-SIV Mode of Operation](https://cyber.biu.ac.il/aes-gcm-siv/) 85 | [AES-GCM-SIV implementations (128 and 256 bit)](https://github.com/Shay-Gueron/AES-GCM-SIV) 86 | [Go implementation](https://github.com/agl/gcmsiv) 87 | [Java implementation](https://github.com/codahale/aes-gcm-siv) 88 | [AES-GCM-SIV (Adam Langley)](https://www.imperialviolet.org/2017/05/14/aesgcmsiv.html) 89 | [Towards A Safer Footgun (Coda Hale)](https://codahale.com/towards-a-safer-footgun/) 90 | 91 | ## Performance (Windows) 92 | 93 | ``` ini 94 | BenchmarkDotNet=v0.11.1, OS=Windows 10.0.17134.345 (1803/April2018Update/Redstone4) 95 | Intel Core i7-4800MQ CPU 2.70GHz (Max: 2.69GHz) (Haswell), 1 CPU, 8 logical and 4 physical cores 96 | Frequency=2630636 Hz, Resolution=380.1362 ns, Timer=TSC 97 | .NET Core SDK=3.0.100-alpha1-009638 98 | [Host] : .NET Core 3.0.0-preview1-27003-04 (CoreCLR 4.6.27002.04, CoreFX 4.6.27002.03), 64bit RyuJIT 99 | ``` 100 | | Method | Categories | Size | Mean | Error | StdDev | Scaled | 101 | |------------ |----------- |----- |-----------:|-----------:|------------:|-------:| 102 | | **AES-GCM** | **Encryption** | **128** | **306.2 ns** | **0.5986 ns** | **0.5307 ns** | **1.00** | 103 | | AES-GCM-SIV | Encryption | 128 | 287.7 ns | 3.6306 ns | 3.2185 ns | 0.94 | 104 | | | | | | | | | 105 | | AES-GCM | Decryption | 128 | 311.7 ns | 0.2751 ns | 0.2438 ns | 1.00 | 106 | | AES-GCM-SIV | Decryption | 128 | 329.5 ns | 2.6803 ns | 2.2382 ns | 1.06 | 107 | | | | | | | | | 108 | | **AES-GCM** | **Encryption** | **1024** | **681.1 ns** | **1.5380 ns** | **1.3634 ns** | **1.00** | 109 | | AES-GCM-SIV | Encryption | 1024 | 663.0 ns | 2.6639 ns | 2.4918 ns | 0.97 | 110 | | | | | | | | | 111 | | AES-GCM | Decryption | 1024 | 681.0 ns | 0.7810 ns | 0.6923 ns | 1.00 | 112 | | AES-GCM-SIV | Decryption | 1024 | 715.3 ns | 1.3908 ns | 1.3009 ns | 1.05 | 113 | | | | | | | | | 114 | | **AES-GCM** | **Encryption** | **4096** | **1,984.3 ns** | **6.5387 ns** | **5.4601 ns** | **1.00** | 115 | | AES-GCM-SIV | Encryption | 4096 | 1,877.8 ns | 0.5862 ns | 0.5196 ns | 0.95 | 116 | | | | | | | | | 117 | | AES-GCM | Decryption | 4096 | 1,988.5 ns | 1.0060 ns | 0.8401 ns | 1.00 | 118 | | AES-GCM-SIV | Decryption | 4096 | 1,882.5 ns | 7.0526 ns | 6.5970 ns | 0.95 | 119 | | | | | | | | | 120 | | **AES-GCM** | **Encryption** | **8192** | **3,754.4 ns** | **84.4706 ns** | **79.0138 ns** | **1.00** | 121 | | AES-GCM-SIV | Encryption | 8192 | 3,503.4 ns | 2.5222 ns | 2.1061 ns | 0.93 | 122 | | | | | | | | | 123 | | AES-GCM | Decryption | 8192 | 4,038.8 ns | 79.7916 ns | 114.4348 ns | 1.00 | 124 | | AES-GCM-SIV | Decryption | 8192 | 3,609.7 ns | 66.9556 ns | 62.6303 ns | 0.89 | 125 | 126 | ## Performance (macOS) 127 | 128 | ``` ini 129 | BenchmarkDotNet=v0.11.1, OS=macOS Mojave 10.14 (18A391) [Darwin 18.0.0] 130 | Intel Core i7-5557U CPU 3.10GHz (Broadwell), 1 CPU, 4 logical and 2 physical cores 131 | .NET Core SDK=3.0.100-alpha1-009640 132 | [Host] : .NET Core 3.0.0-preview1-27004-04 (CoreCLR 4.6.27003.04, CoreFX 4.6.27003.02), 64bit RyuJIT 133 | ``` 134 | | Method | Categories | Size | Mean | Error | StdDev | Scaled | 135 | |------------ |----------- |----- |-----------:|----------:|----------:|-------:| 136 | | **AES-GCM** | **Encryption** | **128** | **503.1 ns** | **0.2081 ns** | **0.1737 ns** | **1.00** | 137 | | AES-GCM-SIV | Encryption | 128 | 315.4 ns | 0.1813 ns | 0.1514 ns | 0.63 | 138 | | | | | | | | | 139 | | AES-GCM | Decryption | 128 | 517.2 ns | 0.4337 ns | 0.3621 ns | 1.00 | 140 | | AES-GCM-SIV | Decryption | 128 | 368.2 ns | 0.1659 ns | 0.1385 ns | 0.71 | 141 | | | | | | | | | 142 | | **AES-GCM** | **Encryption** | **1024** | **795.1 ns** | **1.0668 ns** | **0.9979 ns** | **1.00** | 143 | | AES-GCM-SIV | Encryption | 1024 | 666.7 ns | 0.5449 ns | 0.4830 ns | 0.84 | 144 | | | | | | | | | 145 | | AES-GCM | Decryption | 1024 | 779.5 ns | 1.2164 ns | 0.9497 ns | 1.00 | 146 | | AES-GCM-SIV | Decryption | 1024 | 697.7 ns | 0.8535 ns | 0.7566 ns | 0.90 | 147 | | | | | | | | | 148 | | **AES-GCM** | **Encryption** | **4096** | **1,711.2 ns** | **2.1837 ns** | **2.0426 ns** | **1.00** | 149 | | AES-GCM-SIV | Encryption | 4096 | 1,767.6 ns | 2.5230 ns | 2.2366 ns | 1.03 | 150 | | | | | | | | | 151 | | AES-GCM | Decryption | 4096 | 1,711.9 ns | 6.3718 ns | 5.9602 ns | 1.00 | 152 | | AES-GCM-SIV | Decryption | 4096 | 1,780.6 ns | 1.7417 ns | 1.5440 ns | 1.04 | 153 | | | | | | | | | 154 | | **AES-GCM** | **Encryption** | **8192** | **2,981.2 ns** | **8.2092 ns** | **7.6789 ns** | **1.00** | 155 | | AES-GCM-SIV | Encryption | 8192 | 3,276.0 ns | 4.5095 ns | 3.7657 ns | 1.10 | 156 | | | | | | | | | 157 | | AES-GCM | Decryption | 8192 | 2,991.5 ns | 6.8195 ns | 6.3789 ns | 1.00 | 158 | | AES-GCM-SIV | Decryption | 8192 | 3,205.7 ns | 4.4109 ns | 4.1260 ns | 1.07 | 159 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: AES-GCM-SIV 3 | --- 4 | 5 | # AES-GCM-SIV 6 | 7 | [![NuGet][nuget-shield]][nuget-link] 8 | [![Build Status][build-shield]][build-link] 9 | [![Blazing Fast][speed-shield]][speed-link] 10 | [![API Docs][docs-shield]][docs-link] 11 | [![License][license-shield]][license-link] 12 | 13 | .NET Core 3.0 implementation of [AES-GCM-SIV] nonce misuse-resistant authenticated 14 | encryption, defined in [draft-irtf-cfrg-gcmsiv-08]. Fastest available authenticated 15 | encryption library for .NET, with the encryption/decryption rate of roughly 8 Gbps/core. 16 | Implemented using .NET Core 3.0 platform intrinsics. 17 | 18 | ![](aes-gcm-siv.svg) 19 | 20 | [nuget-shield]: https://img.shields.io/nuget/v/AES-GCM-SIV.svg 21 | [nuget-link]: https://www.nuget.org/packages/AES-GCM-SIV 22 | [build-shield]: https://dev.azure.com/metalnem/aes-gcm-siv/_apis/build/status/Metalnem.aes-gcm-siv 23 | [build-link]: https://dev.azure.com/metalnem/aes-gcm-siv/_build/latest?definitionId=1 24 | [speed-shield]: https://img.shields.io/badge/speed-blazing%20%F0%9F%94%A5-brightgreen.svg 25 | [speed-link]: https://twitter.com/acdlite/status/974390255393505280 26 | [docs-shield]: https://img.shields.io/badge/docs-API-orange.svg?style=flat 27 | [docs-link]: https://metalnem.github.io/aes-gcm-siv/api/Cryptography.AesGcmSiv.html 28 | [license-shield]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat 29 | [license-link]: https://github.com/metalnem/aes-gcm-siv/blob/master/LICENSE 30 | [AES-GCM-SIV]: https://eprint.iacr.org/2017/168.pdf 31 | [draft-irtf-cfrg-gcmsiv-08]: https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-08 32 | 33 | ## Usage 34 | 35 | ```csharp 36 | // Plaintext to encrypt. 37 | var plaintext = "I'm cooking MC's like a pound of bacon"; 38 | 39 | // Create a 32-byte key. 40 | var key = new byte[32]; 41 | RandomNumberGenerator.Fill(key); 42 | 43 | // Create a 12-byte nonce. 44 | var nonce = new byte[12]; 45 | RandomNumberGenerator.Fill(nonce); 46 | 47 | // Create a new AesGcmSiv instance. It implements the IDisposable 48 | // interface, so it's best to create it inside using statement. 49 | using (var siv = new AesGcmSiv(key)) 50 | { 51 | // If the message is string, convert it to byte array first. 52 | var bytes = Encoding.UTF8.GetBytes(plaintext); 53 | 54 | // Encrypt the message. 55 | var ciphertext = new byte[bytes.Length]; 56 | var tag = new byte[16]; 57 | siv.Encrypt(nonce, bytes, ciphertext, tag); 58 | 59 | // To decrypt the message, call the Decrypt method with the 60 | // ciphertext and the same nonce that you generated previously. 61 | siv.Decrypt(nonce, ciphertext, tag, bytes); 62 | 63 | // If the message was originally string, 64 | // convert if from byte array to string. 65 | plaintext = Encoding.UTF8.GetString(bytes); 66 | 67 | // Print the decrypted message to the standard output. 68 | Console.WriteLine(plaintext); 69 | } 70 | ``` 71 | 72 | ## Installation 73 | 74 | ``` 75 | > dotnet add package AES-GCM-SIV --version 0.3.2 76 | ``` 77 | 78 | ## Acknowledgements 79 | 80 | This implementation is based on the [C intrinsics code] written by Shay Gueron. 81 | 82 | [C intrinsics code]: https://github.com/Shay-Gueron/AES-GCM-SIV 83 | 84 | ## Resources 85 | 86 | [AES-GCM-SIV: Nonce Misuse-Resistant Authenticated Encryption](https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-08) 87 | [AES-GCM-SIV: Specification and Analysis](https://eprint.iacr.org/2017/168.pdf) 88 | [Webpage for the AES-GCM-SIV Mode of Operation](https://cyber.biu.ac.il/aes-gcm-siv/) 89 | [AES-GCM-SIV implementations (128 and 256 bit)](https://github.com/Shay-Gueron/AES-GCM-SIV) 90 | [Go implementation](https://github.com/agl/gcmsiv) 91 | [Java implementation](https://github.com/codahale/aes-gcm-siv) 92 | [AES-GCM-SIV (Adam Langley)](https://www.imperialviolet.org/2017/05/14/aesgcmsiv.html) 93 | [Towards A Safer Footgun (Coda Hale)](https://codahale.com/towards-a-safer-footgun/) 94 | 95 | ## Performance (Windows) 96 | 97 | ``` ini 98 | BenchmarkDotNet=v0.11.1, OS=Windows 10.0.17134.345 (1803/April2018Update/Redstone4) 99 | Intel Core i7-4800MQ CPU 2.70GHz (Max: 2.69GHz) (Haswell), 1 CPU, 8 logical and 4 physical cores 100 | Frequency=2630636 Hz, Resolution=380.1362 ns, Timer=TSC 101 | .NET Core SDK=3.0.100-alpha1-009638 102 | [Host] : .NET Core 3.0.0-preview1-27003-04 (CoreCLR 4.6.27002.04, CoreFX 4.6.27002.03), 64bit RyuJIT 103 | ``` 104 | | Method | Categories | Size | Mean | Error | StdDev | Scaled | 105 | |------------ |----------- |----- |-----------:|-----------:|------------:|-------:| 106 | | **AES-GCM** | **Encryption** | **128** | **306.2 ns** | **0.5986 ns** | **0.5307 ns** | **1.00** | 107 | | AES-GCM-SIV | Encryption | 128 | 287.7 ns | 3.6306 ns | 3.2185 ns | 0.94 | 108 | | | | | | | | | 109 | | AES-GCM | Decryption | 128 | 311.7 ns | 0.2751 ns | 0.2438 ns | 1.00 | 110 | | AES-GCM-SIV | Decryption | 128 | 329.5 ns | 2.6803 ns | 2.2382 ns | 1.06 | 111 | | | | | | | | | 112 | | **AES-GCM** | **Encryption** | **1024** | **681.1 ns** | **1.5380 ns** | **1.3634 ns** | **1.00** | 113 | | AES-GCM-SIV | Encryption | 1024 | 663.0 ns | 2.6639 ns | 2.4918 ns | 0.97 | 114 | | | | | | | | | 115 | | AES-GCM | Decryption | 1024 | 681.0 ns | 0.7810 ns | 0.6923 ns | 1.00 | 116 | | AES-GCM-SIV | Decryption | 1024 | 715.3 ns | 1.3908 ns | 1.3009 ns | 1.05 | 117 | | | | | | | | | 118 | | **AES-GCM** | **Encryption** | **4096** | **1,984.3 ns** | **6.5387 ns** | **5.4601 ns** | **1.00** | 119 | | AES-GCM-SIV | Encryption | 4096 | 1,877.8 ns | 0.5862 ns | 0.5196 ns | 0.95 | 120 | | | | | | | | | 121 | | AES-GCM | Decryption | 4096 | 1,988.5 ns | 1.0060 ns | 0.8401 ns | 1.00 | 122 | | AES-GCM-SIV | Decryption | 4096 | 1,882.5 ns | 7.0526 ns | 6.5970 ns | 0.95 | 123 | | | | | | | | | 124 | | **AES-GCM** | **Encryption** | **8192** | **3,754.4 ns** | **84.4706 ns** | **79.0138 ns** | **1.00** | 125 | | AES-GCM-SIV | Encryption | 8192 | 3,503.4 ns | 2.5222 ns | 2.1061 ns | 0.93 | 126 | | | | | | | | | 127 | | AES-GCM | Decryption | 8192 | 4,038.8 ns | 79.7916 ns | 114.4348 ns | 1.00 | 128 | | AES-GCM-SIV | Decryption | 8192 | 3,609.7 ns | 66.9556 ns | 62.6303 ns | 0.89 | 129 | 130 | ## Performance (macOS) 131 | 132 | ``` ini 133 | BenchmarkDotNet=v0.11.1, OS=macOS Mojave 10.14 (18A391) [Darwin 18.0.0] 134 | Intel Core i7-5557U CPU 3.10GHz (Broadwell), 1 CPU, 4 logical and 2 physical cores 135 | .NET Core SDK=3.0.100-alpha1-009640 136 | [Host] : .NET Core 3.0.0-preview1-27004-04 (CoreCLR 4.6.27003.04, CoreFX 4.6.27003.02), 64bit RyuJIT 137 | ``` 138 | | Method | Categories | Size | Mean | Error | StdDev | Scaled | 139 | |------------ |----------- |----- |-----------:|----------:|----------:|-------:| 140 | | **AES-GCM** | **Encryption** | **128** | **503.1 ns** | **0.2081 ns** | **0.1737 ns** | **1.00** | 141 | | AES-GCM-SIV | Encryption | 128 | 315.4 ns | 0.1813 ns | 0.1514 ns | 0.63 | 142 | | | | | | | | | 143 | | AES-GCM | Decryption | 128 | 517.2 ns | 0.4337 ns | 0.3621 ns | 1.00 | 144 | | AES-GCM-SIV | Decryption | 128 | 368.2 ns | 0.1659 ns | 0.1385 ns | 0.71 | 145 | | | | | | | | | 146 | | **AES-GCM** | **Encryption** | **1024** | **795.1 ns** | **1.0668 ns** | **0.9979 ns** | **1.00** | 147 | | AES-GCM-SIV | Encryption | 1024 | 666.7 ns | 0.5449 ns | 0.4830 ns | 0.84 | 148 | | | | | | | | | 149 | | AES-GCM | Decryption | 1024 | 779.5 ns | 1.2164 ns | 0.9497 ns | 1.00 | 150 | | AES-GCM-SIV | Decryption | 1024 | 697.7 ns | 0.8535 ns | 0.7566 ns | 0.90 | 151 | | | | | | | | | 152 | | **AES-GCM** | **Encryption** | **4096** | **1,711.2 ns** | **2.1837 ns** | **2.0426 ns** | **1.00** | 153 | | AES-GCM-SIV | Encryption | 4096 | 1,767.6 ns | 2.5230 ns | 2.2366 ns | 1.03 | 154 | | | | | | | | | 155 | | AES-GCM | Decryption | 4096 | 1,711.9 ns | 6.3718 ns | 5.9602 ns | 1.00 | 156 | | AES-GCM-SIV | Decryption | 4096 | 1,780.6 ns | 1.7417 ns | 1.5440 ns | 1.04 | 157 | | | | | | | | | 158 | | **AES-GCM** | **Encryption** | **8192** | **2,981.2 ns** | **8.2092 ns** | **7.6789 ns** | **1.00** | 159 | | AES-GCM-SIV | Encryption | 8192 | 3,276.0 ns | 4.5095 ns | 3.7657 ns | 1.10 | 160 | | | | | | | | | 161 | | AES-GCM | Decryption | 8192 | 2,991.5 ns | 6.8195 ns | 6.3789 ns | 1.00 | 162 | | AES-GCM-SIV | Decryption | 8192 | 3,205.7 ns | 4.4109 ns | 4.1260 ns | 1.07 | 163 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/AesGcmSivTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Reflection; 6 | using System.Runtime.InteropServices; 7 | using System.Security.Cryptography; 8 | using Newtonsoft.Json.Linq; 9 | using Xunit; 10 | 11 | namespace Cryptography.Tests 12 | { 13 | public class AesGcmSivTest 14 | { 15 | private const string Aes128GcmSiv = "Vectors/aes-128-gcm-siv.json"; 16 | private const string Aes256GcmSiv = "Vectors/aes-256-gcm-siv.json"; 17 | private const string Authentication1000 = "Vectors/authentication-1000.json"; 18 | private const string CounterWrap = "Vectors/counter-wrap.json"; 19 | private const string Encryption1000 = "Vectors/encryption-1000.json"; 20 | private const string RandomKeys10000 = "Vectors/random-keys-10000.json"; 21 | 22 | private static readonly FieldInfo threshold = 23 | typeof(AesGcmSiv).GetField("threshold", BindingFlags.Instance | BindingFlags.NonPublic); 24 | 25 | [Fact] 26 | public void TestEncrypt() 27 | { 28 | var files = new string[] 29 | { 30 | Aes256GcmSiv, 31 | Authentication1000, 32 | CounterWrap, 33 | Encryption1000, 34 | RandomKeys10000 35 | }; 36 | 37 | foreach (var vector in files.SelectMany(LoadVectors)) 38 | { 39 | using (var siv = new AesGcmSiv(vector.Key)) 40 | { 41 | TestEncryptSingle(siv, vector); 42 | 43 | threshold.SetValue(siv, -1); 44 | TestEncryptSingle(siv, vector); 45 | 46 | threshold.SetValue(siv, Int32.MaxValue); 47 | TestEncryptSingle(siv, vector); 48 | } 49 | } 50 | } 51 | 52 | private void TestEncryptSingle(AesGcmSiv siv, Vector vector) 53 | { 54 | var tag = new byte[16]; 55 | var ciphertext = new byte[vector.Plaintext.Length]; 56 | 57 | siv.Encrypt(vector.Nonce, vector.Plaintext, ciphertext, tag, vector.Aad); 58 | Assert.Equal(Hex.Encode(vector.Result), Hex.Encode(Concat(ciphertext, tag))); 59 | 60 | siv.Encrypt((ReadOnlySpan)vector.Nonce, vector.Plaintext, ciphertext, tag, vector.Aad); 61 | Assert.Equal(Hex.Encode(vector.Result), Hex.Encode(Concat(ciphertext, tag))); 62 | } 63 | 64 | [Fact] 65 | public void TestDecrypt() 66 | { 67 | var files = new string[] 68 | { 69 | Aes256GcmSiv, 70 | Authentication1000, 71 | CounterWrap, 72 | Encryption1000, 73 | RandomKeys10000 74 | }; 75 | 76 | foreach (var vector in files.SelectMany(LoadVectors)) 77 | { 78 | using (var siv = new AesGcmSiv(vector.Key)) 79 | { 80 | TestDecryptSingle(siv, vector); 81 | 82 | threshold.SetValue(siv, -1); 83 | TestDecryptSingle(siv, vector); 84 | 85 | threshold.SetValue(siv, Int32.MaxValue); 86 | TestDecryptSingle(siv, vector); 87 | } 88 | } 89 | } 90 | 91 | [Fact(Skip = "Takes too long to complete.")] 92 | public void TestDecryptFailure() 93 | { 94 | var files = new string[] 95 | { 96 | Aes256GcmSiv, 97 | Authentication1000, 98 | CounterWrap, 99 | Encryption1000, 100 | RandomKeys10000 101 | }; 102 | 103 | foreach (var vector in files.SelectMany(LoadVectors)) 104 | { 105 | using (var siv = new AesGcmSiv(vector.Key)) 106 | { 107 | var ciphertext = vector.Result.AsSpan(0, vector.Plaintext.Length); 108 | var tag = vector.Result.AsSpan(vector.Plaintext.Length); 109 | 110 | for (int i = 0; i < ciphertext.Length; ++i) 111 | { 112 | var value = ciphertext[i]; 113 | 114 | for (int j = 0; j < 8; ++j) 115 | { 116 | ciphertext[i] ^= (byte)(1 << j); 117 | Assert.Throws(() => TestDecryptSingle(siv, vector)); 118 | 119 | ciphertext[i] ^= (byte)(1 << j); 120 | Assert.Equal(value, ciphertext[i]); 121 | } 122 | } 123 | 124 | for (int i = 0; i < vector.Aad.Length; ++i) 125 | { 126 | var value = vector.Aad[i]; 127 | 128 | for (int j = 0; j < 8; ++j) 129 | { 130 | vector.Aad[i] ^= (byte)(1 << j); 131 | Assert.Throws(() => TestDecryptSingle(siv, vector)); 132 | 133 | vector.Aad[i] ^= (byte)(1 << j); 134 | Assert.Equal(value, vector.Aad[i]); 135 | } 136 | } 137 | 138 | for (int i = 0; i < tag.Length; ++i) 139 | { 140 | var value = tag[i]; 141 | 142 | for (int j = 0; j < 8; ++j) 143 | { 144 | tag[i] ^= (byte)(1 << j); 145 | Assert.Throws(() => TestDecryptSingle(siv, vector)); 146 | 147 | tag[i] ^= (byte)(1 << j); 148 | Assert.Equal(value, tag[i]); 149 | } 150 | } 151 | } 152 | } 153 | } 154 | 155 | private void TestDecryptSingle(AesGcmSiv siv, Vector vector) 156 | { 157 | var ciphertext = new byte[vector.Plaintext.Length]; 158 | var tag = new byte[16]; 159 | 160 | Array.Copy(vector.Result, ciphertext, vector.Plaintext.Length); 161 | Array.Copy(vector.Result, vector.Plaintext.Length, tag, 0, tag.Length); 162 | 163 | siv.Decrypt(vector.Nonce, ciphertext, tag, ciphertext, vector.Aad); 164 | Assert.Equal(Hex.Encode(vector.Plaintext), Hex.Encode(ciphertext)); 165 | 166 | Array.Copy(vector.Result, ciphertext, vector.Plaintext.Length); 167 | Array.Copy(vector.Result, vector.Plaintext.Length, tag, 0, tag.Length); 168 | 169 | siv.Decrypt((ReadOnlySpan)vector.Nonce, ciphertext, tag, ciphertext, vector.Aad); 170 | Assert.Equal(Hex.Encode(vector.Plaintext), Hex.Encode(ciphertext)); 171 | } 172 | 173 | [Fact(Skip = "Takes too long to complete.")] 174 | public void TestMaxInputLengthManaged() 175 | { 176 | var key = new byte[32]; 177 | var nonce = new byte[12]; 178 | var plaintext = new byte[0x7fffffc7]; 179 | var tag = new byte[16]; 180 | var empty = new byte[0]; 181 | 182 | using (var siv = new AesGcmSiv(key)) 183 | { 184 | siv.Encrypt(nonce, plaintext, plaintext, tag); 185 | Assert.Equal("b8f9d292c80c757ce0639ee04dba3ebd", Hex.Encode(tag)); 186 | 187 | siv.Decrypt(nonce, plaintext, tag, plaintext); 188 | 189 | siv.Encrypt(nonce, empty, empty, tag, plaintext); 190 | Assert.Equal("a6126fd232ed46bfa639cef6418b14fd", Hex.Encode(tag)); 191 | 192 | siv.Decrypt(nonce, empty, tag, empty, plaintext); 193 | 194 | siv.Encrypt(nonce, plaintext, plaintext, tag, plaintext); 195 | Assert.Equal("6d15c063e7c3d68db84201d887ddde46", Hex.Encode(tag)); 196 | 197 | siv.Decrypt(nonce, plaintext, tag, plaintext, plaintext); 198 | Assert.True(plaintext.All(item => item == 0)); 199 | } 200 | } 201 | 202 | [Fact(Skip = "Takes too long to complete.")] 203 | public unsafe void TestMaxInputLengthUnmanaged() 204 | { 205 | var length = Int32.MaxValue; 206 | var buffer = Marshal.AllocHGlobal(length); 207 | 208 | try 209 | { 210 | var key = new byte[32]; 211 | var nonce = new byte[12]; 212 | var plaintext = new Span(buffer.ToPointer(), length); 213 | var tag = new byte[16]; 214 | 215 | using (var siv = new AesGcmSiv(key)) 216 | { 217 | siv.Encrypt(nonce, plaintext, plaintext, tag, default); 218 | Assert.Equal("b8246fbcb073f59dbf963b46a19db688", Hex.Encode(tag)); 219 | 220 | siv.Decrypt(nonce, plaintext, tag, plaintext, default); 221 | 222 | siv.Encrypt(nonce, default, default, tag, plaintext); 223 | Assert.Equal("c5b65922f2f64799a1d62c8036520c9d", Hex.Encode(tag)); 224 | 225 | siv.Decrypt(nonce, default, tag, default, plaintext); 226 | 227 | siv.Encrypt(nonce, plaintext, plaintext, tag, plaintext); 228 | Assert.Equal("e017665be4c97b25610602e6e4c81a5e", Hex.Encode(tag)); 229 | 230 | siv.Decrypt(nonce, plaintext, tag, plaintext, plaintext); 231 | 232 | foreach (var item in plaintext) 233 | { 234 | Assert.Equal(0, item); 235 | } 236 | } 237 | } 238 | finally 239 | { 240 | Marshal.FreeHGlobal(buffer); 241 | } 242 | } 243 | 244 | [Fact] 245 | public void TestParameterValidation() 246 | { 247 | Assert.Throws(() => new AesGcmSiv(null)); 248 | Assert.Throws(() => new AesGcmSiv(new byte[16])); 249 | Assert.Throws(() => new AesGcmSiv(new byte[48])); 250 | 251 | var key = new byte[32]; 252 | var nonce = new byte[12]; 253 | var plaintext = new byte[128]; 254 | var ciphertext = new byte[128]; 255 | var tag = new byte[16]; 256 | var empty = new byte[0]; 257 | 258 | using (var siv = new AesGcmSiv(key)) 259 | { 260 | Assert.Throws(() => siv.Encrypt(null, plaintext, ciphertext, tag)); 261 | Assert.Throws(() => siv.Encrypt(nonce, null, ciphertext, tag)); 262 | Assert.Throws(() => siv.Encrypt(nonce, plaintext, null, tag)); 263 | Assert.Throws(() => siv.Encrypt(nonce, plaintext, ciphertext, null)); 264 | 265 | Assert.Throws(() => siv.Encrypt(empty, plaintext, ciphertext, tag)); 266 | Assert.Throws(() => siv.Encrypt(nonce, plaintext, ciphertext, empty)); 267 | Assert.Throws(() => siv.Encrypt(nonce, plaintext, empty, tag)); 268 | Assert.Throws(() => siv.Encrypt(nonce, empty, ciphertext, tag)); 269 | 270 | Assert.Throws(() => siv.Encrypt((ReadOnlySpan)empty, plaintext, ciphertext, tag, default)); 271 | Assert.Throws(() => siv.Encrypt((ReadOnlySpan)nonce, plaintext, ciphertext, empty, default)); 272 | Assert.Throws(() => siv.Encrypt((ReadOnlySpan)nonce, plaintext, empty, tag, default)); 273 | Assert.Throws(() => siv.Encrypt((ReadOnlySpan)nonce, empty, ciphertext, tag, default)); 274 | 275 | siv.Encrypt(nonce, plaintext, ciphertext, tag); 276 | 277 | Assert.Throws(() => siv.Decrypt(null, ciphertext, tag, plaintext)); 278 | Assert.Throws(() => siv.Decrypt(nonce, null, tag, plaintext)); 279 | Assert.Throws(() => siv.Decrypt(nonce, ciphertext, null, plaintext)); 280 | Assert.Throws(() => siv.Decrypt(nonce, ciphertext, tag, null)); 281 | 282 | Assert.Throws(() => siv.Decrypt(empty, ciphertext, tag, plaintext)); 283 | Assert.Throws(() => siv.Decrypt(nonce, ciphertext, empty, plaintext)); 284 | Assert.Throws(() => siv.Decrypt(nonce, empty, tag, plaintext)); 285 | Assert.Throws(() => siv.Decrypt(nonce, ciphertext, tag, empty)); 286 | 287 | Assert.Throws(() => siv.Decrypt((ReadOnlySpan)empty, ciphertext, tag, plaintext, default)); 288 | Assert.Throws(() => siv.Decrypt((ReadOnlySpan)nonce, ciphertext, empty, plaintext, default)); 289 | Assert.Throws(() => siv.Decrypt((ReadOnlySpan)nonce, empty, tag, plaintext, default)); 290 | Assert.Throws(() => siv.Decrypt((ReadOnlySpan)nonce, ciphertext, tag, empty, default)); 291 | 292 | siv.Decrypt(nonce, ciphertext, tag, plaintext); 293 | siv.Dispose(); 294 | 295 | Assert.Throws(() => siv.Encrypt(nonce, plaintext, ciphertext, tag)); 296 | Assert.Throws(() => siv.Encrypt((ReadOnlySpan)nonce, plaintext, ciphertext, tag, default)); 297 | Assert.Throws(() => siv.Decrypt(nonce, ciphertext, tag, plaintext)); 298 | Assert.Throws(() => siv.Decrypt((ReadOnlySpan)nonce, ciphertext, tag, plaintext, default)); 299 | } 300 | } 301 | 302 | private static IEnumerable LoadVectors(string file) 303 | { 304 | var s = File.ReadAllText(file); 305 | var json = JObject.Parse(s); 306 | 307 | foreach (var vector in json["vectors"]) 308 | { 309 | yield return new Vector 310 | { 311 | Plaintext = GetBytes(vector, "plaintext"), 312 | Aad = GetBytes(vector, "aad"), 313 | Key = GetBytes(vector, "key"), 314 | Nonce = GetBytes(vector, "nonce"), 315 | RecordAuthenticationKey = GetBytes(vector, "record_authentication_key"), 316 | RecordEncryptionKey = GetBytes(vector, "record_encryption_key"), 317 | PolyvalInput = GetBytes(vector, "polyval_input"), 318 | PolyvalResult = GetBytes(vector, "polyval_result"), 319 | PolyvalResultXorNonce = GetBytes(vector, "polyval_result_xor_nonce"), 320 | PolyvalResultXorNonceMasked = GetBytes(vector, "polyval_result_xor_nonce_masked"), 321 | Tag = GetBytes(vector, "tag"), 322 | InitialCounter = GetBytes(vector, "initial_counter"), 323 | Result = GetBytes(vector, "result") 324 | }; 325 | } 326 | } 327 | 328 | private static string GetString(JToken token, string property) 329 | { 330 | return (string)token[property] ?? String.Empty; 331 | } 332 | 333 | private static byte[] GetBytes(JToken token, string property) 334 | { 335 | return Hex.Decode(GetString(token, property)); 336 | } 337 | 338 | private static byte[] Concat(byte[] x, byte[] y) 339 | { 340 | var result = new byte[x.Length + y.Length]; 341 | 342 | x.CopyTo(result, 0); 343 | y.CopyTo(result, x.Length); 344 | 345 | return result; 346 | } 347 | } 348 | } 349 | -------------------------------------------------------------------------------- /src/Cryptography/AesGcmSiv.Polyval.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Intrinsics; 3 | using System.Runtime.Intrinsics.X86; 4 | 5 | namespace Cryptography 6 | { 7 | public unsafe partial class AesGcmSiv 8 | { 9 | // PolyvalHorner updates the POLYVAL value in polyval to include length bytes 10 | // of data from input, given the POLYVAL key in hashKey. If the length is not 11 | // divisible by 16, input is padded with zeros until it's a multiple of 16 bytes. 12 | private static void PolyvalHorner(byte* polyval, byte* hashKey, byte* input, int length) 13 | { 14 | if (length == 0) 15 | { 16 | return; 17 | } 18 | 19 | int blocks = Math.DivRem(length, 16, out int remainder); 20 | Vector128 tmp1, tmp2, tmp3, tmp4; 21 | 22 | var poly = Sse.StaticCast(Sse2.SetVector128(0xc2000000, 0, 0, 1)); 23 | var t = Sse.StaticCast(Sse2.LoadVector128(polyval)); 24 | var h = Sse.StaticCast(Sse2.LoadVector128(hashKey)); 25 | 26 | for (int i = 0; i < blocks; ++i) 27 | { 28 | t = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(&input[i * 16]))); 29 | tmp1 = Pclmulqdq.CarrylessMultiply(t, h, 0x00); 30 | tmp4 = Pclmulqdq.CarrylessMultiply(t, h, 0x11); 31 | tmp2 = Pclmulqdq.CarrylessMultiply(t, h, 0x10); 32 | tmp3 = Pclmulqdq.CarrylessMultiply(t, h, 0x01); 33 | tmp2 = Sse2.Xor(tmp2, tmp3); 34 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 35 | tmp2 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 36 | tmp1 = Sse2.Xor(tmp3, tmp1); 37 | tmp4 = Sse2.Xor(tmp4, tmp2); 38 | 39 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 40 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 41 | tmp1 = Sse2.Xor(tmp3, tmp2); 42 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 43 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 44 | tmp1 = Sse2.Xor(tmp3, tmp2); 45 | t = Sse2.Xor(tmp4, tmp1); 46 | } 47 | 48 | if (remainder != 0) 49 | { 50 | byte* b = stackalloc byte[16]; 51 | new Span(input + length - remainder, remainder).CopyTo(new Span(b, 16)); 52 | 53 | t = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(b))); 54 | tmp1 = Pclmulqdq.CarrylessMultiply(t, h, 0x00); 55 | tmp4 = Pclmulqdq.CarrylessMultiply(t, h, 0x11); 56 | tmp2 = Pclmulqdq.CarrylessMultiply(t, h, 0x10); 57 | tmp3 = Pclmulqdq.CarrylessMultiply(t, h, 0x01); 58 | tmp2 = Sse2.Xor(tmp2, tmp3); 59 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 60 | tmp2 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 61 | tmp1 = Sse2.Xor(tmp3, tmp1); 62 | tmp4 = Sse2.Xor(tmp4, tmp2); 63 | 64 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 65 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 66 | tmp1 = Sse2.Xor(tmp3, tmp2); 67 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 68 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 69 | tmp1 = Sse2.Xor(tmp3, tmp2); 70 | t = Sse2.Xor(tmp4, tmp1); 71 | } 72 | 73 | Sse2.Store(polyval, Sse.StaticCast(t)); 74 | } 75 | 76 | // InitPowersTable writes powers 1..size of hashKey to htbl. 77 | private static void InitPowersTable(byte* htbl, int size, byte* hashKey) 78 | { 79 | Vector128 tmp1, tmp2, tmp3, tmp4; 80 | 81 | var poly = Sse.StaticCast(Sse2.SetVector128(0xc2000000, 0, 0, 1)); 82 | var t = Sse.StaticCast(Sse2.LoadVector128(hashKey)); 83 | var h = t; 84 | 85 | Sse2.Store(htbl, Sse.StaticCast(t)); 86 | 87 | for (int i = 1; i < size; ++i) 88 | { 89 | tmp1 = Pclmulqdq.CarrylessMultiply(t, h, 0x00); 90 | tmp4 = Pclmulqdq.CarrylessMultiply(t, h, 0x11); 91 | tmp2 = Pclmulqdq.CarrylessMultiply(t, h, 0x10); 92 | tmp3 = Pclmulqdq.CarrylessMultiply(t, h, 0x01); 93 | tmp2 = Sse2.Xor(tmp2, tmp3); 94 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 95 | tmp2 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 96 | tmp1 = Sse2.Xor(tmp3, tmp1); 97 | tmp4 = Sse2.Xor(tmp4, tmp2); 98 | 99 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 100 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 101 | tmp1 = Sse2.Xor(tmp3, tmp2); 102 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 103 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 104 | tmp1 = Sse2.Xor(tmp3, tmp2); 105 | t = Sse2.Xor(tmp4, tmp1); 106 | Sse2.Store(&htbl[i * 16], Sse.StaticCast(t)); 107 | } 108 | } 109 | 110 | // PolyvalPowersTable updates the POLYVAL value in polyval to include length bytes 111 | // of data from input, given the POLYVAL key in hashKey. It uses the precomputed 112 | // powers of the key given in htbl. If the length is not divisible by 16, input 113 | // is padded with zeros until it's a multiple of 16 bytes. 114 | private static void PolyvalPowersTable(byte* polyval, byte* htbl, byte* input, int length) 115 | { 116 | if (length == 0) 117 | { 118 | return; 119 | } 120 | 121 | int blocks = Math.DivRem(length, 16, out int remainder16); 122 | int remainder128 = length % 128 - remainder16; 123 | Vector128 tmp0, tmp1, tmp2, tmp3, tmp4; 124 | 125 | var xhi = Sse2.SetZeroVector128(); 126 | var poly = Sse.StaticCast(Sse2.SetVector128(0xc2000000, 0, 0, 1)); 127 | var t = Sse.StaticCast(Sse2.LoadVector128(polyval)); 128 | 129 | if (remainder128 != 0) 130 | { 131 | int remainder128Blocks = remainder128 / 16; 132 | blocks -= remainder128Blocks; 133 | 134 | var data = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(input))); 135 | var h = Sse.StaticCast(Sse2.LoadVector128(&htbl[(remainder128Blocks - 1) * 16])); 136 | 137 | tmp2 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 138 | tmp0 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 139 | tmp1 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 140 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 141 | tmp2 = Sse2.Xor(tmp2, tmp3); 142 | 143 | for (int i = 1; i < remainder128Blocks; ++i) 144 | { 145 | data = Sse.StaticCast(Sse2.LoadVector128(&input[i * 16])); 146 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[(remainder128Blocks - i - 1) * 16])); 147 | 148 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 149 | tmp0 = Sse2.Xor(tmp0, tmp3); 150 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 151 | tmp1 = Sse2.Xor(tmp1, tmp3); 152 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 153 | tmp2 = Sse2.Xor(tmp2, tmp3); 154 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 155 | tmp2 = Sse2.Xor(tmp2, tmp3); 156 | } 157 | 158 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 159 | tmp2 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 160 | xhi = Sse2.Xor(tmp3, tmp1); 161 | t = Sse2.Xor(tmp0, tmp2); 162 | } 163 | 164 | if (blocks != 0) 165 | { 166 | var fixedInput = input + remainder128; 167 | 168 | if (remainder128 == 0) 169 | { 170 | var data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[7 * 16])); 171 | var h = Sse.StaticCast(Sse2.LoadVector128(&htbl[0 * 16])); 172 | 173 | tmp2 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 174 | tmp0 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 175 | tmp1 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 176 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 177 | tmp2 = Sse2.Xor(tmp2, tmp3); 178 | 179 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[6 * 16])); 180 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[1 * 16])); 181 | 182 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 183 | tmp2 = Sse2.Xor(tmp2, tmp3); 184 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 185 | tmp0 = Sse2.Xor(tmp0, tmp3); 186 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 187 | tmp1 = Sse2.Xor(tmp1, tmp3); 188 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 189 | tmp2 = Sse2.Xor(tmp2, tmp3); 190 | 191 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[5 * 16])); 192 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[2 * 16])); 193 | 194 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 195 | tmp2 = Sse2.Xor(tmp2, tmp3); 196 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 197 | tmp0 = Sse2.Xor(tmp0, tmp3); 198 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 199 | tmp1 = Sse2.Xor(tmp1, tmp3); 200 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 201 | tmp2 = Sse2.Xor(tmp2, tmp3); 202 | 203 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[4 * 16])); 204 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[3 * 16])); 205 | 206 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 207 | tmp2 = Sse2.Xor(tmp2, tmp3); 208 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 209 | tmp0 = Sse2.Xor(tmp0, tmp3); 210 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 211 | tmp1 = Sse2.Xor(tmp1, tmp3); 212 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 213 | tmp2 = Sse2.Xor(tmp2, tmp3); 214 | 215 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[3 * 16])); 216 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[4 * 16])); 217 | tmp4 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 218 | 219 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 220 | tmp2 = Sse2.Xor(tmp2, tmp3); 221 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 222 | tmp0 = Sse2.Xor(tmp0, tmp3); 223 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 224 | tmp1 = Sse2.Xor(tmp1, tmp3); 225 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 226 | tmp2 = Sse2.Xor(tmp2, tmp3); 227 | 228 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[2 * 16])); 229 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[5 * 16])); 230 | 231 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 232 | tmp2 = Sse2.Xor(tmp2, tmp3); 233 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 234 | tmp0 = Sse2.Xor(tmp0, tmp3); 235 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 236 | tmp1 = Sse2.Xor(tmp1, tmp3); 237 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 238 | tmp2 = Sse2.Xor(tmp2, tmp3); 239 | 240 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[1 * 16])); 241 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[6 * 16])); 242 | 243 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 244 | tmp2 = Sse2.Xor(tmp2, tmp3); 245 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 246 | tmp0 = Sse2.Xor(tmp0, tmp3); 247 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 248 | tmp1 = Sse2.Xor(tmp1, tmp3); 249 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 250 | tmp2 = Sse2.Xor(tmp2, tmp3); 251 | 252 | data = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(&fixedInput[0 * 16]))); 253 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[7 * 16])); 254 | 255 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 256 | tmp2 = Sse2.Xor(tmp2, tmp3); 257 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 258 | tmp0 = Sse2.Xor(tmp0, tmp3); 259 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 260 | tmp1 = Sse2.Xor(tmp1, tmp3); 261 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 262 | tmp2 = Sse2.Xor(tmp2, tmp3); 263 | 264 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 265 | tmp2 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 266 | xhi = Sse2.Xor(tmp3, tmp1); 267 | t = Sse2.Xor(tmp0, tmp2); 268 | } 269 | 270 | for (int i = remainder128 == 0 ? 8 : 0; i < blocks; i += 8) 271 | { 272 | var data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 7) * 16])); 273 | var h = Sse.StaticCast(Sse2.LoadVector128(&htbl[0 * 16])); 274 | 275 | tmp2 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 276 | tmp0 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 277 | tmp1 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 278 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 279 | tmp2 = Sse2.Xor(tmp2, tmp3); 280 | 281 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 6) * 16])); 282 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[1 * 16])); 283 | 284 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 285 | tmp2 = Sse2.Xor(tmp2, tmp3); 286 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 287 | tmp0 = Sse2.Xor(tmp0, tmp3); 288 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 289 | tmp1 = Sse2.Xor(tmp1, tmp3); 290 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 291 | tmp2 = Sse2.Xor(tmp2, tmp3); 292 | 293 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 5) * 16])); 294 | tmp4 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 295 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 296 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[2 * 16])); 297 | 298 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 299 | tmp2 = Sse2.Xor(tmp2, tmp3); 300 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 301 | tmp0 = Sse2.Xor(tmp0, tmp3); 302 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 303 | tmp1 = Sse2.Xor(tmp1, tmp3); 304 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 305 | tmp2 = Sse2.Xor(tmp2, tmp3); 306 | 307 | t = Sse2.Xor(t, tmp4); 308 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 4) * 16])); 309 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[3 * 16])); 310 | 311 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 312 | tmp2 = Sse2.Xor(tmp2, tmp3); 313 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 314 | tmp0 = Sse2.Xor(tmp0, tmp3); 315 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 316 | tmp1 = Sse2.Xor(tmp1, tmp3); 317 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 318 | tmp2 = Sse2.Xor(tmp2, tmp3); 319 | 320 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 3) * 16])); 321 | tmp4 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 322 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 323 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[4 * 16])); 324 | 325 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 326 | tmp2 = Sse2.Xor(tmp2, tmp3); 327 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 328 | tmp0 = Sse2.Xor(tmp0, tmp3); 329 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 330 | tmp1 = Sse2.Xor(tmp1, tmp3); 331 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 332 | tmp2 = Sse2.Xor(tmp2, tmp3); 333 | 334 | t = Sse2.Xor(t, tmp4); 335 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 2) * 16])); 336 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[5 * 16])); 337 | 338 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 339 | tmp2 = Sse2.Xor(tmp2, tmp3); 340 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 341 | tmp0 = Sse2.Xor(tmp0, tmp3); 342 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 343 | tmp1 = Sse2.Xor(tmp1, tmp3); 344 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 345 | tmp2 = Sse2.Xor(tmp2, tmp3); 346 | 347 | t = Sse2.Xor(t, xhi); 348 | data = Sse.StaticCast(Sse2.LoadVector128(&fixedInput[(i + 1) * 16])); 349 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[6 * 16])); 350 | 351 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 352 | tmp2 = Sse2.Xor(tmp2, tmp3); 353 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 354 | tmp0 = Sse2.Xor(tmp0, tmp3); 355 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 356 | tmp1 = Sse2.Xor(tmp1, tmp3); 357 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 358 | tmp2 = Sse2.Xor(tmp2, tmp3); 359 | 360 | data = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(&fixedInput[i * 16]))); 361 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[7 * 16])); 362 | 363 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 364 | tmp2 = Sse2.Xor(tmp2, tmp3); 365 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 366 | tmp0 = Sse2.Xor(tmp0, tmp3); 367 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 368 | tmp1 = Sse2.Xor(tmp1, tmp3); 369 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 370 | tmp2 = Sse2.Xor(tmp2, tmp3); 371 | 372 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 373 | tmp2 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 374 | xhi = Sse2.Xor(tmp3, tmp1); 375 | t = Sse2.Xor(tmp0, tmp2); 376 | } 377 | } 378 | 379 | if (blocks != 0 || remainder128 != 0) 380 | { 381 | tmp3 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 382 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 383 | t = Sse2.Xor(tmp3, t); 384 | tmp3 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 385 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 386 | t = Sse2.Xor(tmp3, t); 387 | t = Sse2.Xor(xhi, t); 388 | } 389 | 390 | if (remainder16 != 0) 391 | { 392 | byte* b = stackalloc byte[16]; 393 | new Span(input + length - remainder16, remainder16).CopyTo(new Span(b, 16)); 394 | 395 | var data = Sse2.Xor(t, Sse.StaticCast(Sse2.LoadVector128(b))); 396 | var h = Sse.StaticCast(Sse2.LoadVector128(htbl)); 397 | 398 | tmp2 = Pclmulqdq.CarrylessMultiply(data, h, 0x01); 399 | tmp0 = Pclmulqdq.CarrylessMultiply(data, h, 0x00); 400 | tmp1 = Pclmulqdq.CarrylessMultiply(data, h, 0x11); 401 | tmp3 = Pclmulqdq.CarrylessMultiply(data, h, 0x10); 402 | tmp2 = Sse2.Xor(tmp2, tmp3); 403 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 404 | tmp2 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 405 | xhi = Sse2.Xor(tmp3, tmp1); 406 | t = Sse2.Xor(tmp0, tmp2); 407 | 408 | tmp3 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 409 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 410 | t = Sse2.Xor(tmp3, t); 411 | tmp3 = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 412 | t = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 413 | t = Sse2.Xor(tmp3, t); 414 | t = Sse2.Xor(xhi, t); 415 | } 416 | 417 | Sse2.Store(polyval, Sse.StaticCast(t)); 418 | } 419 | } 420 | } 421 | -------------------------------------------------------------------------------- /src/Cryptography/AesGcmSiv.Decrypt.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Intrinsics; 3 | using System.Runtime.Intrinsics.X86; 4 | using Aes = System.Runtime.Intrinsics.X86.Aes; 5 | 6 | namespace Cryptography 7 | { 8 | public unsafe partial class AesGcmSiv 9 | { 10 | // DecryptPowersTable decrypts ctLen bytes from ct and writes them to pt. While 11 | // decrypting, it updates the POLYVAL value in polyval. In order to decrypt and 12 | // update the POLYVAL value, it uses the expanded key from ks and the table of 13 | // powers in htbl. Decryption processes 6 blocks of data in parallel. 14 | private static void DecryptPowersTable(byte* ct, int ctLen, byte* pt, byte* polyval, byte* htbl, byte* tag, byte* ks) 15 | { 16 | Vector128 sCtr1, sCtr2, sCtr3, sCtr4, sCtr5, sCtr6, tmp0, tmp1, tmp2, tmp3, tmp4, h; 17 | 18 | var poly = Sse.StaticCast(Sse2.SetVector128(0xc2000000, 0, 0, 1)); 19 | var t = Sse.StaticCast(Sse2.LoadVector128(polyval)); 20 | 21 | var orMask = Sse.StaticCast(Sse2.SetVector128(0x80000000, 0, 0, 0)); 22 | var ctr = Sse2.Or(Sse2.LoadVector128(tag), orMask); 23 | 24 | var one = Sse2.SetVector128(0, 0, 0, 1); 25 | var two = Sse2.SetVector128(0, 0, 0, 2); 26 | 27 | int blocks = 0; 28 | 29 | if (ctLen >= 96) 30 | { 31 | var ctr1 = ctr; 32 | var ctr2 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 33 | var ctr3 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), two)); 34 | var ctr4 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr3), one)); 35 | var ctr5 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr3), two)); 36 | var ctr6 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr5), one)); 37 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr5), two)); 38 | 39 | var key = Sse2.LoadVector128(ks); 40 | ctr1 = Sse2.Xor(ctr1, key); 41 | ctr2 = Sse2.Xor(ctr2, key); 42 | ctr3 = Sse2.Xor(ctr3, key); 43 | ctr4 = Sse2.Xor(ctr4, key); 44 | ctr5 = Sse2.Xor(ctr5, key); 45 | ctr6 = Sse2.Xor(ctr6, key); 46 | 47 | for (int i = 1; i < 14; ++i) 48 | { 49 | key = Sse2.LoadVector128(&ks[i * 16]); 50 | ctr1 = Aes.Encrypt(ctr1, key); 51 | ctr2 = Aes.Encrypt(ctr2, key); 52 | ctr3 = Aes.Encrypt(ctr3, key); 53 | ctr4 = Aes.Encrypt(ctr4, key); 54 | ctr5 = Aes.Encrypt(ctr5, key); 55 | ctr6 = Aes.Encrypt(ctr6, key); 56 | } 57 | 58 | key = Sse2.LoadVector128(&ks[14 * 16]); 59 | ctr1 = Aes.EncryptLast(ctr1, key); 60 | ctr2 = Aes.EncryptLast(ctr2, key); 61 | ctr3 = Aes.EncryptLast(ctr3, key); 62 | ctr4 = Aes.EncryptLast(ctr4, key); 63 | ctr5 = Aes.EncryptLast(ctr5, key); 64 | ctr6 = Aes.EncryptLast(ctr6, key); 65 | 66 | ctr1 = Sse2.Xor(ctr1, Sse2.LoadVector128(&ct[0 * 16])); 67 | ctr2 = Sse2.Xor(ctr2, Sse2.LoadVector128(&ct[1 * 16])); 68 | ctr3 = Sse2.Xor(ctr3, Sse2.LoadVector128(&ct[2 * 16])); 69 | ctr4 = Sse2.Xor(ctr4, Sse2.LoadVector128(&ct[3 * 16])); 70 | ctr5 = Sse2.Xor(ctr5, Sse2.LoadVector128(&ct[4 * 16])); 71 | ctr6 = Sse2.Xor(ctr6, Sse2.LoadVector128(&ct[5 * 16])); 72 | 73 | Sse2.Store(&pt[0 * 16], ctr1); 74 | Sse2.Store(&pt[1 * 16], ctr2); 75 | Sse2.Store(&pt[2 * 16], ctr3); 76 | Sse2.Store(&pt[3 * 16], ctr4); 77 | Sse2.Store(&pt[4 * 16], ctr5); 78 | Sse2.Store(&pt[5 * 16], ctr6); 79 | 80 | ctLen -= 96; 81 | blocks += 6; 82 | 83 | while (ctLen >= 96) 84 | { 85 | sCtr6 = Sse.StaticCast(ctr6); 86 | sCtr5 = Sse.StaticCast(ctr5); 87 | sCtr4 = Sse.StaticCast(ctr4); 88 | sCtr3 = Sse.StaticCast(ctr3); 89 | sCtr2 = Sse.StaticCast(ctr2); 90 | sCtr1 = Sse.StaticCast(ctr1); 91 | 92 | ctr1 = ctr; 93 | ctr2 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 94 | ctr3 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), two)); 95 | ctr4 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr3), one)); 96 | ctr5 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr3), two)); 97 | ctr6 = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr5), one)); 98 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr5), two)); 99 | 100 | key = Sse2.LoadVector128(ks); 101 | ctr1 = Sse2.Xor(ctr1, key); 102 | ctr2 = Sse2.Xor(ctr2, key); 103 | ctr3 = Sse2.Xor(ctr3, key); 104 | ctr4 = Sse2.Xor(ctr4, key); 105 | ctr5 = Sse2.Xor(ctr5, key); 106 | ctr6 = Sse2.Xor(ctr6, key); 107 | 108 | tmp3 = Sse.StaticCast(Sse2.LoadVector128(htbl)); 109 | tmp1 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x11); 110 | tmp2 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x00); 111 | tmp0 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x01); 112 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x10); 113 | tmp0 = Sse2.Xor(tmp3, tmp0); 114 | 115 | key = Sse2.LoadVector128(&ks[1 * 16]); 116 | ctr1 = Aes.Encrypt(ctr1, key); 117 | ctr2 = Aes.Encrypt(ctr2, key); 118 | ctr3 = Aes.Encrypt(ctr3, key); 119 | ctr4 = Aes.Encrypt(ctr4, key); 120 | ctr5 = Aes.Encrypt(ctr5, key); 121 | ctr6 = Aes.Encrypt(ctr6, key); 122 | 123 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[1 * 16])); 124 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x10); 125 | tmp0 = Sse2.Xor(tmp0, tmp3); 126 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x11); 127 | tmp1 = Sse2.Xor(tmp1, tmp3); 128 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x00); 129 | tmp2 = Sse2.Xor(tmp2, tmp3); 130 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x01); 131 | tmp0 = Sse2.Xor(tmp0, tmp3); 132 | 133 | key = Sse2.LoadVector128(&ks[2 * 16]); 134 | ctr1 = Aes.Encrypt(ctr1, key); 135 | ctr2 = Aes.Encrypt(ctr2, key); 136 | ctr3 = Aes.Encrypt(ctr3, key); 137 | ctr4 = Aes.Encrypt(ctr4, key); 138 | ctr5 = Aes.Encrypt(ctr5, key); 139 | ctr6 = Aes.Encrypt(ctr6, key); 140 | 141 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[2 * 16])); 142 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x10); 143 | tmp0 = Sse2.Xor(tmp0, tmp3); 144 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x11); 145 | tmp1 = Sse2.Xor(tmp1, tmp3); 146 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x00); 147 | tmp2 = Sse2.Xor(tmp2, tmp3); 148 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x01); 149 | tmp0 = Sse2.Xor(tmp0, tmp3); 150 | 151 | key = Sse2.LoadVector128(&ks[3 * 16]); 152 | ctr1 = Aes.Encrypt(ctr1, key); 153 | ctr2 = Aes.Encrypt(ctr2, key); 154 | ctr3 = Aes.Encrypt(ctr3, key); 155 | ctr4 = Aes.Encrypt(ctr4, key); 156 | ctr5 = Aes.Encrypt(ctr5, key); 157 | ctr6 = Aes.Encrypt(ctr6, key); 158 | 159 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[3 * 16])); 160 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x10); 161 | tmp0 = Sse2.Xor(tmp0, tmp3); 162 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x11); 163 | tmp1 = Sse2.Xor(tmp1, tmp3); 164 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x00); 165 | tmp2 = Sse2.Xor(tmp2, tmp3); 166 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x01); 167 | tmp0 = Sse2.Xor(tmp0, tmp3); 168 | 169 | key = Sse2.LoadVector128(&ks[4 * 16]); 170 | ctr1 = Aes.Encrypt(ctr1, key); 171 | ctr2 = Aes.Encrypt(ctr2, key); 172 | ctr3 = Aes.Encrypt(ctr3, key); 173 | ctr4 = Aes.Encrypt(ctr4, key); 174 | ctr5 = Aes.Encrypt(ctr5, key); 175 | ctr6 = Aes.Encrypt(ctr6, key); 176 | 177 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[4 * 16])); 178 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x10); 179 | tmp0 = Sse2.Xor(tmp0, tmp3); 180 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x11); 181 | tmp1 = Sse2.Xor(tmp1, tmp3); 182 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x00); 183 | tmp2 = Sse2.Xor(tmp2, tmp3); 184 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x01); 185 | tmp0 = Sse2.Xor(tmp0, tmp3); 186 | 187 | key = Sse2.LoadVector128(&ks[5 * 16]); 188 | ctr1 = Aes.Encrypt(ctr1, key); 189 | ctr2 = Aes.Encrypt(ctr2, key); 190 | ctr3 = Aes.Encrypt(ctr3, key); 191 | ctr4 = Aes.Encrypt(ctr4, key); 192 | ctr5 = Aes.Encrypt(ctr5, key); 193 | ctr6 = Aes.Encrypt(ctr6, key); 194 | 195 | key = Sse2.LoadVector128(&ks[6 * 16]); 196 | ctr1 = Aes.Encrypt(ctr1, key); 197 | ctr2 = Aes.Encrypt(ctr2, key); 198 | ctr3 = Aes.Encrypt(ctr3, key); 199 | ctr4 = Aes.Encrypt(ctr4, key); 200 | ctr5 = Aes.Encrypt(ctr5, key); 201 | ctr6 = Aes.Encrypt(ctr6, key); 202 | 203 | key = Sse2.LoadVector128(&ks[7 * 16]); 204 | ctr1 = Aes.Encrypt(ctr1, key); 205 | ctr2 = Aes.Encrypt(ctr2, key); 206 | ctr3 = Aes.Encrypt(ctr3, key); 207 | ctr4 = Aes.Encrypt(ctr4, key); 208 | ctr5 = Aes.Encrypt(ctr5, key); 209 | ctr6 = Aes.Encrypt(ctr6, key); 210 | 211 | sCtr1 = Sse2.Xor(t, sCtr1); 212 | tmp4 = Sse.StaticCast(Sse2.LoadVector128(&htbl[5 * 16])); 213 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x01); 214 | tmp0 = Sse2.Xor(tmp3, tmp0); 215 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x11); 216 | tmp1 = Sse2.Xor(tmp3, tmp1); 217 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x00); 218 | tmp2 = Sse2.Xor(tmp3, tmp2); 219 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x10); 220 | tmp0 = Sse2.Xor(tmp3, tmp0); 221 | 222 | key = Sse2.LoadVector128(&ks[8 * 16]); 223 | ctr1 = Aes.Encrypt(ctr1, key); 224 | ctr2 = Aes.Encrypt(ctr2, key); 225 | ctr3 = Aes.Encrypt(ctr3, key); 226 | ctr4 = Aes.Encrypt(ctr4, key); 227 | ctr5 = Aes.Encrypt(ctr5, key); 228 | ctr6 = Aes.Encrypt(ctr6, key); 229 | 230 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp0, 8); 231 | tmp4 = Sse2.Xor(tmp3, tmp1); 232 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp0, 8); 233 | t = Sse2.Xor(tmp3, tmp2); 234 | 235 | key = Sse2.LoadVector128(&ks[9 * 16]); 236 | ctr1 = Aes.Encrypt(ctr1, key); 237 | ctr2 = Aes.Encrypt(ctr2, key); 238 | ctr3 = Aes.Encrypt(ctr3, key); 239 | ctr4 = Aes.Encrypt(ctr4, key); 240 | ctr5 = Aes.Encrypt(ctr5, key); 241 | ctr6 = Aes.Encrypt(ctr6, key); 242 | 243 | tmp1 = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 244 | t = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 245 | t = Sse2.Xor(tmp1, t); 246 | 247 | key = Sse2.LoadVector128(&ks[10 * 16]); 248 | ctr1 = Aes.Encrypt(ctr1, key); 249 | ctr2 = Aes.Encrypt(ctr2, key); 250 | ctr3 = Aes.Encrypt(ctr3, key); 251 | ctr4 = Aes.Encrypt(ctr4, key); 252 | ctr5 = Aes.Encrypt(ctr5, key); 253 | ctr6 = Aes.Encrypt(ctr6, key); 254 | 255 | key = Sse2.LoadVector128(&ks[11 * 16]); 256 | ctr1 = Aes.Encrypt(ctr1, key); 257 | ctr2 = Aes.Encrypt(ctr2, key); 258 | ctr3 = Aes.Encrypt(ctr3, key); 259 | ctr4 = Aes.Encrypt(ctr4, key); 260 | ctr5 = Aes.Encrypt(ctr5, key); 261 | ctr6 = Aes.Encrypt(ctr6, key); 262 | 263 | key = Sse2.LoadVector128(&ks[12 * 16]); 264 | ctr1 = Aes.Encrypt(ctr1, key); 265 | ctr2 = Aes.Encrypt(ctr2, key); 266 | ctr3 = Aes.Encrypt(ctr3, key); 267 | ctr4 = Aes.Encrypt(ctr4, key); 268 | ctr5 = Aes.Encrypt(ctr5, key); 269 | ctr6 = Aes.Encrypt(ctr6, key); 270 | 271 | key = Sse2.LoadVector128(&ks[13 * 16]); 272 | ctr1 = Aes.Encrypt(ctr1, key); 273 | ctr2 = Aes.Encrypt(ctr2, key); 274 | ctr3 = Aes.Encrypt(ctr3, key); 275 | ctr4 = Aes.Encrypt(ctr4, key); 276 | ctr5 = Aes.Encrypt(ctr5, key); 277 | ctr6 = Aes.Encrypt(ctr6, key); 278 | 279 | key = Sse2.LoadVector128(&ks[14 * 16]); 280 | ctr1 = Aes.EncryptLast(ctr1, key); 281 | ctr2 = Aes.EncryptLast(ctr2, key); 282 | ctr3 = Aes.EncryptLast(ctr3, key); 283 | ctr4 = Aes.EncryptLast(ctr4, key); 284 | ctr5 = Aes.EncryptLast(ctr5, key); 285 | ctr6 = Aes.EncryptLast(ctr6, key); 286 | 287 | ctr1 = Sse2.Xor(ctr1, Sse2.LoadVector128(&ct[(blocks + 0) * 16])); 288 | ctr2 = Sse2.Xor(ctr2, Sse2.LoadVector128(&ct[(blocks + 1) * 16])); 289 | ctr3 = Sse2.Xor(ctr3, Sse2.LoadVector128(&ct[(blocks + 2) * 16])); 290 | ctr4 = Sse2.Xor(ctr4, Sse2.LoadVector128(&ct[(blocks + 3) * 16])); 291 | ctr5 = Sse2.Xor(ctr5, Sse2.LoadVector128(&ct[(blocks + 4) * 16])); 292 | ctr6 = Sse2.Xor(ctr6, Sse2.LoadVector128(&ct[(blocks + 5) * 16])); 293 | 294 | tmp1 = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 295 | t = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 296 | t = Sse2.Xor(tmp1, t); 297 | t = Sse2.Xor(tmp4, t); 298 | 299 | Sse2.Store(&pt[(blocks + 0) * 16], ctr1); 300 | Sse2.Store(&pt[(blocks + 1) * 16], ctr2); 301 | Sse2.Store(&pt[(blocks + 2) * 16], ctr3); 302 | Sse2.Store(&pt[(blocks + 3) * 16], ctr4); 303 | Sse2.Store(&pt[(blocks + 4) * 16], ctr5); 304 | Sse2.Store(&pt[(blocks + 5) * 16], ctr6); 305 | 306 | ctLen -= 96; 307 | blocks += 6; 308 | } 309 | 310 | sCtr6 = Sse.StaticCast(ctr6); 311 | sCtr5 = Sse.StaticCast(ctr5); 312 | sCtr4 = Sse.StaticCast(ctr4); 313 | sCtr3 = Sse.StaticCast(ctr3); 314 | sCtr2 = Sse.StaticCast(ctr2); 315 | sCtr1 = Sse.StaticCast(ctr1); 316 | 317 | tmp3 = Sse.StaticCast(Sse2.LoadVector128(htbl)); 318 | tmp0 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x10); 319 | tmp1 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x11); 320 | tmp2 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x00); 321 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr6, tmp3, 0x01); 322 | tmp0 = Sse2.Xor(tmp3, tmp0); 323 | 324 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[1 * 16])); 325 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x10); 326 | tmp0 = Sse2.Xor(tmp0, tmp3); 327 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x11); 328 | tmp1 = Sse2.Xor(tmp1, tmp3); 329 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x00); 330 | tmp2 = Sse2.Xor(tmp2, tmp3); 331 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr5, h, 0x01); 332 | tmp0 = Sse2.Xor(tmp0, tmp3); 333 | 334 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[2 * 16])); 335 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x10); 336 | tmp0 = Sse2.Xor(tmp0, tmp3); 337 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x11); 338 | tmp1 = Sse2.Xor(tmp1, tmp3); 339 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x00); 340 | tmp2 = Sse2.Xor(tmp2, tmp3); 341 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr4, h, 0x01); 342 | tmp0 = Sse2.Xor(tmp0, tmp3); 343 | 344 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[3 * 16])); 345 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x10); 346 | tmp0 = Sse2.Xor(tmp0, tmp3); 347 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x11); 348 | tmp1 = Sse2.Xor(tmp1, tmp3); 349 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x00); 350 | tmp2 = Sse2.Xor(tmp2, tmp3); 351 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr3, h, 0x01); 352 | tmp0 = Sse2.Xor(tmp0, tmp3); 353 | 354 | h = Sse.StaticCast(Sse2.LoadVector128(&htbl[4 * 16])); 355 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x10); 356 | tmp0 = Sse2.Xor(tmp0, tmp3); 357 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x11); 358 | tmp1 = Sse2.Xor(tmp1, tmp3); 359 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x00); 360 | tmp2 = Sse2.Xor(tmp2, tmp3); 361 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr2, h, 0x01); 362 | tmp0 = Sse2.Xor(tmp0, tmp3); 363 | 364 | sCtr1 = Sse2.Xor(t, sCtr1); 365 | tmp4 = Sse.StaticCast(Sse2.LoadVector128(&htbl[5 * 16])); 366 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x11); 367 | tmp1 = Sse2.Xor(tmp3, tmp1); 368 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x00); 369 | tmp2 = Sse2.Xor(tmp3, tmp2); 370 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x10); 371 | tmp0 = Sse2.Xor(tmp3, tmp0); 372 | tmp3 = Pclmulqdq.CarrylessMultiply(sCtr1, tmp4, 0x01); 373 | tmp0 = Sse2.Xor(tmp3, tmp0); 374 | 375 | tmp3 = Sse2.ShiftRightLogical128BitLane(tmp0, 8); 376 | tmp4 = Sse2.Xor(tmp3, tmp1); 377 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp0, 8); 378 | t = Sse2.Xor(tmp3, tmp2); 379 | 380 | tmp1 = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 381 | t = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 382 | t = Sse2.Xor(tmp1, t); 383 | tmp1 = Sse.StaticCast(Ssse3.AlignRight(Sse.StaticCast(t), Sse.StaticCast(t), 8)); 384 | t = Pclmulqdq.CarrylessMultiply(t, poly, 0x10); 385 | t = Sse2.Xor(tmp1, t); 386 | t = Sse2.Xor(tmp4, t); 387 | } 388 | 389 | h = Sse.StaticCast(Sse2.LoadVector128(htbl)); 390 | 391 | while (ctLen >= 16) 392 | { 393 | var tmp = ctr; 394 | ctr = Sse.StaticCast(Sse2.Add(Sse.StaticCast(ctr), one)); 395 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(ks)); 396 | 397 | for (int i = 1; i < 14; ++i) 398 | { 399 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[i * 16])); 400 | } 401 | 402 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 403 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(&ct[blocks * 16])); 404 | Sse2.Store(&pt[blocks * 16], tmp); 405 | 406 | t = Sse2.Xor(Sse.StaticCast(tmp), t); 407 | tmp1 = Pclmulqdq.CarrylessMultiply(t, h, 0x00); 408 | tmp4 = Pclmulqdq.CarrylessMultiply(t, h, 0x11); 409 | tmp2 = Pclmulqdq.CarrylessMultiply(t, h, 0x10); 410 | tmp3 = Pclmulqdq.CarrylessMultiply(t, h, 0x01); 411 | tmp2 = Sse2.Xor(tmp3, tmp2); 412 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 413 | tmp2 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 414 | tmp1 = Sse2.Xor(tmp1, tmp3); 415 | tmp4 = Sse2.Xor(tmp2, tmp4); 416 | 417 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 418 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 419 | tmp1 = Sse2.Xor(tmp2, tmp3); 420 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 421 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 422 | tmp1 = Sse2.Xor(tmp2, tmp3); 423 | t = Sse2.Xor(tmp1, tmp4); 424 | 425 | ctLen -= 16; 426 | ++blocks; 427 | } 428 | 429 | if (ctLen > 0) 430 | { 431 | byte* b = stackalloc byte[16]; 432 | new Span(ct + blocks * 16, ctLen).CopyTo(new Span(b, 16)); 433 | var tmp = Sse2.Xor(ctr, Sse2.LoadVector128(ks)); 434 | 435 | for (int i = 1; i < 14; ++i) 436 | { 437 | tmp = Aes.Encrypt(tmp, Sse2.LoadVector128(&ks[i * 16])); 438 | } 439 | 440 | tmp = Aes.EncryptLast(tmp, Sse2.LoadVector128(&ks[14 * 16])); 441 | tmp = Sse2.Xor(tmp, Sse2.LoadVector128(b)); 442 | Sse2.Store(b, tmp); 443 | 444 | new Span(b, ctLen).CopyTo(new Span(&pt[blocks * 16], ctLen)); 445 | new Span(b + ctLen, 16 - ctLen).Clear(); 446 | 447 | t = Sse2.Xor(Sse.StaticCast(Sse2.LoadVector128(b)), t); 448 | tmp1 = Pclmulqdq.CarrylessMultiply(t, h, 0x00); 449 | tmp4 = Pclmulqdq.CarrylessMultiply(t, h, 0x11); 450 | tmp2 = Pclmulqdq.CarrylessMultiply(t, h, 0x10); 451 | tmp3 = Pclmulqdq.CarrylessMultiply(t, h, 0x01); 452 | tmp2 = Sse2.Xor(tmp3, tmp2); 453 | tmp3 = Sse2.ShiftLeftLogical128BitLane(tmp2, 8); 454 | tmp2 = Sse2.ShiftRightLogical128BitLane(tmp2, 8); 455 | tmp1 = Sse2.Xor(tmp1, tmp3); 456 | tmp4 = Sse2.Xor(tmp2, tmp4); 457 | 458 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 459 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 460 | tmp1 = Sse2.Xor(tmp2, tmp3); 461 | tmp2 = Pclmulqdq.CarrylessMultiply(tmp1, poly, 0x10); 462 | tmp3 = Sse.StaticCast(Sse2.Shuffle(Sse.StaticCast(tmp1), 78)); 463 | tmp1 = Sse2.Xor(tmp2, tmp3); 464 | t = Sse2.Xor(tmp1, tmp4); 465 | } 466 | 467 | Sse2.Store(polyval, Sse.StaticCast(t)); 468 | } 469 | } 470 | } 471 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Vectors/aes-128-gcm-siv.json: -------------------------------------------------------------------------------- 1 | { 2 | "vectors": [ 3 | { 4 | "plaintext": "", 5 | "aad": "", 6 | "key": "01000000000000000000000000000000", 7 | "nonce": "030000000000000000000000", 8 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 9 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 10 | "polyval_input": "00000000000000000000000000000000", 11 | "polyval_result": "00000000000000000000000000000000", 12 | "polyval_result_xor_nonce": "03000000000000000000000000000000", 13 | "polyval_result_xor_nonce_masked": "03000000000000000000000000000000", 14 | "tag": "dc20e2d83f25705bb49e439eca56de25", 15 | "initial_counter": "dc20e2d83f25705bb49e439eca56dea5", 16 | "result": "dc20e2d83f25705bb49e439eca56de25" 17 | }, 18 | { 19 | "plaintext": "0100000000000000", 20 | "aad": "", 21 | "key": "01000000000000000000000000000000", 22 | "nonce": "030000000000000000000000", 23 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 24 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 25 | "polyval_input": "0100000000000000000000000000000000000000000000004000000000000000", 26 | "polyval_result": "eb93b7740962c5e49d2a90a7dc5cec74", 27 | "polyval_result_xor_nonce": "e893b7740962c5e49d2a90a7dc5cec74", 28 | "polyval_result_xor_nonce_masked": "e893b7740962c5e49d2a90a7dc5cec74", 29 | "tag": "578782fff6013b815b287c22493a364c", 30 | "initial_counter": "578782fff6013b815b287c22493a36cc", 31 | "result": "b5d839330ac7b786578782fff6013b815b287c22493a364c" 32 | }, 33 | { 34 | "plaintext": "010000000000000000000000", 35 | "aad": "", 36 | "key": "01000000000000000000000000000000", 37 | "nonce": "030000000000000000000000", 38 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 39 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 40 | "polyval_input": "0100000000000000000000000000000000000000000000006000000000000000", 41 | "polyval_result": "48eb6c6c5a2dbe4a1dde508fee06361b", 42 | "polyval_result_xor_nonce": "4beb6c6c5a2dbe4a1dde508fee06361b", 43 | "polyval_result_xor_nonce_masked": "4beb6c6c5a2dbe4a1dde508fee06361b", 44 | "tag": "a4978db357391a0bc4fdec8b0d106639", 45 | "initial_counter": "a4978db357391a0bc4fdec8b0d1066b9", 46 | "result": "7323ea61d05932260047d942a4978db357391a0bc4fdec8b0d106639" 47 | }, 48 | { 49 | "plaintext": "01000000000000000000000000000000", 50 | "aad": "", 51 | "key": "01000000000000000000000000000000", 52 | "nonce": "030000000000000000000000", 53 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 54 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 55 | "polyval_input": "0100000000000000000000000000000000000000000000008000000000000000", 56 | "polyval_result": "20806c26e3c1de019e111255708031d6", 57 | "polyval_result_xor_nonce": "23806c26e3c1de019e111255708031d6", 58 | "polyval_result_xor_nonce_masked": "23806c26e3c1de019e11125570803156", 59 | "tag": "303aaf90f6fe21199c6068577437a0c4", 60 | "initial_counter": "303aaf90f6fe21199c6068577437a0c4", 61 | "result": "743f7c8077ab25f8624e2e948579cf77303aaf90f6fe21199c6068577437a0c4" 62 | }, 63 | { 64 | "plaintext": "0100000000000000000000000000000002000000000000000000000000000000", 65 | "aad": "", 66 | "key": "01000000000000000000000000000000", 67 | "nonce": "030000000000000000000000", 68 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 69 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 70 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000000000000000000000001000000000000", 71 | "polyval_result": "ce6edc9a50b36d9a98986bbf6a261c3b", 72 | "polyval_result_xor_nonce": "cd6edc9a50b36d9a98986bbf6a261c3b", 73 | "polyval_result_xor_nonce_masked": "cd6edc9a50b36d9a98986bbf6a261c3b", 74 | "tag": "1a8e45dcd4578c667cd86847bf6155ff", 75 | "initial_counter": "1a8e45dcd4578c667cd86847bf6155ff", 76 | "result": "84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a94451a8e45dcd4578c667cd86847bf6155ff" 77 | }, 78 | { 79 | "plaintext": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000", 80 | "aad": "", 81 | "key": "01000000000000000000000000000000", 82 | "nonce": "030000000000000000000000", 83 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 84 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 85 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000000000000000000008001000000000000", 86 | "polyval_result": "81388746bc22d26b2abc3dcb15754222", 87 | "polyval_result_xor_nonce": "82388746bc22d26b2abc3dcb15754222", 88 | "polyval_result_xor_nonce_masked": "82388746bc22d26b2abc3dcb15754222", 89 | "tag": "5e6e311dbf395d35b0fe39c2714388f8", 90 | "initial_counter": "5e6e311dbf395d35b0fe39c2714388f8", 91 | "result": "3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b5e6e311dbf395d35b0fe39c2714388f8" 92 | }, 93 | { 94 | "plaintext": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000", 95 | "aad": "", 96 | "key": "01000000000000000000000000000000", 97 | "nonce": "030000000000000000000000", 98 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 99 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 100 | "polyval_input": "0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000000000000000000000002000000000000", 101 | "polyval_result": "1e39b6d3344d348f6044f89935d1cf78", 102 | "polyval_result_xor_nonce": "1d39b6d3344d348f6044f89935d1cf78", 103 | "polyval_result_xor_nonce_masked": "1d39b6d3344d348f6044f89935d1cf78", 104 | "tag": "8a263dd317aa88d56bdf3936dba75bb8", 105 | "initial_counter": "8a263dd317aa88d56bdf3936dba75bb8", 106 | "result": "2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f8a263dd317aa88d56bdf3936dba75bb8" 107 | }, 108 | { 109 | "plaintext": "0200000000000000", 110 | "aad": "01", 111 | "key": "01000000000000000000000000000000", 112 | "nonce": "030000000000000000000000", 113 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 114 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 115 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000004000000000000000", 116 | "polyval_result": "b26781e7e2c1376f96bec195f3709b2a", 117 | "polyval_result_xor_nonce": "b16781e7e2c1376f96bec195f3709b2a", 118 | "polyval_result_xor_nonce_masked": "b16781e7e2c1376f96bec195f3709b2a", 119 | "tag": "3b0a1a2560969cdf790d99759abd1508", 120 | "initial_counter": "3b0a1a2560969cdf790d99759abd1588", 121 | "result": "1e6daba35669f4273b0a1a2560969cdf790d99759abd1508" 122 | }, 123 | { 124 | "plaintext": "020000000000000000000000", 125 | "aad": "01", 126 | "key": "01000000000000000000000000000000", 127 | "nonce": "030000000000000000000000", 128 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 129 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 130 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000006000000000000000", 131 | "polyval_result": "111f5affb18e4cc1164a01bdc12a4145", 132 | "polyval_result_xor_nonce": "121f5affb18e4cc1164a01bdc12a4145", 133 | "polyval_result_xor_nonce_masked": "121f5affb18e4cc1164a01bdc12a4145", 134 | "tag": "08299c5102745aaa3a0c469fad9e075a", 135 | "initial_counter": "08299c5102745aaa3a0c469fad9e07da", 136 | "result": "296c7889fd99f41917f4462008299c5102745aaa3a0c469fad9e075a" 137 | }, 138 | { 139 | "plaintext": "02000000000000000000000000000000", 140 | "aad": "01", 141 | "key": "01000000000000000000000000000000", 142 | "nonce": "030000000000000000000000", 143 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 144 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 145 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000008000000000000000", 146 | "polyval_result": "79745ab508622c8a958543675fac4688", 147 | "polyval_result_xor_nonce": "7a745ab508622c8a958543675fac4688", 148 | "polyval_result_xor_nonce_masked": "7a745ab508622c8a958543675fac4608", 149 | "tag": "8f8936ec039e4e4bb97ebd8c4457441f", 150 | "initial_counter": "8f8936ec039e4e4bb97ebd8c4457449f", 151 | "result": "e2b0c5da79a901c1745f700525cb335b8f8936ec039e4e4bb97ebd8c4457441f" 152 | }, 153 | { 154 | "plaintext": "0200000000000000000000000000000003000000000000000000000000000000", 155 | "aad": "01", 156 | "key": "01000000000000000000000000000000", 157 | "nonce": "030000000000000000000000", 158 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 159 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 160 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000008000000000000000001000000000000", 161 | "polyval_result": "2ce7daaf7c89490822051255b12eca6b", 162 | "polyval_result_xor_nonce": "2fe7daaf7c89490822051255b12eca6b", 163 | "polyval_result_xor_nonce_masked": "2fe7daaf7c89490822051255b12eca6b", 164 | "tag": "e6af6a7f87287da059a71684ed3498e1", 165 | "initial_counter": "e6af6a7f87287da059a71684ed3498e1", 166 | "result": "620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71e6af6a7f87287da059a71684ed3498e1" 167 | }, 168 | { 169 | "plaintext": "020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000", 170 | "aad": "01", 171 | "key": "01000000000000000000000000000000", 172 | "nonce": "030000000000000000000000", 173 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 174 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 175 | "polyval_input": "0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000008000000000000008001000000000000", 176 | "polyval_result": "9ca987715d69c1786711dfcd22f830fc", 177 | "polyval_result_xor_nonce": "9fa987715d69c1786711dfcd22f830fc", 178 | "polyval_result_xor_nonce_masked": "9fa987715d69c1786711dfcd22f8307c", 179 | "tag": "6a8cc3865f76897c2e4b245cf31c51f2", 180 | "initial_counter": "6a8cc3865f76897c2e4b245cf31c51f2", 181 | "result": "50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e6a8cc3865f76897c2e4b245cf31c51f2" 182 | }, 183 | { 184 | "plaintext": "02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000", 185 | "aad": "01", 186 | "key": "01000000000000000000000000000000", 187 | "nonce": "030000000000000000000000", 188 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 189 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 190 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000000500000000000000000000000000000008000000000000000002000000000000", 191 | "polyval_result": "ffcd05d5770f34ad9267f0a59994b15a", 192 | "polyval_result_xor_nonce": "fccd05d5770f34ad9267f0a59994b15a", 193 | "polyval_result_xor_nonce_masked": "fccd05d5770f34ad9267f0a59994b15a", 194 | "tag": "cdc46ae475563de037001ef84ae21744", 195 | "initial_counter": "cdc46ae475563de037001ef84ae217c4", 196 | "result": "2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80cdc46ae475563de037001ef84ae21744" 197 | }, 198 | { 199 | "plaintext": "02000000", 200 | "aad": "010000000000000000000000", 201 | "key": "01000000000000000000000000000000", 202 | "nonce": "030000000000000000000000", 203 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 204 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 205 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000060000000000000002000000000000000", 206 | "polyval_result": "f6ce9d3dcd68a2fd603c7ecc18fb9918", 207 | "polyval_result_xor_nonce": "f5ce9d3dcd68a2fd603c7ecc18fb9918", 208 | "polyval_result_xor_nonce_masked": "f5ce9d3dcd68a2fd603c7ecc18fb9918", 209 | "tag": "07eb1f84fb28f8cb73de8e99e2f48a14", 210 | "initial_counter": "07eb1f84fb28f8cb73de8e99e2f48a94", 211 | "result": "a8fe3e8707eb1f84fb28f8cb73de8e99e2f48a14" 212 | }, 213 | { 214 | "plaintext": "0300000000000000000000000000000004000000", 215 | "aad": "010000000000000000000000000000000200", 216 | "key": "01000000000000000000000000000000", 217 | "nonce": "030000000000000000000000", 218 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 219 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 220 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000009000000000000000a000000000000000", 221 | "polyval_result": "4781d492cb8f926c504caa36f61008fe", 222 | "polyval_result_xor_nonce": "4481d492cb8f926c504caa36f61008fe", 223 | "polyval_result_xor_nonce_masked": "4481d492cb8f926c504caa36f610087e", 224 | "tag": "24afc9805e976f451e6d87f6fe106514", 225 | "initial_counter": "24afc9805e976f451e6d87f6fe106594", 226 | "result": "6bb0fecf5ded9b77f902c7d5da236a4391dd029724afc9805e976f451e6d87f6fe106514" 227 | }, 228 | { 229 | "plaintext": "030000000000000000000000000000000400", 230 | "aad": "0100000000000000000000000000000002000000", 231 | "key": "01000000000000000000000000000000", 232 | "nonce": "030000000000000000000000", 233 | "record_authentication_key": "d9b360279694941ac5dbc6987ada7377", 234 | "record_encryption_key": "4004a0dcd862f2a57360219d2d44ef6c", 235 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000a0000000000000009000000000000000", 236 | "polyval_result": "75cbc23a1a10e348aeb8e384b5cc79fd", 237 | "polyval_result_xor_nonce": "76cbc23a1a10e348aeb8e384b5cc79fd", 238 | "polyval_result_xor_nonce_masked": "76cbc23a1a10e348aeb8e384b5cc797d", 239 | "tag": "bff9b2ef00fb47920cc72a0c0f13b9fd", 240 | "initial_counter": "bff9b2ef00fb47920cc72a0c0f13b9fd", 241 | "result": "44d0aaf6fb2f1f34add5e8064e83e12a2adabff9b2ef00fb47920cc72a0c0f13b9fd" 242 | }, 243 | { 244 | "plaintext": "", 245 | "aad": "", 246 | "key": "e66021d5eb8e4f4066d4adb9c33560e4", 247 | "nonce": "f46e44bb3da0015c94f70887", 248 | "record_authentication_key": "036ee1fe2d7926af68898095e54e7b3c", 249 | "record_encryption_key": "5e46482396008223b5c1d25173d87539", 250 | "polyval_input": "00000000000000000000000000000000", 251 | "polyval_result": "00000000000000000000000000000000", 252 | "polyval_result_xor_nonce": "f46e44bb3da0015c94f7088700000000", 253 | "polyval_result_xor_nonce_masked": "f46e44bb3da0015c94f7088700000000", 254 | "tag": "a4194b79071b01a87d65f706e3949578", 255 | "initial_counter": "a4194b79071b01a87d65f706e39495f8", 256 | "result": "a4194b79071b01a87d65f706e3949578" 257 | }, 258 | { 259 | "plaintext": "7a806c", 260 | "aad": "46bb91c3c5", 261 | "key": "36864200e0eaf5284d884a0e77d31646", 262 | "nonce": "bae8e37fc83441b16034566b", 263 | "record_authentication_key": "3e28de1120b2981a0155795ca2812af6", 264 | "record_encryption_key": "6d4b78b31a4c9c03d8db0f42f7507fae", 265 | "polyval_input": "46bb91c3c500000000000000000000007a806c0000000000000000000000000028000000000000001800000000000000", 266 | "polyval_result": "43d9a745511dcfa21b96dd606f1d5720", 267 | "polyval_result_xor_nonce": "f931443a99298e137ba28b0b6f1d5720", 268 | "polyval_result_xor_nonce_masked": "f931443a99298e137ba28b0b6f1d5720", 269 | "tag": "711bd85bc1e4d3e0a462e074eea428a8", 270 | "initial_counter": "711bd85bc1e4d3e0a462e074eea428a8", 271 | "result": "af60eb711bd85bc1e4d3e0a462e074eea428a8" 272 | }, 273 | { 274 | "plaintext": "bdc66f146545", 275 | "aad": "fc880c94a95198874296", 276 | "key": "aedb64a6c590bc84d1a5e269e4b47801", 277 | "nonce": "afc0577e34699b9e671fdd4f", 278 | "record_authentication_key": "43b8de9cea62330d15cccfc84a33e8c8", 279 | "record_encryption_key": "8e54631607e431e095b54852868e3a27", 280 | "polyval_input": "fc880c94a95198874296000000000000bdc66f1465450000000000000000000050000000000000003000000000000000", 281 | "polyval_result": "26498e0d2b1ef004e808c458e8f2f515", 282 | "polyval_result_xor_nonce": "8989d9731f776b9a8f171917e8f2f515", 283 | "polyval_result_xor_nonce_masked": "8989d9731f776b9a8f171917e8f2f515", 284 | "tag": "d6a9c45545cfc11f03ad743dba20f966", 285 | "initial_counter": "d6a9c45545cfc11f03ad743dba20f9e6", 286 | "result": "bb93a3e34d3cd6a9c45545cfc11f03ad743dba20f966" 287 | }, 288 | { 289 | "plaintext": "1177441f195495860f", 290 | "aad": "046787f3ea22c127aaf195d1894728", 291 | "key": "d5cc1fd161320b6920ce07787f86743b", 292 | "nonce": "275d1ab32f6d1f0434d8848c", 293 | "record_authentication_key": "8a51df64d93eaf667c2c09bd454ce5c5", 294 | "record_encryption_key": "43ab276c2b4a473918ca73f2dd85109c", 295 | "polyval_input": "046787f3ea22c127aaf195d1894728001177441f195495860f0000000000000078000000000000004800000000000000", 296 | "polyval_result": "63a3451c0b23345ad02bba59956517cf", 297 | "polyval_result_xor_nonce": "44fe5faf244e2b5ee4f33ed5956517cf", 298 | "polyval_result_xor_nonce_masked": "44fe5faf244e2b5ee4f33ed59565174f", 299 | "tag": "1d02fd0cd174c84fc5dae2f60f52fd2b", 300 | "initial_counter": "1d02fd0cd174c84fc5dae2f60f52fdab", 301 | "result": "4f37281f7ad12949d01d02fd0cd174c84fc5dae2f60f52fd2b" 302 | }, 303 | { 304 | "plaintext": "9f572c614b4745914474e7c7", 305 | "aad": "c9882e5386fd9f92ec489c8fde2be2cf97e74e93", 306 | "key": "b3fed1473c528b8426a582995929a149", 307 | "nonce": "9e9ad8780c8d63d0ab4149c0", 308 | "record_authentication_key": "22f50707a95dd416df069d670cb775e8", 309 | "record_encryption_key": "f674a5584ee21fe97b4cebc468ab61e4", 310 | "polyval_input": "c9882e5386fd9f92ec489c8fde2be2cf97e74e930000000000000000000000009f572c614b4745914474e7c700000000a0000000000000006000000000000000", 311 | "polyval_result": "0cca0423fba9d77fe7e2e6963b08cdd0", 312 | "polyval_result_xor_nonce": "9250dc5bf724b4af4ca3af563b08cdd0", 313 | "polyval_result_xor_nonce_masked": "9250dc5bf724b4af4ca3af563b08cd50", 314 | "tag": "c1dc2f871fb7561da1286e655e24b7b0", 315 | "initial_counter": "c1dc2f871fb7561da1286e655e24b7b0", 316 | "result": "f54673c5ddf710c745641c8bc1dc2f871fb7561da1286e655e24b7b0" 317 | }, 318 | { 319 | "plaintext": "0d8c8451178082355c9e940fea2f58", 320 | "aad": "2950a70d5a1db2316fd568378da107b52b0da55210cc1c1b0a", 321 | "key": "2d4ed87da44102952ef94b02b805249b", 322 | "nonce": "ac80e6f61455bfac8308a2d4", 323 | "record_authentication_key": "0b00a29a83e7e95b92e3a0783b29f140", 324 | "record_encryption_key": "a430c27f285aed913005975c42eed5f3", 325 | "polyval_input": "2950a70d5a1db2316fd568378da107b52b0da55210cc1c1b0a000000000000000d8c8451178082355c9e940fea2f5800c8000000000000007800000000000000", 326 | "polyval_result": "1086ef25247aa41009bbc40871d9b350", 327 | "polyval_result_xor_nonce": "bc0609d3302f1bbc8ab366dc71d9b350", 328 | "polyval_result_xor_nonce_masked": "bc0609d3302f1bbc8ab366dc71d9b350", 329 | "tag": "83b3449b9f39552de99dc214a1190b0b", 330 | "initial_counter": "83b3449b9f39552de99dc214a1190b8b", 331 | "result": "c9ff545e07b88a015f05b274540aa183b3449b9f39552de99dc214a1190b0b" 332 | }, 333 | { 334 | "plaintext": "6b3db4da3d57aa94842b9803a96e07fb6de7", 335 | "aad": "1860f762ebfbd08284e421702de0de18baa9c9596291b08466f37de21c7f", 336 | "key": "bde3b2f204d1e9f8b06bc47f9745b3d1", 337 | "nonce": "ae06556fb6aa7890bebc18fe", 338 | "record_authentication_key": "21c874a8bad3603d1c3e8784df5b3f9f", 339 | "record_encryption_key": "d1c16d72651c3df504eae27129d818e8", 340 | "polyval_input": "1860f762ebfbd08284e421702de0de18baa9c9596291b08466f37de21c7f00006b3db4da3d57aa94842b9803a96e07fb6de70000000000000000000000000000f0000000000000009000000000000000", 341 | "polyval_result": "55462a5afa0da8d646481e049ef9c764", 342 | "polyval_result_xor_nonce": "fb407f354ca7d046f8f406fa9ef9c764", 343 | "polyval_result_xor_nonce_masked": "fb407f354ca7d046f8f406fa9ef9c764", 344 | "tag": "3e377094f04709f64d7b985310a4db84", 345 | "initial_counter": "3e377094f04709f64d7b985310a4db84", 346 | "result": "6298b296e24e8cc35dce0bed484b7f30d5803e377094f04709f64d7b985310a4db84" 347 | }, 348 | { 349 | "plaintext": "e42a3c02c25b64869e146d7b233987bddfc240871d", 350 | "aad": "7576f7028ec6eb5ea7e298342a94d4b202b370ef9768ec6561c4fe6b7e7296fa859c21", 351 | "key": "f901cfe8a69615a93fdf7a98cad48179", 352 | "nonce": "6245709fb18853f68d833640", 353 | "record_authentication_key": "3724f55f1d22ac0ab830da0b6a995d74", 354 | "record_encryption_key": "75ac87b70c05db287de779006105a344", 355 | "polyval_input": "7576f7028ec6eb5ea7e298342a94d4b202b370ef9768ec6561c4fe6b7e7296fa859c2100000000000000000000000000e42a3c02c25b64869e146d7b233987bddfc240871d00000000000000000000001801000000000000a800000000000000", 356 | "polyval_result": "4cbba090f03f7d1188ea55749fa6c7bd", 357 | "polyval_result_xor_nonce": "2efed00f41b72ee7056963349fa6c7bd", 358 | "polyval_result_xor_nonce_masked": "2efed00f41b72ee7056963349fa6c73d", 359 | "tag": "2d15506c84a9edd65e13e9d24a2a6e70", 360 | "initial_counter": "2d15506c84a9edd65e13e9d24a2a6ef0", 361 | "result": "391cc328d484a4f46406181bcd62efd9b3ee197d052d15506c84a9edd65e13e9d24a2a6e70" 362 | } 363 | ] 364 | } -------------------------------------------------------------------------------- /docs/styles/docfx.css: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. */ 2 | html, 3 | body { 4 | font-family: 'Segoe UI', Tahoma, Helvetica, sans-serif; 5 | height: 100%; 6 | } 7 | button, 8 | a { 9 | color: #337ab7; 10 | cursor: pointer; 11 | } 12 | button:hover, 13 | button:focus, 14 | a:hover, 15 | a:focus { 16 | color: #23527c; 17 | text-decoration: none; 18 | } 19 | a.disable, 20 | a.disable:hover { 21 | text-decoration: none; 22 | cursor: default; 23 | color: #000000; 24 | } 25 | 26 | h1, h2, h3, h4, h5, h6, .text-break { 27 | word-wrap: break-word; 28 | word-break: break-word; 29 | } 30 | 31 | h1 mark, 32 | h2 mark, 33 | h3 mark, 34 | h4 mark, 35 | h5 mark, 36 | h6 mark { 37 | padding: 0; 38 | } 39 | 40 | .inheritance .level0:before, 41 | .inheritance .level1:before, 42 | .inheritance .level2:before, 43 | .inheritance .level3:before, 44 | .inheritance .level4:before, 45 | .inheritance .level5:before { 46 | content: '↳'; 47 | margin-right: 5px; 48 | } 49 | 50 | .inheritance .level0 { 51 | margin-left: 0em; 52 | } 53 | 54 | .inheritance .level1 { 55 | margin-left: 1em; 56 | } 57 | 58 | .inheritance .level2 { 59 | margin-left: 2em; 60 | } 61 | 62 | .inheritance .level3 { 63 | margin-left: 3em; 64 | } 65 | 66 | .inheritance .level4 { 67 | margin-left: 4em; 68 | } 69 | 70 | .inheritance .level5 { 71 | margin-left: 5em; 72 | } 73 | 74 | span.parametername, 75 | span.paramref, 76 | span.typeparamref { 77 | font-style: italic; 78 | } 79 | span.languagekeyword{ 80 | font-weight: bold; 81 | } 82 | 83 | svg:hover path { 84 | fill: #ffffff; 85 | } 86 | 87 | .hljs { 88 | display: inline; 89 | background-color: inherit; 90 | padding: 0; 91 | } 92 | /* additional spacing fixes */ 93 | .btn + .btn { 94 | margin-left: 10px; 95 | } 96 | .btn.pull-right { 97 | margin-left: 10px; 98 | margin-top: 5px; 99 | } 100 | .table { 101 | margin-bottom: 10px; 102 | } 103 | table p { 104 | margin-bottom: 0; 105 | } 106 | table a { 107 | display: inline-block; 108 | } 109 | 110 | /* Make hidden attribute compatible with old browser.*/ 111 | [hidden] { 112 | display: none !important; 113 | } 114 | 115 | h1, 116 | .h1, 117 | h2, 118 | .h2, 119 | h3, 120 | .h3 { 121 | margin-top: 15px; 122 | margin-bottom: 10px; 123 | font-weight: 400; 124 | } 125 | h4, 126 | .h4, 127 | h5, 128 | .h5, 129 | h6, 130 | .h6 { 131 | margin-top: 10px; 132 | margin-bottom: 5px; 133 | } 134 | .navbar { 135 | margin-bottom: 0; 136 | } 137 | #wrapper { 138 | min-height: 100%; 139 | position: relative; 140 | } 141 | /* blends header footer and content together with gradient effect */ 142 | .grad-top { 143 | /* For Safari 5.1 to 6.0 */ 144 | /* For Opera 11.1 to 12.0 */ 145 | /* For Firefox 3.6 to 15 */ 146 | background: linear-gradient(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0)); 147 | /* Standard syntax */ 148 | height: 5px; 149 | } 150 | .grad-bottom { 151 | /* For Safari 5.1 to 6.0 */ 152 | /* For Opera 11.1 to 12.0 */ 153 | /* For Firefox 3.6 to 15 */ 154 | background: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.05)); 155 | /* Standard syntax */ 156 | height: 5px; 157 | } 158 | .divider { 159 | margin: 0 5px; 160 | color: #cccccc; 161 | } 162 | hr { 163 | border-color: #cccccc; 164 | } 165 | header { 166 | position: fixed; 167 | top: 0; 168 | left: 0; 169 | right: 0; 170 | z-index: 1000; 171 | } 172 | header .navbar { 173 | border-width: 0 0 1px; 174 | border-radius: 0; 175 | } 176 | .navbar-brand { 177 | font-size: inherit; 178 | padding: 0; 179 | } 180 | .navbar-collapse { 181 | margin: 0 -15px; 182 | } 183 | .subnav { 184 | min-height: 40px; 185 | } 186 | 187 | .inheritance h5, .inheritedMembers h5{ 188 | padding-bottom: 5px; 189 | border-bottom: 1px solid #ccc; 190 | } 191 | 192 | article h1, article h2, article h3, article h4{ 193 | margin-top: 25px; 194 | } 195 | 196 | article h4{ 197 | border-bottom: 1px solid #ccc; 198 | } 199 | 200 | article span.small.pull-right{ 201 | margin-top: 20px; 202 | } 203 | 204 | article section { 205 | margin-left: 1em; 206 | } 207 | 208 | /*.expand-all { 209 | padding: 10px 0; 210 | }*/ 211 | .breadcrumb { 212 | margin: 0; 213 | padding: 10px 0; 214 | background-color: inherit; 215 | white-space: nowrap; 216 | } 217 | .breadcrumb > li + li:before { 218 | content: "\00a0/"; 219 | } 220 | #autocollapse.collapsed .navbar-header { 221 | float: none; 222 | } 223 | #autocollapse.collapsed .navbar-toggle { 224 | display: block; 225 | } 226 | #autocollapse.collapsed .navbar-collapse { 227 | border-top: 1px solid transparent; 228 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); 229 | } 230 | #autocollapse.collapsed .navbar-collapse.collapse { 231 | display: none !important; 232 | } 233 | #autocollapse.collapsed .navbar-nav { 234 | float: none !important; 235 | margin: 7.5px -15px; 236 | } 237 | #autocollapse.collapsed .navbar-nav > li { 238 | float: none; 239 | } 240 | #autocollapse.collapsed .navbar-nav > li > a { 241 | padding-top: 10px; 242 | padding-bottom: 10px; 243 | } 244 | #autocollapse.collapsed .collapse.in, 245 | #autocollapse.collapsed .collapsing { 246 | display: block !important; 247 | } 248 | #autocollapse.collapsed .collapse.in .navbar-right, 249 | #autocollapse.collapsed .collapsing .navbar-right { 250 | float: none !important; 251 | } 252 | #autocollapse .form-group { 253 | width: 100%; 254 | } 255 | #autocollapse .form-control { 256 | width: 100%; 257 | } 258 | #autocollapse .navbar-header { 259 | margin-left: 0; 260 | margin-right: 0; 261 | } 262 | #autocollapse .navbar-brand { 263 | margin-left: 0; 264 | } 265 | .collapse.in, 266 | .collapsing { 267 | text-align: center; 268 | } 269 | .collapsing .navbar-form { 270 | margin: 0 auto; 271 | max-width: 400px; 272 | padding: 10px 15px; 273 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 274 | } 275 | .collapsed .collapse.in .navbar-form { 276 | margin: 0 auto; 277 | max-width: 400px; 278 | padding: 10px 15px; 279 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1); 280 | } 281 | .navbar .navbar-nav { 282 | display: inline-block; 283 | } 284 | .docs-search { 285 | background: white; 286 | vertical-align: middle; 287 | } 288 | .docs-search > .search-query { 289 | font-size: 14px; 290 | border: 0; 291 | width: 120%; 292 | color: #555; 293 | } 294 | .docs-search > .search-query:focus { 295 | outline: 0; 296 | } 297 | .search-results-frame { 298 | clear: both; 299 | display: table; 300 | width: 100%; 301 | } 302 | .search-results.ng-hide { 303 | display: none; 304 | } 305 | .search-results-container { 306 | padding-bottom: 1em; 307 | border-top: 1px solid #111; 308 | background: rgba(25, 25, 25, 0.5); 309 | } 310 | .search-results-container .search-results-group { 311 | padding-top: 50px !important; 312 | padding: 10px; 313 | } 314 | .search-results-group-heading { 315 | font-family: "Open Sans"; 316 | padding-left: 10px; 317 | color: white; 318 | } 319 | .search-close { 320 | position: absolute; 321 | left: 50%; 322 | margin-left: -100px; 323 | color: white; 324 | text-align: center; 325 | padding: 5px; 326 | background: #333; 327 | border-top-right-radius: 5px; 328 | border-top-left-radius: 5px; 329 | width: 200px; 330 | box-shadow: 0 0 10px #111; 331 | } 332 | #search { 333 | display: none; 334 | } 335 | 336 | /* Search results display*/ 337 | #search-results { 338 | max-width: 960px !important; 339 | margin-top: 120px; 340 | margin-bottom: 115px; 341 | margin-left: auto; 342 | margin-right: auto; 343 | line-height: 1.8; 344 | display: none; 345 | } 346 | 347 | #search-results>.search-list { 348 | text-align: center; 349 | font-size: 2.5rem; 350 | margin-bottom: 50px; 351 | } 352 | 353 | #search-results p { 354 | text-align: center; 355 | } 356 | 357 | #search-results p .index-loading { 358 | animation: index-loading 1.5s infinite linear; 359 | -webkit-animation: index-loading 1.5s infinite linear; 360 | -o-animation: index-loading 1.5s infinite linear; 361 | font-size: 2.5rem; 362 | } 363 | 364 | @keyframes index-loading { 365 | from { transform: scale(1) rotate(0deg);} 366 | to { transform: scale(1) rotate(360deg);} 367 | } 368 | 369 | @-webkit-keyframes index-loading { 370 | from { -webkit-transform: rotate(0deg);} 371 | to { -webkit-transform: rotate(360deg);} 372 | } 373 | 374 | @-o-keyframes index-loading { 375 | from { -o-transform: rotate(0deg);} 376 | to { -o-transform: rotate(360deg);} 377 | } 378 | 379 | #search-results .sr-items { 380 | font-size: 24px; 381 | } 382 | 383 | .sr-item { 384 | margin-bottom: 25px; 385 | } 386 | 387 | .sr-item>.item-href { 388 | font-size: 14px; 389 | color: #093; 390 | } 391 | 392 | .sr-item>.item-brief { 393 | font-size: 13px; 394 | } 395 | 396 | .pagination>li>a { 397 | color: #47A7A0 398 | } 399 | 400 | .pagination>.active>a { 401 | background-color: #47A7A0; 402 | border-color: #47A7A0; 403 | } 404 | 405 | .fixed_header { 406 | position: fixed; 407 | width: 100%; 408 | padding-bottom: 10px; 409 | padding-top: 10px; 410 | margin: 0px; 411 | top: 0; 412 | z-index: 9999; 413 | left: 0; 414 | } 415 | 416 | .fixed_header+.toc{ 417 | margin-top: 50px; 418 | margin-left: 0; 419 | } 420 | 421 | .sidenav, .fixed_header, .toc { 422 | background-color: #f1f1f1; 423 | } 424 | 425 | .sidetoc { 426 | position: fixed; 427 | width: 260px; 428 | top: 150px; 429 | bottom: 0; 430 | overflow-x: hidden; 431 | overflow-y: auto; 432 | background-color: #f1f1f1; 433 | border-left: 1px solid #e7e7e7; 434 | border-right: 1px solid #e7e7e7; 435 | z-index: 1; 436 | } 437 | 438 | .sidetoc.shiftup { 439 | bottom: 70px; 440 | } 441 | 442 | body .toc{ 443 | background-color: #f1f1f1; 444 | overflow-x: hidden; 445 | } 446 | 447 | .sidetoggle.ng-hide { 448 | display: block !important; 449 | } 450 | .sidetoc-expand > .caret { 451 | margin-left: 0px; 452 | margin-top: -2px; 453 | } 454 | .sidetoc-expand > .caret-side { 455 | border-left: 4px solid; 456 | border-top: 4px solid transparent; 457 | border-bottom: 4px solid transparent; 458 | margin-left: 4px; 459 | margin-top: -4px; 460 | } 461 | .sidetoc-heading { 462 | font-weight: 500; 463 | } 464 | 465 | .toc { 466 | margin: 0px 0 0 10px; 467 | padding: 0 10px; 468 | } 469 | .expand-stub { 470 | position: absolute; 471 | left: -10px; 472 | } 473 | .toc .nav > li > a.sidetoc-expand { 474 | position: absolute; 475 | top: 0; 476 | left: 0; 477 | } 478 | .toc .nav > li > a { 479 | color: #666666; 480 | margin-left: 5px; 481 | display: block; 482 | padding: 0; 483 | } 484 | .toc .nav > li > a:hover, 485 | .toc .nav > li > a:focus { 486 | color: #000000; 487 | background: none; 488 | text-decoration: inherit; 489 | } 490 | .toc .nav > li.active > a { 491 | color: #337ab7; 492 | } 493 | .toc .nav > li.active > a:hover, 494 | .toc .nav > li.active > a:focus { 495 | color: #23527c; 496 | } 497 | 498 | .toc .nav > li> .expand-stub { 499 | cursor: pointer; 500 | } 501 | 502 | .toc .nav > li.active > .expand-stub::before, 503 | .toc .nav > li.in > .expand-stub::before, 504 | .toc .nav > li.in.active > .expand-stub::before, 505 | .toc .nav > li.filtered > .expand-stub::before { 506 | content: "-"; 507 | } 508 | 509 | .toc .nav > li > .expand-stub::before, 510 | .toc .nav > li.active > .expand-stub::before { 511 | content: "+"; 512 | } 513 | 514 | .toc .nav > li.filtered > ul, 515 | .toc .nav > li.in > ul { 516 | display: block; 517 | } 518 | 519 | .toc .nav > li > ul { 520 | display: none; 521 | } 522 | 523 | .toc ul{ 524 | font-size: 12px; 525 | margin: 0 0 0 3px; 526 | } 527 | 528 | .toc .level1 > li { 529 | font-weight: bold; 530 | margin-top: 10px; 531 | position: relative; 532 | font-size: 16px; 533 | } 534 | .toc .level2 { 535 | font-weight: normal; 536 | margin: 5px 0 0 15px; 537 | font-size: 14px; 538 | } 539 | .toc-toggle { 540 | display: none; 541 | margin: 0 15px 0px 15px; 542 | } 543 | .sidefilter { 544 | position: fixed; 545 | top: 90px; 546 | width: 260px; 547 | background-color: #f1f1f1; 548 | padding: 15px; 549 | border-left: 1px solid #e7e7e7; 550 | border-right: 1px solid #e7e7e7; 551 | z-index: 1; 552 | } 553 | .toc-filter { 554 | border-radius: 5px; 555 | background: #fff; 556 | color: #666666; 557 | padding: 5px; 558 | position: relative; 559 | margin: 0 5px 0 5px; 560 | } 561 | .toc-filter > input { 562 | border: 0; 563 | color: #666666; 564 | padding-left: 20px; 565 | width: 100%; 566 | } 567 | .toc-filter > input:focus { 568 | outline: 0; 569 | } 570 | .toc-filter > .filter-icon { 571 | position: absolute; 572 | top: 10px; 573 | left: 5px; 574 | } 575 | .article { 576 | margin-top: 120px; 577 | margin-bottom: 115px; 578 | } 579 | 580 | #_content>a{ 581 | margin-top: 105px; 582 | } 583 | 584 | .article.grid-right { 585 | margin-left: 280px; 586 | } 587 | 588 | .inheritance hr { 589 | margin-top: 5px; 590 | margin-bottom: 5px; 591 | } 592 | .article img { 593 | max-width: 100%; 594 | } 595 | .sideaffix { 596 | margin-top: 50px; 597 | font-size: 12px; 598 | max-height: 100%; 599 | overflow: hidden; 600 | top: 100px; 601 | bottom: 10px; 602 | position: fixed; 603 | } 604 | .sideaffix.shiftup { 605 | bottom: 70px; 606 | } 607 | .affix { 608 | position: relative; 609 | height: 100%; 610 | } 611 | .sideaffix > div.contribution { 612 | margin-bottom: 20px; 613 | } 614 | .sideaffix > div.contribution > ul > li > a.contribution-link { 615 | padding: 6px 10px; 616 | font-weight: bold; 617 | font-size: 14px; 618 | } 619 | .sideaffix > div.contribution > ul > li > a.contribution-link:hover { 620 | background-color: #ffffff; 621 | } 622 | .sideaffix ul.nav > li > a:focus { 623 | background: none; 624 | } 625 | .affix h5 { 626 | font-weight: bold; 627 | text-transform: uppercase; 628 | padding-left: 10px; 629 | font-size: 12px; 630 | } 631 | .affix > ul.level1 { 632 | overflow: hidden; 633 | padding-bottom: 10px; 634 | height: calc(100% - 100px); 635 | margin-right: -20px; 636 | } 637 | .affix ul > li > a:before { 638 | color: #cccccc; 639 | position: absolute; 640 | } 641 | .affix ul > li > a:hover { 642 | background: none; 643 | color: #666666; 644 | } 645 | .affix ul > li.active > a, 646 | .affix ul > li.active > a:before { 647 | color: #337ab7; 648 | } 649 | .affix ul > li > a { 650 | padding: 5px 12px; 651 | color: #666666; 652 | } 653 | .affix > ul > li.active:last-child { 654 | margin-bottom: 50px; 655 | } 656 | .affix > ul > li > a:before { 657 | content: "|"; 658 | font-size: 16px; 659 | top: 1px; 660 | left: 0; 661 | } 662 | .affix > ul > li.active > a, 663 | .affix > ul > li.active > a:before { 664 | color: #337ab7; 665 | font-weight: bold; 666 | } 667 | .affix ul ul > li > a { 668 | padding: 2px 15px; 669 | } 670 | .affix ul ul > li > a:before { 671 | content: ">"; 672 | font-size: 14px; 673 | top: -1px; 674 | left: 5px; 675 | } 676 | .affix ul > li > a:before, 677 | .affix ul ul { 678 | display: none; 679 | } 680 | .affix ul > li.active > ul, 681 | .affix ul > li.active > a:before, 682 | .affix ul > li > a:hover:before { 683 | display: block; 684 | white-space: nowrap; 685 | } 686 | .codewrapper { 687 | position: relative; 688 | } 689 | .trydiv { 690 | height: 0px; 691 | } 692 | .tryspan { 693 | position: absolute; 694 | top: 0px; 695 | right: 0px; 696 | border-style: solid; 697 | border-radius: 0px 4px; 698 | box-sizing: border-box; 699 | border-width: 1px; 700 | border-color: #cccccc; 701 | text-align: center; 702 | padding: 2px 8px; 703 | background-color: white; 704 | font-size: 12px; 705 | cursor: pointer; 706 | z-index: 100; 707 | display: none; 708 | color: #767676; 709 | } 710 | .tryspan:hover { 711 | background-color: #3b8bd0; 712 | color: white; 713 | border-color: #3b8bd0; 714 | } 715 | .codewrapper:hover .tryspan { 716 | display: block; 717 | } 718 | .sample-response .response-content{ 719 | max-height: 200px; 720 | } 721 | footer { 722 | position: absolute; 723 | left: 0; 724 | right: 0; 725 | bottom: 0; 726 | z-index: 1000; 727 | } 728 | .footer { 729 | border-top: 1px solid #e7e7e7; 730 | background-color: #f8f8f8; 731 | padding: 15px 0; 732 | } 733 | @media (min-width: 768px) { 734 | #sidetoggle.collapse { 735 | display: block; 736 | } 737 | .topnav .navbar-nav { 738 | float: none; 739 | white-space: nowrap; 740 | } 741 | .topnav .navbar-nav > li { 742 | float: none; 743 | display: inline-block; 744 | } 745 | } 746 | @media only screen and (max-width: 768px) { 747 | #mobile-indicator { 748 | display: block; 749 | } 750 | /* TOC display for responsive */ 751 | .article { 752 | margin-top: 30px !important; 753 | } 754 | header { 755 | position: static; 756 | } 757 | .topnav { 758 | text-align: center; 759 | } 760 | .sidenav { 761 | padding: 15px 0; 762 | margin-left: -15px; 763 | margin-right: -15px; 764 | } 765 | .sidefilter { 766 | position: static; 767 | width: auto; 768 | float: none; 769 | border: none; 770 | } 771 | .sidetoc { 772 | position: static; 773 | width: auto; 774 | float: none; 775 | padding-bottom: 0px; 776 | border: none; 777 | } 778 | .toc .nav > li, .toc .nav > li >a { 779 | display: inline-block; 780 | } 781 | .toc li:after { 782 | margin-left: -3px; 783 | margin-right: 5px; 784 | content: ", "; 785 | color: #666666; 786 | } 787 | .toc .level1 > li { 788 | display: block; 789 | } 790 | 791 | .toc .level1 > li:after { 792 | display: none; 793 | } 794 | .article.grid-right { 795 | margin-left: 0; 796 | } 797 | .grad-top, 798 | .grad-bottom { 799 | display: none; 800 | } 801 | .toc-toggle { 802 | display: block; 803 | } 804 | .sidetoggle.ng-hide { 805 | display: none !important; 806 | } 807 | /*.expand-all { 808 | display: none; 809 | }*/ 810 | .sideaffix { 811 | display: none; 812 | } 813 | .mobile-hide { 814 | display: none; 815 | } 816 | .breadcrumb { 817 | white-space: inherit; 818 | } 819 | 820 | /* workaround for #hashtag url is no longer needed*/ 821 | h1:before, 822 | h2:before, 823 | h3:before, 824 | h4:before { 825 | content: ''; 826 | display: none; 827 | } 828 | } 829 | 830 | /* For toc iframe */ 831 | @media (max-width: 260px) { 832 | .toc .level2 > li { 833 | display: block; 834 | } 835 | 836 | .toc .level2 > li:after { 837 | display: none; 838 | } 839 | } 840 | 841 | /* For code snippet line highlight */ 842 | pre > code .line-highlight { 843 | background-color: #ffffcc; 844 | } 845 | 846 | /* Alerts */ 847 | .alert h5 { 848 | text-transform: uppercase; 849 | font-weight: bold; 850 | margin-top: 0; 851 | } 852 | 853 | .alert h5:before { 854 | position:relative; 855 | top:1px; 856 | display:inline-block; 857 | font-family:'Glyphicons Halflings'; 858 | line-height:1; 859 | -webkit-font-smoothing:antialiased; 860 | -moz-osx-font-smoothing:grayscale; 861 | margin-right: 5px; 862 | font-weight: normal; 863 | } 864 | 865 | .alert-info h5:before { 866 | content:"\e086" 867 | } 868 | 869 | .alert-warning h5:before { 870 | content:"\e127" 871 | } 872 | 873 | .alert-danger h5:before { 874 | content:"\e107" 875 | } 876 | 877 | /* For Embedded Video */ 878 | div.embeddedvideo { 879 | padding-top: 56.25%; 880 | position: relative; 881 | width: 100%; 882 | } 883 | 884 | div.embeddedvideo iframe { 885 | position: absolute; 886 | top: 0; 887 | left: 0; 888 | right: 0; 889 | bottom: 0; 890 | width: 100%; 891 | height: 100%; 892 | } 893 | 894 | /* For printer */ 895 | @media print{ 896 | .article.grid-right { 897 | margin-top: 0px; 898 | margin-left: 0px; 899 | } 900 | .sideaffix { 901 | display: none; 902 | } 903 | .mobile-hide { 904 | display: none; 905 | } 906 | .footer { 907 | display: none; 908 | } 909 | } 910 | 911 | /* For tabbed content */ 912 | 913 | .tabGroup { 914 | margin-top: 1rem; } 915 | .tabGroup ul[role="tablist"] { 916 | margin: 0; 917 | padding: 0; 918 | list-style: none; } 919 | .tabGroup ul[role="tablist"] > li { 920 | list-style: none; 921 | display: inline-block; } 922 | .tabGroup a[role="tab"] { 923 | color: #6e6e6e; 924 | box-sizing: border-box; 925 | display: inline-block; 926 | padding: 5px 7.5px; 927 | text-decoration: none; 928 | border-bottom: 2px solid #fff; } 929 | .tabGroup a[role="tab"]:hover, .tabGroup a[role="tab"]:focus, .tabGroup a[role="tab"][aria-selected="true"] { 930 | border-bottom: 2px solid #0050C5; } 931 | .tabGroup a[role="tab"][aria-selected="true"] { 932 | color: #222; } 933 | .tabGroup a[role="tab"]:hover, .tabGroup a[role="tab"]:focus { 934 | color: #0050C5; } 935 | .tabGroup a[role="tab"]:focus { 936 | outline: 1px solid #0050C5; 937 | outline-offset: -1px; } 938 | @media (min-width: 768px) { 939 | .tabGroup a[role="tab"] { 940 | padding: 5px 15px; } } 941 | .tabGroup section[role="tabpanel"] { 942 | border: 1px solid #e0e0e0; 943 | padding: 15px; 944 | margin: 0; 945 | overflow: hidden; } 946 | .tabGroup section[role="tabpanel"] > .codeHeader, 947 | .tabGroup section[role="tabpanel"] > pre { 948 | margin-left: -16px; 949 | margin-right: -16px; } 950 | .tabGroup section[role="tabpanel"] > :first-child { 951 | margin-top: 0; } 952 | .tabGroup section[role="tabpanel"] > pre:last-child { 953 | display: block; 954 | margin-bottom: -16px; } 955 | 956 | .mainContainer[dir='rtl'] main ul[role="tablist"] { 957 | margin: 0; } 958 | -------------------------------------------------------------------------------- /src/Cryptography.Tests/Vectors/aes-256-gcm-siv.json: -------------------------------------------------------------------------------- 1 | { 2 | "vectors": [ 3 | { 4 | "plaintext": "", 5 | "aad": "", 6 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 7 | "nonce": "030000000000000000000000", 8 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 9 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 10 | "polyval_input": "00000000000000000000000000000000", 11 | "polyval_result": "00000000000000000000000000000000", 12 | "polyval_result_xor_nonce": "03000000000000000000000000000000", 13 | "polyval_result_xor_nonce_masked": "03000000000000000000000000000000", 14 | "tag": "07f5f4169bbf55a8400cd47ea6fd400f", 15 | "initial_counter": "07f5f4169bbf55a8400cd47ea6fd408f", 16 | "result": "07f5f4169bbf55a8400cd47ea6fd400f" 17 | }, 18 | { 19 | "plaintext": "0100000000000000", 20 | "aad": "", 21 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 22 | "nonce": "030000000000000000000000", 23 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 24 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 25 | "polyval_input": "0100000000000000000000000000000000000000000000004000000000000000", 26 | "polyval_result": "05230f62f0eac8aa14fe4d646b59cd41", 27 | "polyval_result_xor_nonce": "06230f62f0eac8aa14fe4d646b59cd41", 28 | "polyval_result_xor_nonce_masked": "06230f62f0eac8aa14fe4d646b59cd41", 29 | "tag": "843122130f7364b761e0b97427e3df28", 30 | "initial_counter": "843122130f7364b761e0b97427e3dfa8", 31 | "result": "c2ef328e5c71c83b843122130f7364b761e0b97427e3df28" 32 | }, 33 | { 34 | "plaintext": "010000000000000000000000", 35 | "aad": "", 36 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 37 | "nonce": "030000000000000000000000", 38 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 39 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 40 | "polyval_input": "0100000000000000000000000000000000000000000000006000000000000000", 41 | "polyval_result": "6d81a24732fd6d03ae5af544720a1c13", 42 | "polyval_result_xor_nonce": "6e81a24732fd6d03ae5af544720a1c13", 43 | "polyval_result_xor_nonce_masked": "6e81a24732fd6d03ae5af544720a1c13", 44 | "tag": "8ca50da9ae6559e48fd10f6e5c9ca17e", 45 | "initial_counter": "8ca50da9ae6559e48fd10f6e5c9ca1fe", 46 | "result": "9aab2aeb3faa0a34aea8e2b18ca50da9ae6559e48fd10f6e5c9ca17e" 47 | }, 48 | { 49 | "plaintext": "01000000000000000000000000000000", 50 | "aad": "", 51 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 52 | "nonce": "030000000000000000000000", 53 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 54 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 55 | "polyval_input": "0100000000000000000000000000000000000000000000008000000000000000", 56 | "polyval_result": "74eee2bf7c9a165f8b25dea73db32a6d", 57 | "polyval_result_xor_nonce": "77eee2bf7c9a165f8b25dea73db32a6d", 58 | "polyval_result_xor_nonce_masked": "77eee2bf7c9a165f8b25dea73db32a6d", 59 | "tag": "c9eac6fa700942702e90862383c6c366", 60 | "initial_counter": "c9eac6fa700942702e90862383c6c3e6", 61 | "result": "85a01b63025ba19b7fd3ddfc033b3e76c9eac6fa700942702e90862383c6c366" 62 | }, 63 | { 64 | "plaintext": "0100000000000000000000000000000002000000000000000000000000000000", 65 | "aad": "", 66 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 67 | "nonce": "030000000000000000000000", 68 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 69 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 70 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000000000000000000000001000000000000", 71 | "polyval_result": "899b6381b3d46f0def7aa0517ba188f5", 72 | "polyval_result_xor_nonce": "8a9b6381b3d46f0def7aa0517ba188f5", 73 | "polyval_result_xor_nonce_masked": "8a9b6381b3d46f0def7aa0517ba18875", 74 | "tag": "e819e63abcd020b006a976397632eb5d", 75 | "initial_counter": "e819e63abcd020b006a976397632ebdd", 76 | "result": "4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027fe819e63abcd020b006a976397632eb5d" 77 | }, 78 | { 79 | "plaintext": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000", 80 | "aad": "", 81 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 82 | "nonce": "030000000000000000000000", 83 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 84 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 85 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000000000000000000008001000000000000", 86 | "polyval_result": "c1f8593d8fc29b0c290cae1992f71f51", 87 | "polyval_result_xor_nonce": "c2f8593d8fc29b0c290cae1992f71f51", 88 | "polyval_result_xor_nonce_masked": "c2f8593d8fc29b0c290cae1992f71f51", 89 | "tag": "790bc96880a99ba804bd12c0e6a22cc4", 90 | "initial_counter": "790bc96880a99ba804bd12c0e6a22cc4", 91 | "result": "c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5790bc96880a99ba804bd12c0e6a22cc4" 92 | }, 93 | { 94 | "plaintext": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000", 95 | "aad": "", 96 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 97 | "nonce": "030000000000000000000000", 98 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 99 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 100 | "polyval_input": "0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000000000000000000000002000000000000", 101 | "polyval_result": "6ef38b06046c7c0e225efaef8e2ec4c4", 102 | "polyval_result_xor_nonce": "6df38b06046c7c0e225efaef8e2ec4c4", 103 | "polyval_result_xor_nonce_masked": "6df38b06046c7c0e225efaef8e2ec444", 104 | "tag": "112864c269fc0d9d88c61fa47e39aa08", 105 | "initial_counter": "112864c269fc0d9d88c61fa47e39aa88", 106 | "result": "c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce112864c269fc0d9d88c61fa47e39aa08" 107 | }, 108 | { 109 | "plaintext": "0200000000000000", 110 | "aad": "01", 111 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 112 | "nonce": "030000000000000000000000", 113 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 114 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 115 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000004000000000000000", 116 | "polyval_result": "34e57bafe011b9b36fc6821b7ffb3354", 117 | "polyval_result_xor_nonce": "37e57bafe011b9b36fc6821b7ffb3354", 118 | "polyval_result_xor_nonce_masked": "37e57bafe011b9b36fc6821b7ffb3354", 119 | "tag": "91213f267e3b452f02d01ae33e4ec854", 120 | "initial_counter": "91213f267e3b452f02d01ae33e4ec8d4", 121 | "result": "1de22967237a813291213f267e3b452f02d01ae33e4ec854" 122 | }, 123 | { 124 | "plaintext": "020000000000000000000000", 125 | "aad": "01", 126 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 127 | "nonce": "030000000000000000000000", 128 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 129 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 130 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000006000000000000000", 131 | "polyval_result": "5c47d68a22061c1ad5623a3b66a8e206", 132 | "polyval_result_xor_nonce": "5f47d68a22061c1ad5623a3b66a8e206", 133 | "polyval_result_xor_nonce_masked": "5f47d68a22061c1ad5623a3b66a8e206", 134 | "tag": "c1a4a19ae800941ccdc57cc8413c277f", 135 | "initial_counter": "c1a4a19ae800941ccdc57cc8413c27ff", 136 | "result": "163d6f9cc1b346cd453a2e4cc1a4a19ae800941ccdc57cc8413c277f" 137 | }, 138 | { 139 | "plaintext": "02000000000000000000000000000000", 140 | "aad": "01", 141 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 142 | "nonce": "030000000000000000000000", 143 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 144 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 145 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000008000000000000008000000000000000", 146 | "polyval_result": "452896726c616746f01d11d82911d478", 147 | "polyval_result_xor_nonce": "462896726c616746f01d11d82911d478", 148 | "polyval_result_xor_nonce_masked": "462896726c616746f01d11d82911d478", 149 | "tag": "b292d28ff61189e8e49f3875ef91aff7", 150 | "initial_counter": "b292d28ff61189e8e49f3875ef91aff7", 151 | "result": "c91545823cc24f17dbb0e9e807d5ec17b292d28ff61189e8e49f3875ef91aff7" 152 | }, 153 | { 154 | "plaintext": "0200000000000000000000000000000003000000000000000000000000000000", 155 | "aad": "01", 156 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 157 | "nonce": "030000000000000000000000", 158 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 159 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 160 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000008000000000000000001000000000000", 161 | "polyval_result": "4e58c1e341c9bb0ae34eda9509dfc90c", 162 | "polyval_result_xor_nonce": "4d58c1e341c9bb0ae34eda9509dfc90c", 163 | "polyval_result_xor_nonce_masked": "4d58c1e341c9bb0ae34eda9509dfc90c", 164 | "tag": "aea1bad12702e1965604374aab96dbbc", 165 | "initial_counter": "aea1bad12702e1965604374aab96dbbc", 166 | "result": "07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365aea1bad12702e1965604374aab96dbbc" 167 | }, 168 | { 169 | "plaintext": "020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000", 170 | "aad": "01", 171 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 172 | "nonce": "030000000000000000000000", 173 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 174 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 175 | "polyval_input": "0100000000000000000000000000000002000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000008000000000000008001000000000000", 176 | "polyval_result": "2566a4aff9a525df9772c16d4eaf8d2a", 177 | "polyval_result_xor_nonce": "2666a4aff9a525df9772c16d4eaf8d2a", 178 | "polyval_result_xor_nonce_masked": "2666a4aff9a525df9772c16d4eaf8d2a", 179 | "tag": "03332742b228c647173616cfd44c54eb", 180 | "initial_counter": "03332742b228c647173616cfd44c54eb", 181 | "result": "c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe2503332742b228c647173616cfd44c54eb" 182 | }, 183 | { 184 | "plaintext": "02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000", 185 | "aad": "01", 186 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 187 | "nonce": "030000000000000000000000", 188 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 189 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 190 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000000500000000000000000000000000000008000000000000000002000000000000", 191 | "polyval_result": "da58d2f61b0a9d343b2f37fb0c519733", 192 | "polyval_result_xor_nonce": "d958d2f61b0a9d343b2f37fb0c519733", 193 | "polyval_result_xor_nonce_masked": "d958d2f61b0a9d343b2f37fb0c519733", 194 | "tag": "5bde0285037c5de81e5b570a049b62a0", 195 | "initial_counter": "5bde0285037c5de81e5b570a049b62a0", 196 | "result": "67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c895bde0285037c5de81e5b570a049b62a0" 197 | }, 198 | { 199 | "plaintext": "02000000", 200 | "aad": "010000000000000000000000", 201 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 202 | "nonce": "030000000000000000000000", 203 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 204 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 205 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000060000000000000002000000000000000", 206 | "polyval_result": "6dc76ae84b88916e073a303aafde05cf", 207 | "polyval_result_xor_nonce": "6ec76ae84b88916e073a303aafde05cf", 208 | "polyval_result_xor_nonce_masked": "6ec76ae84b88916e073a303aafde054f", 209 | "tag": "1835e517741dfddccfa07fa4661b74cf", 210 | "initial_counter": "1835e517741dfddccfa07fa4661b74cf", 211 | "result": "22b3f4cd1835e517741dfddccfa07fa4661b74cf" 212 | }, 213 | { 214 | "plaintext": "0300000000000000000000000000000004000000", 215 | "aad": "010000000000000000000000000000000200", 216 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 217 | "nonce": "030000000000000000000000", 218 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 219 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 220 | "polyval_input": "010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000040000000000000000000000000000009000000000000000a000000000000000", 221 | "polyval_result": "973ef4fd04bd31d193816ab26f8655ca", 222 | "polyval_result_xor_nonce": "943ef4fd04bd31d193816ab26f8655ca", 223 | "polyval_result_xor_nonce_masked": "943ef4fd04bd31d193816ab26f86554a", 224 | "tag": "b879ad976d8242acc188ab59cabfe307", 225 | "initial_counter": "b879ad976d8242acc188ab59cabfe387", 226 | "result": "43dd0163cdb48f9fe3212bf61b201976067f342bb879ad976d8242acc188ab59cabfe307" 227 | }, 228 | { 229 | "plaintext": "030000000000000000000000000000000400", 230 | "aad": "0100000000000000000000000000000002000000", 231 | "key": "0100000000000000000000000000000000000000000000000000000000000000", 232 | "nonce": "030000000000000000000000", 233 | "record_authentication_key": "b5d3c529dfafac43136d2d11be284d7f", 234 | "record_encryption_key": "b914f4742be9e1d7a2f84addbf96dec3456e3c6c05ecc157cdbf0700fedad222", 235 | "polyval_input": "01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000a0000000000000009000000000000000", 236 | "polyval_result": "2cbb6b7ab2dbffefb797f825f826870c", 237 | "polyval_result_xor_nonce": "2fbb6b7ab2dbffefb797f825f826870c", 238 | "polyval_result_xor_nonce_masked": "2fbb6b7ab2dbffefb797f825f826870c", 239 | "tag": "cfcdf5042112aa29685c912fc2056543", 240 | "initial_counter": "cfcdf5042112aa29685c912fc20565c3", 241 | "result": "462401724b5ce6588d5a54aae5375513a075cfcdf5042112aa29685c912fc2056543" 242 | }, 243 | { 244 | "plaintext": "", 245 | "aad": "", 246 | "key": "e66021d5eb8e4f4066d4adb9c33560e4f46e44bb3da0015c94f7088736864200", 247 | "nonce": "e0eaf5284d884a0e77d31646", 248 | "record_authentication_key": "e40d26f82774aa27f47b047b608b9585", 249 | "record_encryption_key": "7c7c3d9a542cef53dde0e6de9b5800400f82e73ec5f7ee41b7ba8dcb9ba078c3", 250 | "polyval_input": "00000000000000000000000000000000", 251 | "polyval_result": "00000000000000000000000000000000", 252 | "polyval_result_xor_nonce": "e0eaf5284d884a0e77d3164600000000", 253 | "polyval_result_xor_nonce_masked": "e0eaf5284d884a0e77d3164600000000", 254 | "tag": "169fbb2fbf389a995f6390af22228a62", 255 | "initial_counter": "169fbb2fbf389a995f6390af22228ae2", 256 | "result": "169fbb2fbf389a995f6390af22228a62" 257 | }, 258 | { 259 | "plaintext": "671fdd", 260 | "aad": "4fbdc66f14", 261 | "key": "bae8e37fc83441b16034566b7a806c46bb91c3c5aedb64a6c590bc84d1a5e269", 262 | "nonce": "e4b47801afc0577e34699b9e", 263 | "record_authentication_key": "b546f5a850d0a90adfe39e95c2510fc6", 264 | "record_encryption_key": "b9d1e239d62cbb5c49273ddac8838bdcc53bca478a770f07087caa4e0a924a55", 265 | "polyval_input": "4fbdc66f140000000000000000000000671fdd0000000000000000000000000028000000000000001800000000000000", 266 | "polyval_result": "b91f91f96b159a7c611c05035b839e92", 267 | "polyval_result_xor_nonce": "5dabe9f8c4d5cd0255759e9d5b839e92", 268 | "polyval_result_xor_nonce_masked": "5dabe9f8c4d5cd0255759e9d5b839e12", 269 | "tag": "93da9bb81333aee0c785b240d319719d", 270 | "initial_counter": "93da9bb81333aee0c785b240d319719d", 271 | "result": "0eaccb93da9bb81333aee0c785b240d319719d" 272 | }, 273 | { 274 | "plaintext": "195495860f04", 275 | "aad": "6787f3ea22c127aaf195", 276 | "key": "6545fc880c94a95198874296d5cc1fd161320b6920ce07787f86743b275d1ab3", 277 | "nonce": "2f6d1f0434d8848c1177441f", 278 | "record_authentication_key": "e156e1f9b0b07b780cbe30f259e3c8da", 279 | "record_encryption_key": "6fc1c494519f944aae52fcd8b14e5b171b5a9429d3b76e430d49940c0021d612", 280 | "polyval_input": "6787f3ea22c127aaf195000000000000195495860f040000000000000000000050000000000000003000000000000000", 281 | "polyval_result": "2c480ed9d236b1df24c6eec109bd40c1", 282 | "polyval_result_xor_nonce": "032511dde6ee355335b1aade09bd40c1", 283 | "polyval_result_xor_nonce_masked": "032511dde6ee355335b1aade09bd4041", 284 | "tag": "6b62b84dc40c84636a5ec12020ec8c2c", 285 | "initial_counter": "6b62b84dc40c84636a5ec12020ec8cac", 286 | "result": "a254dad4f3f96b62b84dc40c84636a5ec12020ec8c2c" 287 | }, 288 | { 289 | "plaintext": "c9882e5386fd9f92ec", 290 | "aad": "489c8fde2be2cf97e74e932d4ed87d", 291 | "key": "d1894728b3fed1473c528b8426a582995929a1499e9ad8780c8d63d0ab4149c0", 292 | "nonce": "9f572c614b4745914474e7c7", 293 | "record_authentication_key": "0533fd71f4119257361a3ff1469dd4e5", 294 | "record_encryption_key": "4feba89799be8ac3684fa2bb30ade0ea51390e6d87dcf3627d2ee44493853abe", 295 | "polyval_input": "489c8fde2be2cf97e74e932d4ed87d00c9882e5386fd9f92ec0000000000000078000000000000004800000000000000", 296 | "polyval_result": "bf160bc9ded8c63057d2c38aae552fb4", 297 | "polyval_result_xor_nonce": "204127a8959f83a113a6244dae552fb4", 298 | "polyval_result_xor_nonce_masked": "204127a8959f83a113a6244dae552f34", 299 | "tag": "c0fd3dc6628dfe55ebb0b9fb2295c8c2", 300 | "initial_counter": "c0fd3dc6628dfe55ebb0b9fb2295c8c2", 301 | "result": "0df9e308678244c44bc0fd3dc6628dfe55ebb0b9fb2295c8c2" 302 | }, 303 | { 304 | "plaintext": "1db2316fd568378da107b52b", 305 | "aad": "0da55210cc1c1b0abde3b2f204d1e9f8b06bc47f", 306 | "key": "a44102952ef94b02b805249bac80e6f61455bfac8308a2d40d8c845117808235", 307 | "nonce": "5c9e940fea2f582950a70d5a", 308 | "record_authentication_key": "64779ab10ee8a280272f14cc8851b727", 309 | "record_encryption_key": "25f40fc63f49d3b9016a8eeeb75846e0d72ca36ddbd312b6f5ef38ad14bd2651", 310 | "polyval_input": "0da55210cc1c1b0abde3b2f204d1e9f8b06bc47f0000000000000000000000001db2316fd568378da107b52b00000000a0000000000000006000000000000000", 311 | "polyval_result": "cc86ee22c861e1fd474c84676b42739c", 312 | "polyval_result_xor_nonce": "90187a2d224eb9d417eb893d6b42739c", 313 | "polyval_result_xor_nonce_masked": "90187a2d224eb9d417eb893d6b42731c", 314 | "tag": "404099c2587f64979f21826706d497d5", 315 | "initial_counter": "404099c2587f64979f21826706d497d5", 316 | "result": "8dbeb9f7255bf5769dd56692404099c2587f64979f21826706d497d5" 317 | }, 318 | { 319 | "plaintext": "21702de0de18baa9c9596291b08466", 320 | "aad": "f37de21c7ff901cfe8a69615a93fdf7a98cad481796245709f", 321 | "key": "9745b3d1ae06556fb6aa7890bebc18fe6b3db4da3d57aa94842b9803a96e07fb", 322 | "nonce": "6de71860f762ebfbd08284e4", 323 | "record_authentication_key": "27c2959ed4daea3b1f52e849478de376", 324 | "record_encryption_key": "307a38a5a6cf231c0a9af3b527f23a62e9a6ff09aff8ae669f760153e864fc93", 325 | "polyval_input": "f37de21c7ff901cfe8a69615a93fdf7a98cad481796245709f0000000000000021702de0de18baa9c9596291b0846600c8000000000000007800000000000000", 326 | "polyval_result": "c4fa5e5b713853703bcf8e6424505fa5", 327 | "polyval_result_xor_nonce": "a91d463b865ab88beb4d0a8024505fa5", 328 | "polyval_result_xor_nonce_masked": "a91d463b865ab88beb4d0a8024505f25", 329 | "tag": "b3080d28f6ebb5d3648ce97bd5ba67fd", 330 | "initial_counter": "b3080d28f6ebb5d3648ce97bd5ba67fd", 331 | "result": "793576dfa5c0f88729a7ed3c2f1bffb3080d28f6ebb5d3648ce97bd5ba67fd" 332 | }, 333 | { 334 | "plaintext": "b202b370ef9768ec6561c4fe6b7e7296fa85", 335 | "aad": "9c2159058b1f0fe91433a5bdc20e214eab7fecef4454a10ef0657df21ac7", 336 | "key": "b18853f68d833640e42a3c02c25b64869e146d7b233987bddfc240871d7576f7", 337 | "nonce": "028ec6eb5ea7e298342a94d4", 338 | "record_authentication_key": "670b98154076ddb59b7a9137d0dcc0f0", 339 | "record_encryption_key": "78116d78507fbe69d4a820c350f55c7cb36c3c9287df0e9614b142b76a587c3f", 340 | "polyval_input": "9c2159058b1f0fe91433a5bdc20e214eab7fecef4454a10ef0657df21ac70000b202b370ef9768ec6561c4fe6b7e7296fa850000000000000000000000000000f0000000000000009000000000000000", 341 | "polyval_result": "4e4108f09f41d797dc9256f8da8d58c7", 342 | "polyval_result_xor_nonce": "4ccfce1bc1e6350fe8b8c22cda8d58c7", 343 | "polyval_result_xor_nonce_masked": "4ccfce1bc1e6350fe8b8c22cda8d5847", 344 | "tag": "454fc2a154fea91f8363a39fec7d0a49", 345 | "initial_counter": "454fc2a154fea91f8363a39fec7d0ac9", 346 | "result": "857e16a64915a787637687db4a9519635cdd454fc2a154fea91f8363a39fec7d0a49" 347 | }, 348 | { 349 | "plaintext": "ced532ce4159b035277d4dfbb7db62968b13cd4eec", 350 | "aad": "734320ccc9d9bbbb19cb81b2af4ecbc3e72834321f7aa0f70b7282b4f33df23f167541", 351 | "key": "3c535de192eaed3822a2fbbe2ca9dfc88255e14a661b8aa82cc54236093bbc23", 352 | "nonce": "688089e55540db1872504e1c", 353 | "record_authentication_key": "cb8c3aa3f8dbaeb4b28a3e86ff6625f8", 354 | "record_encryption_key": "02426ce1aa3ab31313b0848469a1b5fc6c9af9602600b195b04ad407026bc06d", 355 | "polyval_input": "734320ccc9d9bbbb19cb81b2af4ecbc3e72834321f7aa0f70b7282b4f33df23f16754100000000000000000000000000ced532ce4159b035277d4dfbb7db62968b13cd4eec00000000000000000000001801000000000000a800000000000000", 356 | "polyval_result": "ffd503c7dd712eb3791b7114b17bb0cf", 357 | "polyval_result_xor_nonce": "97558a228831f5ab0b4b3f08b17bb0cf", 358 | "polyval_result_xor_nonce_masked": "97558a228831f5ab0b4b3f08b17bb04f", 359 | "tag": "9d6c7029675b89eaf4ba1ded1a286594", 360 | "initial_counter": "9d6c7029675b89eaf4ba1ded1a286594", 361 | "result": "626660c26ea6612fb17ad91e8e767639edd6c9faee9d6c7029675b89eaf4ba1ded1a286594" 362 | } 363 | ] 364 | } -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | AES-GCM-SIV 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 | 55 | 56 | 63 |
64 | 606 | 607 |
608 |
609 | 618 |
619 |
620 | 621 | 622 | 623 | 624 | 625 | 626 | --------------------------------------------------------------------------------