forked from mh884/LoadOpenSSLPublicKeyAndEncryptWithRSA
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LoadOpenSSLPublicKeyAndEncryptWithRSA.cs
151 lines (128 loc) · 7.35 KB
/
LoadOpenSSLPublicKeyAndEncryptWithRSA.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
141
142
143
144
145
146
147
148
149
150
151
/// <summary>
/// Method for encrypting URL parameters for prefilling a fast form.
/// Returns an encrypted string to be passed into your Fast Form page URL
/// in the format of dp={encrypted string}.
/// </summary>
/// <param name="dataToEncrypt">
/// The URL string to encrypt. String takes the format of fieldname='fieldvalue', with multiple fields separated by an ampersand.
/// </param>
public static string Encrypt(string DataToEncrypt)
{
string publicKey = "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCQ2dLQ0FRRUFzc2ppREMwM1FkVGUwSllZVjBQVAo2SnhFL01WUXpxQjN5d2E0R2Vpd2RodzNvRnpYbjN3S0o0K01ybE9PcmhMOHdwWnJ0R3pBQ05tVlNnbVZtV1ozCklDcTZuNkpzcmNpSjNXQlBkVDNOVlBxVU9FaG4vTlJPUWVvSDRIdm5hdWh2L09STGhCeDByWlluYXV3TnR6RE8KNS9Md2pTUVRUb3lCV0xOWExoc1VaUGt3ak1ROE1XbnZ2a3RkNHlGZ082RWxRek9Va0xJdTFBQjltVmdYKzRGcwpzYXNPYlN5WUlraTNnQ1NrUTZQTzk3TnBTcHhjTVNlTHdqOHRDc3h0bXFwSnliWEZ5TWhtNC9ZOWJ2eEtKM01oCndHVmZxbk5RZzF6bksvQkozOFZmdmtYeFN6bytvRlJsSHZqUjc2OGhiYkVjOHViVUh6L1VIZlFOb0FraDJnZTAKdVFJREFRQUIKLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==";
string decodedkey = System.Text.Encoding.UTF8.GetString(System.Convert.FromBase64String(publicKey));
var x509Key = DecodeOpenSSLPublicKey(decodedkey);
RSA rsa = CreateRsaProviderFromPublicKey(x509Key);
var EncryptResult = rsa.Encrypt(Encoding.UTF8.GetBytes(DataToEncrypt), RSAEncryptionPadding.OaepSHA1);
return HttpUtility.UrlEncode(Convert.ToBase64String(EncryptResult));
}
static byte[] DecodeOpenSSLPublicKey(String instr)
{
const String pempubheader = "-----BEGIN PUBLIC KEY-----";
const String pempubfooter = "-----END PUBLIC KEY-----";
String pemstr = instr.Trim();
byte[] binkey;
if (!pemstr.StartsWith(pempubheader) || !pemstr.EndsWith(pempubfooter))
return null;
StringBuilder sb = new StringBuilder(pemstr);
sb.Replace(pempubheader, ""); //remove headers/footers, if present
sb.Replace(pempubfooter, "");
String pubstr = sb.ToString().Trim(); //get string after removing leading/trailing whitespace
try
{
binkey = Convert.FromBase64String(pubstr);
}
catch (System.FormatException)
{ //if can't b64 decode, data is not valid
return null;
}
return binkey;
}
private static bool CompareBytearrays(byte[] a, byte[] b)
{
if (a.Length != b.Length)
return false;
int i = 0;
foreach (byte c in a)
{
if (c != b[i])
return false;
i++;
}
return true;
}
private static RSA CreateRsaProviderFromPublicKey(byte[] x509Key)
{
// encoded OID sequence for PKCS #1 rsaEncryption szOID_RSA_RSA = "1.2.840.113549.1.1.1"
byte[] seqOid = { 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00 };
byte[] seq = new byte[15];
// --------- Set up stream to read the asn.1 encoded SubjectPublicKeyInfo blob ------
using (MemoryStream mem = new MemoryStream(x509Key))
{
using (BinaryReader binr = new BinaryReader(mem)) //wrap Memory Stream with BinaryReader for easy reading
{
byte bt = 0;
ushort twobytes = 0;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
seq = binr.ReadBytes(15); //read the Sequence OID
if (!CompareBytearrays(seq, seqOid)) //make sure Sequence for OID is correct
return null;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8103) //data read as little endian order (actual data order for Bit String is 03 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8203)
binr.ReadInt16(); //advance 2 bytes
else
return null;
bt = binr.ReadByte();
if (bt != 0x00) //expect null byte next
return null;
twobytes = binr.ReadUInt16();
if (twobytes == 0x8130) //data read as little endian order (actual data order for Sequence is 30 81)
binr.ReadByte(); //advance 1 byte
else if (twobytes == 0x8230)
binr.ReadInt16(); //advance 2 bytes
else
return null;
twobytes = binr.ReadUInt16();
byte lowbyte = 0x00;
byte highbyte = 0x00;
if (twobytes == 0x8102) //data read as little endian order (actual data order for Integer is 02 81)
lowbyte = binr.ReadByte(); // read next bytes which is bytes in modulus
else if (twobytes == 0x8202)
{
highbyte = binr.ReadByte(); //advance 2 bytes
lowbyte = binr.ReadByte();
}
else
return null;
byte[] modint = { lowbyte, highbyte, 0x00, 0x00 }; //reverse byte order since asn.1 key uses big endian order
int modsize = BitConverter.ToInt32(modint, 0);
int firstbyte = binr.PeekChar();
if (firstbyte == 0x00)
{ //if first byte (highest order) of modulus is zero, don't include it
binr.ReadByte(); //skip this null byte
modsize -= 1; //reduce modulus buffer size by 1
}
byte[] modulus = binr.ReadBytes(modsize); //read the modulus bytes
if (binr.ReadByte() != 0x02) //expect an Integer for the exponent data
return null;
int expbytes = (int)binr.ReadByte(); // should only need one byte for actual exponent data (for all useful values)
byte[] exponent = binr.ReadBytes(expbytes);
// ------- create RSACryptoServiceProvider instance and initialize with public key -----
var rsa = System.Security.Cryptography.RSA.Create();
RSAParameters rsaKeyInfo = new RSAParameters
{
Modulus = modulus,
Exponent = exponent
};
rsa.ImportParameters(rsaKeyInfo);
return rsa;
}
}
}