-
Notifications
You must be signed in to change notification settings - Fork 0
/
SignedContainer.cs
140 lines (113 loc) · 5.05 KB
/
SignedContainer.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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.IO;
using System.Text;
using System.Runtime.Serialization;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using System.Runtime.Serialization.Json;
namespace Vault
{
public class NoCertWithPrivateKeyException : Exception
{
public NoCertWithPrivateKeyException(string message) : base(message) { }
}
public class NoCertFoundException : Exception
{
public NoCertFoundException(string message) : base(message) { }
}
[DataContract]
public class SignedContainer
{
[DataMember]
internal Container container;
[DataMember]
internal string thumbprint;
[DataMember]
internal string signature;
public UriBuilder GetURL()
{
return new UriBuilder(container.url);
}
public string GetUserName()
{
return container.username;
}
public string GetCertificateThumbprint()
{
return thumbprint;
}
public string GetCertificateSubject()
{
return container.certificateSubject;
}
public DateTime GetCreatedDateTime() {
return container.created;
}
public SignedContainer(UriBuilder url, string username, string password)
{
X509Store store = new X509Store("MY", StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection certsOnlyWithPrivateKey = new X509Certificate2Collection();
foreach (X509Certificate2 cert in collection)
{
if (cert.HasPrivateKey)
{
certsOnlyWithPrivateKey.Add(cert);
}
}
X509Certificate2Collection fcollection = (X509Certificate2Collection)certsOnlyWithPrivateKey.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection scollection = X509Certificate2UI.SelectFromCollection(
fcollection,
string.Format("Select certificate to protect your credentials for {0}", url),
"Select a certificate from the following list", X509SelectionFlag.SingleSelection);
if (scollection.Count == 0)
{
throw new NoCertWithPrivateKeyException("to sign, encrypt and store your credentials you have to choose appropriate certificate with private key");
}
var certificate = scollection[0];
var encryptedPassword = Convert.ToBase64String(certificate.GetRSAPublicKey().Encrypt((new UTF8Encoding()).GetBytes(password), RSAEncryptionPadding.OaepSHA512));
var csp = certificate.GetRSAPrivateKey();
if (csp == null)
{
throw new NoCertFoundException("no valid cert was found");
}
container = new Container(url, username, encryptedPassword, certificate.Subject);
this.signature = Convert.ToBase64String(csp.SignData((new UTF8Encoding()).GetBytes(container.ToJSON()), HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1));
this.thumbprint = certificate.Thumbprint;
}
internal X509Certificate2 getCertificate(string thumbprint)
{
X509Store certsStore = new X509Store("MY", StoreLocation.CurrentUser);
certsStore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)certsStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (collection.Count < 1)
{
throw new NoCertFoundException(string.Format("Could not found certificate {0}({1}) to check container signature", container.certificateSubject, thumbprint));
}
return collection[0];
}
internal bool SignatureIsCorrect()
{
return getCertificate(thumbprint).GetRSAPublicKey().VerifyData((new UTF8Encoding()).GetBytes(container.ToJSON()), System.Convert.FromBase64String(signature), HashAlgorithmName.SHA512, RSASignaturePadding.Pkcs1);
}
internal string GetDecryptedPassword()
{
return System.Text.Encoding.UTF8.GetString(
getCertificate(thumbprint).GetRSAPrivateKey().Decrypt(System.Convert.FromBase64String(container.password), RSAEncryptionPadding.OaepSHA512)
);
}
internal string ToJSON()
{
MemoryStream stream = new MemoryStream();
var serializer = new DataContractJsonSerializer(typeof(SignedContainer), new DataContractJsonSerializerSettings()
{
UseSimpleDictionaryFormat = true
});
serializer.WriteObject(stream, this);
stream.Position = 0;
StreamReader streamReader = new StreamReader(stream);
return streamReader.ReadToEnd();
}
}
}