Google Authenticator(谷歌身份验证器)C#版
<div>摘要:Google Authenticator(谷歌身份验证器),是谷歌公司推出的一款动态令牌工具,解决账户使用时遭到的一些不安全的操作进行的“二次验证”,认证器基于RFC文档中的HOTP/TOTP算法实现 ,是一种从共享秘钥和时间或次数一次性令牌的算法。在工作中可以通过认证器方式对账户有更好的保护,但是在查阅一些资料发现适合我这样的小白文章真的很少,针对于C#的文章就更加少了,本文主要是对C#如何使用Google Authenticator(谷歌身份验证器)进行探讨,有不足之处还请见谅。</div><h2>Google Authenticator(谷歌身份验证器)</h2>
<h3>什么是认证器?怎么对接?</h3>
<div>
<p>Google Authenticator(谷歌身份验证器)是微软推出的一个动态密令工具,它有两种密令模式。分别是“TOTP 基于时间”、“HOTP 基于计数器”,通过手机上 简单的设置就可以设定自己独一的动态密令, 那么我们怎么将我们的程序和认证器进行对接呢?其实谷歌认证器并不是需要我们对接这个工具的API而是通过算法来决定,谷歌使用使用HMAC算法生成密令,通过基于次数或者基于时间两个模板进行计算,因此在程序中只需要使用相同的算法即可与之匹配。</p>
</div>
<div>
<h4>TOTP 基于时间</h4>
<ul>
<li>HMAC算法使用固定为HmacSHA1</li>
<li>更新时长固定为30秒</li>
<li>APP端输入数据维度只有两个:账户名称(自己随意填写方便自己查看)和base32格式的key</li>
</ul>
</div>
<div>
<h4>HOTP 基于计数器</h4>
<p>基于计数器模式是根据一个共享秘钥K和一个C计数器进行算法计算</p>
</div>
<h3>认证器安装</h3>
<div>
<p>手机需要安装认证器:</p>
<ul>
<li>Android版:安卓版下载</li>
<li>IOS版:苹果版下载</li>
</ul>
</div>
<h3>效果图</h3>
<h3><img src="https://img2018.cnblogs.com/blog/1407129/201906/1407129-20190619224446456-757566347.gif" alt="" width="335" height="175"><img src="https://img2018.cnblogs.com/blog/1407129/201906/1407129-20190619224616709-1845395391.gif" alt="">容</h3>
<h3><span style="font-size: 1.5em">案例</span></h3>
<h3>控制台</h3>
<div>
<div class="cnblogs_code"><img id="code_img_closed_055caeba-c22e-44bf-bf70-51c2bd4c2a79" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_055caeba-c22e-44bf-bf70-51c2bd4c2a79" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_055caeba-c22e-44bf-bf70-51c2bd4c2a79" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Collections.Generic;
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Linq;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthenticator
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Program
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">void</span> Main(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">[] args)
</span><span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">long</span> duration = <span style="color: rgba(128, 0, 128, 1)">30</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">string</span> key = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xeon997@foxmail.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">14</span> GoogleAuthenticator authenticator = <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthenticator(duration, key);
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 255, 1)">var</span> mobileKey =<span style="color: rgba(0, 0, 0, 1)"> authenticator.GetMobilePhoneKey();
</span><span style="color: rgba(0, 128, 128, 1)">16</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 255, 1)">while</span> (<span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">19</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> Console.WriteLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">手机端秘钥为:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> mobileKey);
</span><span style="color: rgba(0, 128, 128, 1)">21</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 255, 1)">var</span> code =<span style="color: rgba(0, 0, 0, 1)"> authenticator.GenerateCode();
</span><span style="color: rgba(0, 128, 128, 1)">23</span> Console.WriteLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">动态验证码为:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> code);
</span><span style="color: rgba(0, 128, 128, 1)">24</span>
<span style="color: rgba(0, 128, 128, 1)">25</span> Console.WriteLine(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">刷新倒计时:</span><span style="color: rgba(128, 0, 0, 1)">"</span> +<span style="color: rgba(0, 0, 0, 1)"> authenticator.EXPIRE_SECONDS);
</span><span style="color: rgba(0, 128, 128, 1)">26</span>
<span style="color: rgba(0, 128, 128, 1)">27</span> System.Threading.Thread.Sleep(<span style="color: rgba(128, 0, 128, 1)">1000</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)"> Console.Clear();
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">32</span> }</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> </p>
</div>
<h3>认证器类</h3>
<div>
<div class="cnblogs_code"><img id="code_img_closed_53732977-0088-4141-97be-dd6488d5880b" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_53732977-0088-4141-97be-dd6488d5880b" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_53732977-0088-4141-97be-dd6488d5880b" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthorization;
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Security.Cryptography;
</span><span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System.Text;
</span><span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthenticator
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">7</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthenticator
</span><span style="color: rgba(0, 128, 128, 1)">8</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">9</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 10</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 初始化验证码生成规则
</span><span style="color: rgba(0, 128, 128, 1)"> 11</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 12</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="key"></span><span style="color: rgba(0, 128, 0, 1)">秘钥(手机使用Base32码)</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(0, 128, 128, 1)"> 13</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="duration"></span><span style="color: rgba(0, 128, 0, 1)">验证码间隔多久刷新一次(默认30秒和google同步)</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(0, 128, 128, 1)"> 14</span> <span style="color: rgba(0, 0, 255, 1)">public</span> GoogleAuthenticator(<span style="color: rgba(0, 0, 255, 1)">long</span> duration = <span style="color: rgba(128, 0, 128, 1)">30</span>, <span style="color: rgba(0, 0, 255, 1)">string</span> key = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">xeon997@foxmail.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 15</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 16</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.SERECT_KEY =<span style="color: rgba(0, 0, 0, 1)"> key;
</span><span style="color: rgba(0, 128, 128, 1)"> 17</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.SERECT_KEY_MOBILE =<span style="color: rgba(0, 0, 0, 1)"> Base32.ToString(Encoding.UTF8.GetBytes(key));
</span><span style="color: rgba(0, 128, 128, 1)"> 18</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.DURATION_TIME =<span style="color: rgba(0, 0, 0, 1)"> duration;
</span><span style="color: rgba(0, 128, 128, 1)"> 19</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 20</span>
<span style="color: rgba(0, 128, 128, 1)"> 21</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 22</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 间隔时间
</span><span style="color: rgba(0, 128, 128, 1)"> 23</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 24</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">long</span> DURATION_TIME { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)"> 25</span>
<span style="color: rgba(0, 128, 128, 1)"> 26</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 27</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 迭代次数
</span><span style="color: rgba(0, 128, 128, 1)"> 28</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 29</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> COUNTER
</span><span style="color: rgba(0, 128, 128, 1)"> 30</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 31</span> <span style="color: rgba(0, 0, 255, 1)">get</span>
<span style="color: rgba(0, 128, 128, 1)"> 32</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 33</span> <span style="color: rgba(0, 0, 255, 1)">return</span> (<span style="color: rgba(0, 0, 255, 1)">long</span>)(DateTime.UtcNow - <span style="color: rgba(0, 0, 255, 1)">new</span> DateTime(<span style="color: rgba(128, 0, 128, 1)">1970</span>, <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, DateTimeKind.Utc)).TotalSeconds /<span style="color: rgba(0, 0, 0, 1)"> DURATION_TIME;
</span><span style="color: rgba(0, 128, 128, 1)"> 34</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 35</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 36</span>
<span style="color: rgba(0, 128, 128, 1)"> 37</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 38</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 秘钥
</span><span style="color: rgba(0, 128, 128, 1)"> 39</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 40</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span> SERECT_KEY { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)"> 41</span>
<span style="color: rgba(0, 128, 128, 1)"> 42</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 43</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 手机端输入的秘钥
</span><span style="color: rgba(0, 128, 128, 1)"> 44</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 45</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span> SERECT_KEY_MOBILE { <span style="color: rgba(0, 0, 255, 1)">get</span>; <span style="color: rgba(0, 0, 255, 1)">set</span><span style="color: rgba(0, 0, 0, 1)">; }
</span><span style="color: rgba(0, 128, 128, 1)"> 46</span>
<span style="color: rgba(0, 128, 128, 1)"> 47</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 48</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 到期秒数
</span><span style="color: rgba(0, 128, 128, 1)"> 49</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 50</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">long</span><span style="color: rgba(0, 0, 0, 1)"> EXPIRE_SECONDS
</span><span style="color: rgba(0, 128, 128, 1)"> 51</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 52</span> <span style="color: rgba(0, 0, 255, 1)">get</span>
<span style="color: rgba(0, 128, 128, 1)"> 53</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 54</span> <span style="color: rgba(0, 0, 255, 1)">return</span> (DURATION_TIME - (<span style="color: rgba(0, 0, 255, 1)">long</span>)(DateTime.UtcNow - <span style="color: rgba(0, 0, 255, 1)">new</span> DateTime(<span style="color: rgba(128, 0, 128, 1)">1970</span>, <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">1</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, <span style="color: rgba(128, 0, 128, 1)">0</span>, DateTimeKind.Utc)).TotalSeconds %<span style="color: rgba(0, 0, 0, 1)"> DURATION_TIME);
</span><span style="color: rgba(0, 128, 128, 1)"> 55</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 56</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 57</span>
<span style="color: rgba(0, 128, 128, 1)"> 58</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 59</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 获取手机端秘钥
</span><span style="color: rgba(0, 128, 128, 1)"> 60</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 61</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></returns></span>
<span style="color: rgba(0, 128, 128, 1)"> 62</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> GetMobilePhoneKey()
</span><span style="color: rgba(0, 128, 128, 1)"> 63</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 64</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (SERECT_KEY_MOBILE == <span style="color: rgba(0, 0, 255, 1)">null</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 65</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ArgumentNullException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">SERECT_KEY_MOBILE</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 66</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> SERECT_KEY_MOBILE;
</span><span style="color: rgba(0, 128, 128, 1)"> 67</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 68</span>
<span style="color: rgba(0, 128, 128, 1)"> 69</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 70</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 生成认证码
</span><span style="color: rgba(0, 128, 128, 1)"> 71</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 72</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></span><span style="color: rgba(0, 128, 0, 1)">返回验证码</span><span style="color: rgba(128, 128, 128, 1)"></returns></span>
<span style="color: rgba(0, 128, 128, 1)"> 73</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> GenerateCode()
</span><span style="color: rgba(0, 128, 128, 1)"> 74</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 75</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> GenerateHashedCode(SERECT_KEY, COUNTER);
</span><span style="color: rgba(0, 128, 128, 1)"> 76</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 77</span>
<span style="color: rgba(0, 128, 128, 1)"> 78</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 79</span> <span style="color: rgba(128, 128, 128, 1)">///</span><span style="color: rgba(0, 128, 0, 1)"> 按照次数生成哈希编码
</span><span style="color: rgba(0, 128, 128, 1)"> 80</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"></summary></span>
<span style="color: rgba(0, 128, 128, 1)"> 81</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="secret"></span><span style="color: rgba(0, 128, 0, 1)">秘钥</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(0, 128, 128, 1)"> 82</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="iterationNumber"></span><span style="color: rgba(0, 128, 0, 1)">迭代次数</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(0, 128, 128, 1)"> 83</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><param name="digits"></span><span style="color: rgba(0, 128, 0, 1)">生成位数</span><span style="color: rgba(128, 128, 128, 1)"></param></span>
<span style="color: rgba(0, 128, 128, 1)"> 84</span> <span style="color: rgba(128, 128, 128, 1)">///</span> <span style="color: rgba(128, 128, 128, 1)"><returns></span><span style="color: rgba(0, 128, 0, 1)">返回验证码</span><span style="color: rgba(128, 128, 128, 1)"></returns></span>
<span style="color: rgba(0, 128, 128, 1)"> 85</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">string</span> GenerateHashedCode(<span style="color: rgba(0, 0, 255, 1)">string</span> secret, <span style="color: rgba(0, 0, 255, 1)">long</span> iterationNumber, <span style="color: rgba(0, 0, 255, 1)">int</span> digits = <span style="color: rgba(128, 0, 128, 1)">6</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 86</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 87</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] counter =<span style="color: rgba(0, 0, 0, 1)"> BitConverter.GetBytes(iterationNumber);
</span><span style="color: rgba(0, 128, 128, 1)"> 88</span>
<span style="color: rgba(0, 128, 128, 1)"> 89</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (BitConverter.IsLittleEndian)
</span><span style="color: rgba(0, 128, 128, 1)"> 90</span> <span style="color: rgba(0, 0, 0, 1)"> Array.Reverse(counter);
</span><span style="color: rgba(0, 128, 128, 1)"> 91</span>
<span style="color: rgba(0, 128, 128, 1)"> 92</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] key =<span style="color: rgba(0, 0, 0, 1)"> Encoding.ASCII.GetBytes(secret);
</span><span style="color: rgba(0, 128, 128, 1)"> 93</span>
<span style="color: rgba(0, 128, 128, 1)"> 94</span> HMACSHA1 hmac = <span style="color: rgba(0, 0, 255, 1)">new</span> HMACSHA1(key, <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 95</span>
<span style="color: rgba(0, 128, 128, 1)"> 96</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] hash =<span style="color: rgba(0, 0, 0, 1)"> hmac.ComputeHash(counter);
</span><span style="color: rgba(0, 128, 128, 1)"> 97</span>
<span style="color: rgba(0, 128, 128, 1)"> 98</span> <span style="color: rgba(0, 0, 255, 1)">int</span> offset = hash & <span style="color: rgba(128, 0, 128, 1)">0xf</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 99</span>
<span style="color: rgba(0, 128, 128, 1)">100</span> <span style="color: rgba(0, 0, 255, 1)">int</span> binary =
<span style="color: rgba(0, 128, 128, 1)">101</span> ((hash & <span style="color: rgba(128, 0, 128, 1)">0x7f</span>) << <span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">102</span> | ((hash & <span style="color: rgba(128, 0, 128, 1)">0xff</span>) << <span style="color: rgba(128, 0, 128, 1)">16</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">103</span> | ((hash & <span style="color: rgba(128, 0, 128, 1)">0xff</span>) << <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">104</span> | (hash & <span style="color: rgba(128, 0, 128, 1)">0xff</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">105</span>
<span style="color: rgba(0, 128, 128, 1)">106</span> <span style="color: rgba(0, 0, 255, 1)">int</span> password = binary % (<span style="color: rgba(0, 0, 255, 1)">int</span>)Math.Pow(<span style="color: rgba(128, 0, 128, 1)">10</span>, digits); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 6 digits</span>
<span style="color: rgba(0, 128, 128, 1)">107</span>
<span style="color: rgba(0, 128, 128, 1)">108</span> <span style="color: rgba(0, 0, 255, 1)">return</span> password.ToString(<span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">string</span>(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">0</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">, digits));
</span><span style="color: rgba(0, 128, 128, 1)">109</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">110</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">111</span> }</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> </p>
<p><span style="font-size: 1.17em">Base32转码类</span></p>
</div>
<div>
<div class="cnblogs_code"><img id="code_img_closed_333f57cc-4312-4d81-b388-a2b62a46b77a" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_333f57cc-4312-4d81-b388-a2b62a46b77a" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_333f57cc-4312-4d81-b388-a2b62a46b77a" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 255, 1)">using</span><span style="color: rgba(0, 0, 0, 1)"> System;
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 255, 1)">namespace</span><span style="color: rgba(0, 0, 0, 1)"> GoogleAuthorization
</span><span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Base32
</span><span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">6</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] ToBytes(<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)"> input)
</span><span style="color: rgba(0, 128, 128, 1)">7</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">8</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">.IsNullOrEmpty(input))
</span><span style="color: rgba(0, 128, 128, 1)">9</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 10</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ArgumentNullException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">input</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 11</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 12</span>
<span style="color: rgba(0, 128, 128, 1)"> 13</span> input = input.TrimEnd(<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">=</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 14</span> <span style="color: rgba(0, 0, 255, 1)">int</span> byteCount = input.Length * <span style="color: rgba(128, 0, 128, 1)">5</span> / <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 15</span> <span style="color: rgba(0, 0, 255, 1)">byte</span>[] returnArray = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 16</span>
<span style="color: rgba(0, 128, 128, 1)"> 17</span> <span style="color: rgba(0, 0, 255, 1)">byte</span> curByte = <span style="color: rgba(128, 0, 128, 1)">0</span>, bitsRemaining = <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 18</span> <span style="color: rgba(0, 0, 255, 1)">int</span> mask = <span style="color: rgba(128, 0, 128, 1)">0</span>, arrayIndex = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 19</span>
<span style="color: rgba(0, 128, 128, 1)"> 20</span> <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">char</span> c <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> input)
</span><span style="color: rgba(0, 128, 128, 1)"> 21</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 22</span> <span style="color: rgba(0, 0, 255, 1)">int</span> cValue =<span style="color: rgba(0, 0, 0, 1)"> CharToValue(c);
</span><span style="color: rgba(0, 128, 128, 1)"> 23</span>
<span style="color: rgba(0, 128, 128, 1)"> 24</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (bitsRemaining > <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 25</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 26</span> mask = cValue << (bitsRemaining - <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 27</span> curByte = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)(curByte |<span style="color: rgba(0, 0, 0, 1)"> mask);
</span><span style="color: rgba(0, 128, 128, 1)"> 28</span> bitsRemaining -= <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 29</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 30</span> <span style="color: rgba(0, 0, 255, 1)">else</span>
<span style="color: rgba(0, 128, 128, 1)"> 31</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 32</span> mask = cValue >> (<span style="color: rgba(128, 0, 128, 1)">5</span> -<span style="color: rgba(0, 0, 0, 1)"> bitsRemaining);
</span><span style="color: rgba(0, 128, 128, 1)"> 33</span> curByte = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)(curByte |<span style="color: rgba(0, 0, 0, 1)"> mask);
</span><span style="color: rgba(0, 128, 128, 1)"> 34</span> returnArray =<span style="color: rgba(0, 0, 0, 1)"> curByte;
</span><span style="color: rgba(0, 128, 128, 1)"> 35</span> curByte = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)(cValue << (<span style="color: rgba(128, 0, 128, 1)">3</span> +<span style="color: rgba(0, 0, 0, 1)"> bitsRemaining));
</span><span style="color: rgba(0, 128, 128, 1)"> 36</span> bitsRemaining += <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 37</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 38</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 39</span>
<span style="color: rgba(0, 128, 128, 1)"> 40</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (arrayIndex !=<span style="color: rgba(0, 0, 0, 1)"> byteCount)
</span><span style="color: rgba(0, 128, 128, 1)"> 41</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 42</span> returnArray =<span style="color: rgba(0, 0, 0, 1)"> curByte;
</span><span style="color: rgba(0, 128, 128, 1)"> 43</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 44</span>
<span style="color: rgba(0, 128, 128, 1)"> 45</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> returnArray;
</span><span style="color: rgba(0, 128, 128, 1)"> 46</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 47</span>
<span style="color: rgba(0, 128, 128, 1)"> 48</span> <span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">string</span> ToString(<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)">[] input)
</span><span style="color: rgba(0, 128, 128, 1)"> 49</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 50</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (input == <span style="color: rgba(0, 0, 255, 1)">null</span> || input.Length == <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 51</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 52</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ArgumentNullException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">input</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 53</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 54</span>
<span style="color: rgba(0, 128, 128, 1)"> 55</span> <span style="color: rgba(0, 0, 255, 1)">int</span> charCount = (<span style="color: rgba(0, 0, 255, 1)">int</span>)Math.Ceiling(input.Length / 5d) * <span style="color: rgba(128, 0, 128, 1)">8</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 56</span> <span style="color: rgba(0, 0, 255, 1)">char</span>[] returnArray = <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">char</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 57</span>
<span style="color: rgba(0, 128, 128, 1)"> 58</span> <span style="color: rgba(0, 0, 255, 1)">byte</span> nextChar = <span style="color: rgba(128, 0, 128, 1)">0</span>, bitsRemaining = <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 59</span> <span style="color: rgba(0, 0, 255, 1)">int</span> arrayIndex = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 60</span>
<span style="color: rgba(0, 128, 128, 1)"> 61</span> <span style="color: rgba(0, 0, 255, 1)">foreach</span> (<span style="color: rgba(0, 0, 255, 1)">byte</span> b <span style="color: rgba(0, 0, 255, 1)">in</span><span style="color: rgba(0, 0, 0, 1)"> input)
</span><span style="color: rgba(0, 128, 128, 1)"> 62</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 63</span> nextChar = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)(nextChar | (b >> (<span style="color: rgba(128, 0, 128, 1)">8</span> -<span style="color: rgba(0, 0, 0, 1)"> bitsRemaining)));
</span><span style="color: rgba(0, 128, 128, 1)"> 64</span> returnArray =<span style="color: rgba(0, 0, 0, 1)"> ValueToChar(nextChar);
</span><span style="color: rgba(0, 128, 128, 1)"> 65</span>
<span style="color: rgba(0, 128, 128, 1)"> 66</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (bitsRemaining < <span style="color: rgba(128, 0, 128, 1)">4</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 67</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 68</span> nextChar = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)((b >> (<span style="color: rgba(128, 0, 128, 1)">3</span> - bitsRemaining)) & <span style="color: rgba(128, 0, 128, 1)">31</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 69</span> returnArray =<span style="color: rgba(0, 0, 0, 1)"> ValueToChar(nextChar);
</span><span style="color: rgba(0, 128, 128, 1)"> 70</span> bitsRemaining += <span style="color: rgba(128, 0, 128, 1)">5</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 71</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 72</span>
<span style="color: rgba(0, 128, 128, 1)"> 73</span> bitsRemaining -= <span style="color: rgba(128, 0, 128, 1)">3</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 74</span> nextChar = (<span style="color: rgba(0, 0, 255, 1)">byte</span>)((b << bitsRemaining) & <span style="color: rgba(128, 0, 128, 1)">31</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 75</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 76</span>
<span style="color: rgba(0, 128, 128, 1)"> 77</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (arrayIndex !=<span style="color: rgba(0, 0, 0, 1)"> charCount)
</span><span style="color: rgba(0, 128, 128, 1)"> 78</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 79</span> returnArray =<span style="color: rgba(0, 0, 0, 1)"> ValueToChar(nextChar);
</span><span style="color: rgba(0, 128, 128, 1)"> 80</span> <span style="color: rgba(0, 0, 255, 1)">while</span> (arrayIndex != charCount) returnArray = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">=</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 81</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 82</span>
<span style="color: rgba(0, 128, 128, 1)"> 83</span> <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(0, 0, 255, 1)">new</span> <span style="color: rgba(0, 0, 255, 1)">string</span><span style="color: rgba(0, 0, 0, 1)">(returnArray);
</span><span style="color: rgba(0, 128, 128, 1)"> 84</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 85</span>
<span style="color: rgba(0, 128, 128, 1)"> 86</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">int</span> CharToValue(<span style="color: rgba(0, 0, 255, 1)">char</span><span style="color: rgba(0, 0, 0, 1)"> c)
</span><span style="color: rgba(0, 128, 128, 1)"> 87</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 88</span> <span style="color: rgba(0, 0, 255, 1)">var</span> value = (<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">)c;
</span><span style="color: rgba(0, 128, 128, 1)"> 89</span>
<span style="color: rgba(0, 128, 128, 1)"> 90</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (value < <span style="color: rgba(128, 0, 128, 1)">91</span> && value > <span style="color: rgba(128, 0, 128, 1)">64</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 91</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 92</span> <span style="color: rgba(0, 0, 255, 1)">return</span> value - <span style="color: rgba(128, 0, 128, 1)">65</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 93</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 94</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (value < <span style="color: rgba(128, 0, 128, 1)">56</span> && value > <span style="color: rgba(128, 0, 128, 1)">49</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 95</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 96</span> <span style="color: rgba(0, 0, 255, 1)">return</span> value - <span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 97</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)"> 98</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (value < <span style="color: rgba(128, 0, 128, 1)">123</span> && value > <span style="color: rgba(128, 0, 128, 1)">96</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)"> 99</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">100</span> <span style="color: rgba(0, 0, 255, 1)">return</span> value - <span style="color: rgba(128, 0, 128, 1)">97</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">101</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">102</span>
<span style="color: rgba(0, 128, 128, 1)">103</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ArgumentException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Character is not a Base32 character.</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">c</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">104</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">105</span>
<span style="color: rgba(0, 128, 128, 1)">106</span> <span style="color: rgba(0, 0, 255, 1)">private</span> <span style="color: rgba(0, 0, 255, 1)">static</span> <span style="color: rgba(0, 0, 255, 1)">char</span> ValueToChar(<span style="color: rgba(0, 0, 255, 1)">byte</span><span style="color: rgba(0, 0, 0, 1)"> b)
</span><span style="color: rgba(0, 128, 128, 1)">107</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">108</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (b < <span style="color: rgba(128, 0, 128, 1)">26</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">109</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">110</span> <span style="color: rgba(0, 0, 255, 1)">return</span> (<span style="color: rgba(0, 0, 255, 1)">char</span>)(b + <span style="color: rgba(128, 0, 128, 1)">65</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">111</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">112</span>
<span style="color: rgba(0, 128, 128, 1)">113</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (b < <span style="color: rgba(128, 0, 128, 1)">32</span><span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">114</span> <span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">115</span> <span style="color: rgba(0, 0, 255, 1)">return</span> (<span style="color: rgba(0, 0, 255, 1)">char</span>)(b + <span style="color: rgba(128, 0, 128, 1)">24</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">116</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">117</span>
<span style="color: rgba(0, 128, 128, 1)">118</span> <span style="color: rgba(0, 0, 255, 1)">throw</span> <span style="color: rgba(0, 0, 255, 1)">new</span> ArgumentException(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Byte is not a value Base32 value.</span><span style="color: rgba(128, 0, 0, 1)">"</span>, <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">b</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">119</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">120</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">121</span> }</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> </p>
</div>
<h2>总结</h2>
<h3>需要注意的坑</h3>
<div>
<p>移动端下载的认证器的秘钥key是通过base32转码得到的,而程序端是直接输入源码。</p>
<p>如原秘钥为xeon997@foxmail.com生成的base32码PBSW63RZHE3UAZTPPBWWC2LMFZRW63I=才是移动端需要输入的秘钥。</p>
<p>在网上找了很多资料没有发现关于C#的案例,所以在此记录一下自己遇到的坑,让更多的人能够跳过这个坑。</p>
<p>案例地址:</p>
<p>git:https://github.com/CN-Yi/GoogleAuthenticator</p>
<p>gitee:https://gitee.com/hsyi/GoogleAuthenticator</p>
<p>在此感谢提供学习资料的大神们,如果有错误的地方欢迎留言。</p>
<div> </div>
</div><br><br>
来源:https://www.cnblogs.com/hsyi/p/11054869.html
頁:
[1]