This repository has been archived by the owner on Aug 2, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 344
/
CosmosDbAuthorizationHeader.cs
110 lines (94 loc) · 4.32 KB
/
CosmosDbAuthorizationHeader.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Binary.Base64Experimental;
using System.Buffers;
using System.Buffers.Cryptography;
using System.Buffers.Text;
using System.Buffers.Writer;
using System.Text.Encodings.Web.Utf8;
using System.Text.Utf8;
using static System.Buffers.Text.TextEncodings;
namespace System.Azure.Authentication
{
public struct CosmosDbAuthorizationHeader : IBufferFormattable {
public Sha256 Hash;
public string KeyType;
public string Method;
public string ResourceId;
public string ResourceType;
public string Version;
public DateTime Time;
private static TransformationFormat s_toBase64 = new TransformationFormat(Base64Experimental.BytesToUtf8Encoder);
private static TransformationFormat s_toLower = new TransformationFormat(Ascii.ToLowercase);
public static bool TryWrite(Span<byte> output, Sha256 hash, string keyType, string verb, string resourceId, string resourceType, string tokenVersion, DateTime utc, out int bytesWritten)
{
Span<byte> buffer = stackalloc byte[AuthenticationHeaderBufferSize];
var writer = BufferWriter.Create(buffer);
writer.Enlarge = (minumumSize) => { return new byte[minumumSize * 2]; };
// compute signature hash
writer.WriteLine(verb, s_toLower);
writer.WriteLine(resourceType, s_toLower);
writer.WriteLine(resourceId, s_toLower);
writer.WriteLine(utc, 'l');
writer.Write('\n');
hash.Append(writer.Written);
// combine token
writer.WrittenCount = 0; // reuse writer and buffer
writer.Write("type=");
writer.Write(keyType);
writer.Write("&ver=");
writer.Write(tokenVersion);
writer.Write("&sig=");
writer.WriteBytes(hash, s_toBase64);
if (UrlEncoder.Utf8.Encode(writer.Written, output, out var consumed, out bytesWritten) != OperationStatus.Done)
{
bytesWritten = 0;
return false;
}
return true;
}
public static bool TryWrite(Span<byte> output, Sha256 hash, Utf8Span keyType, Utf8Span verb, Utf8Span resourceId, Utf8Span resourceType, Utf8Span tokenVersion, DateTime utc, out int bytesWritten)
{
Span<byte> buffer = stackalloc byte[AuthenticationHeaderBufferSize];
var writer = BufferWriter.Create(buffer);
writer.Enlarge = (minumumSize) => { return new byte[minumumSize * 2]; };
// compute signature hash
writer.WriteLine(verb, s_toLower);
writer.WriteLine(resourceType, s_toLower);
writer.WriteLine(resourceId, s_toLower);
writer.WriteLine(utc, 'l');
writer.Write('\n');
hash.Append(writer.Written);
// combine token
writer.WrittenCount = 0; // reuse writer and buffer
writer.Write(s_typeLiteral);
writer.Write(keyType);
writer.Write(s_verLiteral);
writer.Write(tokenVersion);
writer.Write(s_sigLiteral);
writer.WriteBytes(hash, s_toBase64);
if (UrlEncoder.Utf8.Encode(writer.Written, output, out var consumed, out bytesWritten) != OperationStatus.Done)
{
bytesWritten = 0;
return false;
}
return true;
}
public bool TryFormat(Span<byte> buffer, out int written, StandardFormat format = default, SymbolTable symbolTable = null)
{
if (TryWrite(buffer, Hash, KeyType, Method, ResourceId, ResourceType, Version, Time, out written))
{
return true;
}
buffer.Clear();
written = 0;
return false;
}
const int AuthenticationHeaderBufferSize = 256;
// These will go away once we have UTF8 literals in the language
static readonly Utf8String s_typeLiteral = (Utf8String)"type=";
static readonly Utf8String s_verLiteral = (Utf8String)"&ver=";
static readonly Utf8String s_sigLiteral = (Utf8String)"&sig=";
}
}