Skip to content

Commit 86d5134

Browse files
committed
A first attempt of new cryptography.
1 parent 08c0f27 commit 86d5134

2 files changed

Lines changed: 295 additions & 281 deletions

File tree

src/Berrysoft.Tsinghua.Net/AuthHelper.cs

Lines changed: 3 additions & 278 deletions
Original file line numberDiff line numberDiff line change
@@ -100,30 +100,11 @@ private async Task<string> GetChallengeAsync()
100100
/// Get login data with username, password and "challenge".
101101
/// </summary>
102102
/// <returns>A dictionary contains the data.</returns>
103-
/// <remarks>
104-
/// This is a function translated from javascript.
105-
/// <code language="JavaScript"><![CDATA[
106-
/// jQuery.getJSON(url.replace("srun_portal", "get_challenge"), { "username": $data.username, "ip": $data.ip, "double_stack": "1" }, function(data) {
107-
/// var token = "";
108-
/// if (data.res != "ok") {
109-
/// alert(data.error);
110-
/// return;
111-
/// }
112-
/// token = data.challenge;
113-
/// $data.info = "{SRBX1}" + base64.encode(jQuery.xEncode(JSON.stringify({ "username": $data.username, "password": $data.password, "ip": $data.ip, "acid": $data.ac_id, "enc_ver": enc}), token));
114-
/// var hmd5 = new Hashes.MD5().hex_hmac(token, data.password);
115-
/// $data.password = "{MD5}" + hmd5;
116-
/// $data.chksum = new Hashes.SHA1().hex(token + $data.username + token + hmd5 + token + $data.ac_id + token + $data.ip + token + n + token + type + token + $data.info);
117-
/// $data.n = n;
118-
/// $data.type = type;
119-
/// return get(url, $data, callback, "jsonp");
120-
/// });
121-
/// ]]></code>
122-
/// </remarks>
123103
private async Task<Dictionary<string, string>> GetLoginDataAsync()
124104
{
125-
const string passwordMD5 = "5e543256c480ac577d30f76f9120eb74";
105+
//const string passwordMD5 = "5e543256c480ac577d30f76f9120eb74";
126106
string token = await GetChallengeAsync();
107+
string passwordMD5 = CryptographyHelper.GetHMACMD5(token);
127108
if (loginDataDictionary == null)
128109
{
129110
loginDataDictionary = new Dictionary<string, string>
@@ -136,267 +117,11 @@ private async Task<Dictionary<string, string>> GetLoginDataAsync()
136117
["password"] = "{MD5}" + passwordMD5
137118
};
138119
}
139-
loginDataDictionary["info"] = "{SRBX1}" + Base64Encode(XEncode(string.Format(LoginInfoJson, Username, Password), token));
120+
loginDataDictionary["info"] = "{SRBX1}" + CryptographyHelper.Base64Encode(CryptographyHelper.XEncode(string.Format(LoginInfoJson, Username, Password), token));
140121
loginDataDictionary["username"] = Username;
141122
loginDataDictionary["chksum"] = CryptographyHelper.GetSHA1(string.Format(ChkSumData, token, Username, passwordMD5, loginDataDictionary["info"]));
142123
return loginDataDictionary;
143124
}
144-
#region Encode methods
145-
/// <summary>
146-
/// Encode a <see cref="string"/> to its UTF-8 form.
147-
/// </summary>
148-
/// <param name="a">String to be encoded.</param>
149-
/// <param name="b">Whether to add the length of the string in the end.</param>
150-
/// <returns>A <see cref="uint"/> array contains encoded string.</returns>
151-
/// <remarks>
152-
/// This is a function translated from javascript.
153-
/// <code language="JavaScript"><![CDATA[
154-
/// function s(a, b) {
155-
/// var c = a.length,
156-
/// v = [];
157-
/// for (var i = 0; i < c; i += 4) {
158-
/// v[i >> 2] = a.charCodeAt(i) | a.charCodeAt(i + 1) << 8 | a.charCodeAt(i + 2) << 16 | a.charCodeAt(i + 3) << 24;
159-
/// }
160-
/// if (b) {
161-
/// v[v.length] = c;
162-
/// }
163-
/// return v;
164-
/// }
165-
/// ]]></code>
166-
/// </remarks>
167-
private static unsafe uint[] S(string a, bool b)
168-
{
169-
int c = a.Length;
170-
int n = c / 4;
171-
n += c % 4 != 0 ? 1 : 0;
172-
//Array is 30 times faster than stack array and Encoding.GetBytes().
173-
uint[] v;
174-
if (b)
175-
{
176-
v = new uint[n + 1];
177-
v[n] = (uint)c;
178-
}
179-
else
180-
{
181-
v = new uint[n >= 4 ? n : 4];
182-
}
183-
fixed (uint* pv = v)
184-
{
185-
byte* pb = (byte*)pv;
186-
for (int i = 0; i < c; i++)
187-
{
188-
pb[i] = (byte)a[i];
189-
}
190-
}
191-
return v;
192-
}
193-
/// <summary>
194-
/// Decode a <see cref="string"/> from its UTF-8 form.
195-
/// </summary>
196-
/// <param name="a">A <see cref="uint"/> array contains the encoded string.</param>
197-
/// <param name="b">Whether the length of the original string is in the end.</param>
198-
/// <returns>Decoded string.</returns>
199-
/// <remarks>
200-
/// This is a function translated from javascript.
201-
/// <code language="JavaScript"><![CDATA[
202-
/// function l(a, b) {
203-
/// var d = a.length,
204-
/// c = (d - 1) << 2;
205-
/// if (b) {
206-
/// var m = a[d - 1];
207-
/// if ((m<c - 3) || (m > c))
208-
/// return null;
209-
/// c = m;
210-
/// }
211-
/// for (var i = 0; i < d; i++) {
212-
/// a[i] = String.fromCharCode(a[i] & 0xff, a[i] >>> 8 & 0xff, a[i] >>> 16 & 0xff, a[i] >>> 24 & 0xff);
213-
/// }
214-
/// if (b) {
215-
/// return a.join('').substring(0, c);
216-
/// } else {
217-
/// return a.join('');
218-
/// }
219-
/// }
220-
/// ]]></code>
221-
/// </remarks>
222-
private static unsafe string L(uint[] a, bool b)
223-
{
224-
int d = a.Length;
225-
uint c = ((uint)(d - 1)) << 2;
226-
if (b)
227-
{
228-
uint m = a[d - 1];
229-
if (m < c - 3 || m > c)
230-
{
231-
return null;
232-
}
233-
c = m;
234-
}
235-
fixed (uint* pa = a)
236-
{
237-
byte* pb = (byte*)pa;
238-
int n = d << 2;
239-
//When the return string needs subtracted, stack array is a little faster than array;
240-
//otherwise, array is 1.2 times faster than stack array.
241-
char[] aa = new char[n];
242-
for (int i = 0; i < n; i++)
243-
{
244-
aa[i] = (char)pb[i];
245-
}
246-
if (b)
247-
{
248-
return new string(aa, 0, (int)c);
249-
}
250-
else
251-
{
252-
return new string(aa);
253-
}
254-
}
255-
}
256-
/// <summary>
257-
/// Encode a string by a special TEA algorithm.
258-
/// </summary>
259-
/// <param name="str">String to be encoded.</param>
260-
/// <param name="key">Key to encode.</param>
261-
/// <returns>Encoded string.</returns>
262-
/// <remarks>
263-
/// This is a function translated from javascript.
264-
/// <code language="JavaScript"><![CDATA[
265-
/// xEncode: function(str, key) {
266-
/// if (str == "") {
267-
/// return "";
268-
/// }
269-
/// var v = s(str, true),
270-
/// k = s(key, false);
271-
/// if (k.length < 4) {
272-
/// k.length = 4;
273-
/// }
274-
/// var n = v.length - 1,
275-
/// z = v[n],
276-
/// y = v[0],
277-
/// c = 0x86014019 | 0x183639A0,
278-
/// m,
279-
/// e,
280-
/// p,
281-
/// q = Math.floor(6 + 52 / (n + 1)),
282-
/// d = 0;
283-
/// while (0 < q--) {
284-
/// d = d + c & (0x8CE0D9BF | 0x731F2640);
285-
/// e = d >>> 2 & 3;
286-
/// for (p = 0; p<n; p++) {
287-
/// y = v[p + 1];
288-
/// m = z >>> 5 ^ y << 2;
289-
/// m += (y >>> 3 ^ z << 4) ^ (d ^ y);
290-
/// m += k[(p & 3) ^ e] ^ z;
291-
/// z = v[p] = v[p] + m & (0xEFB8D130 | 0x10472ECF);
292-
/// }
293-
/// y = v[0];
294-
/// m = z >>> 5 ^ y << 2;
295-
/// m += (y >>> 3 ^ z << 4) ^ (d ^ y);
296-
/// m += k[(p & 3) ^ e] ^ z;
297-
/// z = v[n] = v[n] + m & (0xBB390742 | 0x44C6F8BD);
298-
/// }
299-
/// return l(v, false);
300-
/// }
301-
/// ]]></code>
302-
/// </remarks>
303-
private static string XEncode(string str, string key)
304-
{
305-
if (str.Length == 0)
306-
{
307-
return string.Empty;
308-
}
309-
uint[] v = S(str, true);
310-
uint[] k = S(key, false);
311-
int n = v.Length - 1;
312-
uint z = v[n];
313-
uint y = v[0];
314-
int q = 6 + 52 / (n + 1);
315-
uint d = 0;
316-
while (q-- > 0)
317-
{
318-
d += 0x9E3779B9;
319-
uint e = (d >> 2) & 3;
320-
for (int p = 0; p <= n; p++)
321-
{
322-
y = v[p == n ? 0 : p + 1];
323-
uint m = (z >> 5) ^ (y << 2);
324-
m += (y >> 3) ^ (z << 4) ^ (d ^ y);
325-
m += k[(p & 3) ^ (int)e] ^ z;
326-
z = v[p] += m;
327-
}
328-
}
329-
return L(v, false);
330-
}
331-
332-
private static readonly string Base64N = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA";
333-
/// <summary>
334-
/// Encode a string to base64 in a special way.
335-
/// </summary>
336-
/// <param name="t">String to be encoded.</param>
337-
/// <returns>Encoded string.</returns>
338-
/// <remarks>
339-
/// This is a function translated from javascript.
340-
/// <code language="JavaScript"><![CDATA[
341-
/// Base64: function() {
342-
/// var n = "LVoJPiCN2R8G90yg+hmFHuacZ1OWMnrsSTXkYpUq/3dlbfKwv6xztjI7DeBE45QA",
343-
/// r = "=",
344-
/// o = false,
345-
/// f = false;
346-
/// this.encode = function(t) {
347-
/// var o,
348-
/// i,
349-
/// h,
350-
/// u = "",
351-
/// a = t.length;
352-
/// r = r || "=";
353-
/// t = f ? e(t) : t;
354-
/// for (o = 0; o < a; o += 3) {
355-
/// h = t.charCodeAt(o) << 16 | (o + 1 < a ? t.charCodeAt(o+1) << 8 : 0) | (o + 2 < a ? t.charCodeAt(o+2) : 0);
356-
/// for ( i = 0; i < 4; i += 1) {
357-
/// if (o * 8 + i * 6 > a * 8) {
358-
/// u += r
359-
/// } else {
360-
/// u += n.charAt(h >>> 6 * (3 - i) & 63)
361-
/// }
362-
/// }
363-
/// }
364-
/// return u
365-
/// };
366-
/// }
367-
/// ]]></code>
368-
/// </remarks>
369-
private unsafe static string Base64Encode(string t)
370-
{
371-
int a = t.Length;
372-
int len = a / 3 * 4;
373-
len += a % 3 != 0 ? 4 : 0;
374-
//Stack array is 30 times faster than array, StringBuilder and Converter.ToBase64String().
375-
char* u = stackalloc char[len];
376-
char r = '=';
377-
int h = 0;
378-
byte* p = (byte*)&h;
379-
int ui = 0;
380-
for (int o = 0; o < a; o += 3)
381-
{
382-
p[2] = (byte)t[o];
383-
p[1] = (byte)(o + 1 < a ? t[o + 1] : 0);
384-
p[0] = (byte)(o + 2 < a ? t[o + 2] : 0);
385-
for (int i = 0; i < 4; i += 1)
386-
{
387-
if (o * 8 + i * 6 > a * 8)
388-
{
389-
u[ui++] = r;
390-
}
391-
else
392-
{
393-
u[ui++] = Base64N[h >> 6 * (3 - i) & 0x3F];
394-
}
395-
}
396-
}
397-
return new string(u, 0, len);
398-
}
399-
#endregion
400125
}
401126
/// <summary>
402127
/// Exposes methods to login, logout and get flux from https://auth4.tsinghua.edu.cn/.

0 commit comments

Comments
 (0)