短信验证码

代码源自 Microsoft.AspNet.Identity 程序集.

 1 using System;
 2 using System.Net;
 3 using System.Security.Cryptography;
 4 using System.Text;
 5 
 6 namespace Authentication
 7 {
 8     internal static class Rfc6238AuthenticationService
 9     {
10         private static readonly DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
11         private static readonly TimeSpan _timestep = TimeSpan.FromMinutes(3.0);
12         private static readonly Encoding _encoding = new UTF8Encoding(false, true);
13 
14         private static int ComputeTotp(HashAlgorithm hashAlgorithm, ulong timestepNumber, string modifier)
15         {
16             byte[] bytes = BitConverter.GetBytes(IPAddress.HostToNetworkOrder((long)timestepNumber));
17             byte[] array = hashAlgorithm.ComputeHash(ApplyModifier(bytes, modifier));
18             int num = (int)(array[array.Length - 1] & 15);
19             int num2 = (int)(array[num] & 127) << 24 | (int)(array[num + 1] & 255) << 16 |
20                        (int)(array[num + 2] & 255) << 8 | (int)(array[num + 3] & 255);
21             return num2 % 1000000;
22         }
23 
24         private static byte[] ApplyModifier(byte[] input, string modifier)
25         {
26             if (string.IsNullOrEmpty(modifier))
27             {
28                 return input;
29             }
30             byte[] bytes = _encoding.GetBytes(modifier);
31             byte[] array = new byte[checked(input.Length + bytes.Length)];
32             Buffer.BlockCopy(input, 0, array, 0, input.Length);
33             Buffer.BlockCopy(bytes, 0, array, input.Length, bytes.Length);
34             return array;
35         }
36 
37         private static ulong GetCurrentTimeStepNumber()
38         {
39             return
40                 (ulong)
41                     ((DateTime.UtcNow - _unixEpoch).Ticks /
42                      _timestep.Ticks);
43         }
44 
45         public static int GenerateCode(SecurityToken securityToken, string modifier = null)
46         {
47             if (securityToken == null)
48             {
49                 throw new ArgumentNullException("securityToken");
50             }
51             ulong currentTimeStepNumber = GetCurrentTimeStepNumber();
52             int result;
53             using (HMACSHA1 hMACSHA = new HMACSHA1(securityToken.GetDataNoClone()))
54             {
55                 result = ComputeTotp(hMACSHA, currentTimeStepNumber, modifier);
56             }
57             return result;
58         }
59     }
60 
61     internal sealed class SecurityToken
62     {
63         private readonly byte[] _data;
64         public SecurityToken(byte[] data)
65         {
66             this._data = (byte[])data.Clone();
67         }
68         internal byte[] GetDataNoClone()
69         {
70             return this._data;
71         }
72     }
73 }
View Code

 

var stampCode ="123";

var code = Rfc6238AuthenticationService.GenerateCode(new SecurityToken(Encoding.Unicode.GetBytes(stampCode)));

 

生成时需要更换种子 stampCode。

posted @ 2016-03-02 14:00  奔跑的Code  阅读(441)  评论(0编辑  收藏  举报