Skip to content

Commit

Permalink
fixed: AES解密错误,还存在问题 #2
Browse files Browse the repository at this point in the history
  • Loading branch information
yiyungent committed Jul 13, 2020
1 parent 21b19c3 commit 32aac38
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 43 deletions.
2 changes: 0 additions & 2 deletions examples/ASPNETCoreClient/wwwroot/js/SimCaptcha.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,6 @@
function sendVCodePos() {
var ts = Date.now(); // js 13位 毫秒时间戳
var verifyInfo = { appId: _appId, vCodePos: _vCodePos, userId: _resUserId, ua: navigator.userAgent, ts: ts }; // ua, ts 服务端暂时未用,保留。用户花费在此验证码的时间 = 验证码服务端 接收到点击位置数据时间 - 验证码服务端 产生验证码图片时间
console.log("verifyInfo", verifyInfo);
// 发送ajax到验证码服务端 -> 得到response结果,封装为 res
httpPost(_reqVCodeCheckUrl, verifyInfo, function (response) {

Expand Down Expand Up @@ -248,7 +247,6 @@
// var xOffset = event.clientX - ($(obj).offset().left - $(window).scrollLeft());;
// var yOffset = event.clientY - ($(obj).offset().top - $(window).scrollTop());;

// TODO: 待修复, 位置不正确
return { x: xOffset, y: yOffset };
}

Expand Down
2 changes: 1 addition & 1 deletion examples/ASPNETCoreService/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"AllowedHosts": "*",
"SimCaptcha": {
"AesKey": "qwertyuiopasdfghjklzxcvbnm123456", // ±ØÐë>=16λ
"AesKey": "8G5M4Ff9hel8fUA9", // ±ØÐëΪ16λ
"AllowErrorNum": 1,
"ExpiredSec": 60,
"AppList": [
Expand Down
2 changes: 1 addition & 1 deletion src/SimCaptcha.AspNetCore/LocalCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace SimCaptcha.AspNetCore
{
/// <summary>
/// TODO: 实现缓存
/// 实现缓存
/// <para>注意: 均为绝对过期,非滑动过期</para>
/// </summary>
public class LocalCache : ICache
Expand Down
32 changes: 11 additions & 21 deletions src/SimCaptcha/Common/AesHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,6 @@ public class AesHelper
/// </summary>
private const string ALGORITHM = "AES";

/// <summary>
/// 默认的初始化向量值
/// </summary>
private const string IV_DEFAULT = "g8v20drvOmIx2PuR";

/// <summary>
/// 默认加密的KEY
/// </summary>
private const string KEY_DEFAULT = "8G5M4Ff9hel8fUA9";

#region 其它填充模式(但是php目前所知填充模式只有ZeroPadding,于是其他语言就只能跟着它来了)
/// <summary>
/// 工作模式:CBC
Expand Down Expand Up @@ -65,18 +55,18 @@ public class AesHelper
/// <param name="iv">初始化向量值,如果不填则使用默认值</param>
/// <returns></returns>
[Obsolete("SimCaptcha 加解密默认全使用ECB模式, 请注意", true)]
public static string EncryptCbcMode(string toEncrypt, string key = KEY_DEFAULT, string iv = IV_DEFAULT)
public static string EncryptCbcMode(string toEncrypt, string key, string iv)
{
if (!string.IsNullOrEmpty(toEncrypt))
{
// 如果key或iv为空,则使用默认值
if (key == null || key.Length != 16)
{
key = KEY_DEFAULT;
throw new Exception(nameof(key) + "必须为16位!");
}
if (iv == null || iv.Length != 16)
{
iv = IV_DEFAULT;
throw new Exception(nameof(iv) + "必须为16位!");
}

byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
Expand Down Expand Up @@ -119,18 +109,18 @@ public static string EncryptCbcMode(string toEncrypt, string key = KEY_DEFAULT,
/// <param name="iv">初始化向量值,如果不填则使用默认值</param>
/// <returns></returns>
[Obsolete("SimCaptcha 加解密默认全使用ECB模式, 请注意", true)]
public static string DecryptCbcMode(string toDecrypt, string key = KEY_DEFAULT, string iv = IV_DEFAULT)
public static string DecryptCbcMode(string toDecrypt, string key, string iv)
{
if (!string.IsNullOrEmpty(toDecrypt))
{
// 如果key或iv为空,则使用默认值
if (key == null || key.Length != 16)
{
key = KEY_DEFAULT;
throw new Exception(nameof(key) + "必须为16位!");
}
if (iv == null || iv.Length != 16)
{
iv = IV_DEFAULT;
throw new Exception(nameof(iv) + "必须为16位!");
}

byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
Expand Down Expand Up @@ -169,14 +159,14 @@ public static string DecryptCbcMode(string toDecrypt, string key = KEY_DEFAULT,
/// <param name="toEncrypt">待加密字符串</param>
/// <param name="key">秘钥,如果不填则使用默认值</param>
/// <returns></returns>
public static string EncryptEcbMode(string toEncrypt, string key = KEY_DEFAULT)
public static string EncryptEcbMode(string toEncrypt, string key)
{
if (!string.IsNullOrEmpty(toEncrypt))
{
// 如果key或iv为空,则使用默认值
if (key == null || key.Length != 16)
{
key = KEY_DEFAULT;
throw new Exception(nameof(key) + "必须为16位!");
}

byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
Expand Down Expand Up @@ -215,14 +205,14 @@ public static string EncryptEcbMode(string toEncrypt, string key = KEY_DEFAULT)
/// <param name="toDecrypt">AES加密之后的字符串</param>
/// <param name="key">秘钥,如果不填则使用默认值</param>
/// <returns></returns>
public static string DecryptEcbMode(string toDecrypt, string key = KEY_DEFAULT)
public static string DecryptEcbMode(string toDecrypt, string key)
{
if (!string.IsNullOrEmpty(toDecrypt))
{
// 如果key为空,则使用默认值
if (key == null || key.Length != 16)
{
key = KEY_DEFAULT;
throw new Exception(nameof(key) + "必须为16位!");
}

byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
Expand All @@ -233,7 +223,7 @@ public static string DecryptEcbMode(string toDecrypt, string key = KEY_DEFAULT)
RijndaelManaged rDel = new RijndaelManaged
{
Key = keyArray,
Mode = CipherMode.CBC,
Mode = CipherMode.ECB,
Padding = TRANSFORM_ECB
};
ICryptoTransform cTransform = rDel.CreateDecryptor();
Expand Down
42 changes: 24 additions & 18 deletions src/SimCaptcha/SimCaptchaService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using SimCaptcha.Models;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
Expand Down Expand Up @@ -46,7 +47,7 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
{
VCodeCheckResponseModel rtnResult = new VCodeCheckResponseModel();
// 允许的偏移量(点触容错)
int allowOffset = 8;
int allowOffset = 10;

#region 尝试从内存中取出对应的 VCodeKey
// 获取此用户会话的验证码效验 vCodeKey
Expand All @@ -59,18 +60,25 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
}
string rightVCodeKey = _cacheHelper.Get<string>(cacheKeyVCodeKey);
// AES解密
// TODO: 解密有误
//string vCodeKeyJsonStr = AesHelper.DecryptEcbMode(rightVCodeKey, _options.AesKey);
string vCodeKeyJsonStr = rightVCodeKey;
string vCodeKeyJsonStr = AesHelper.DecryptEcbMode(rightVCodeKey, _options.AesKey);
// json -> 对象
VCodeKeyModel vCodeKeyModel = null;
try
{
// 能够转换为 对象,则说明 vCodeKey 无误,可以使用
vCodeKeyModel = JsonHelper.Deserialize<VCodeKeyModel>(vCodeKeyJsonStr);
// TODO: fixed: 临时修复, 直接将全部为0的字节去除,
byte[] bytes = Encoding.UTF8.GetBytes(vCodeKeyJsonStr);
byte[] remove0Bytes = bytes.Where(m => m != 0).ToArray();
string remove0ByteStr = Encoding.UTF8.GetString(remove0Bytes);

// 能够转换为 对象, 则说明 vCodeKey 无误, 可以使用
//vCodeKeyModel = JsonHelper.Deserialize<VCodeKeyModel>(vCodeKeyJsonStr);
vCodeKeyModel = JsonHelper.Deserialize<VCodeKeyModel>(remove0ByteStr);
}
catch (Exception ex)
{ }
{
// TODO: BUG: 经加密再解密后的jsonStr,虽然看起来一样,但发生了一点改变, 导致无法转换
// '0x00' is invalid after a single JSON value. Expected end of data. LineNumber: 0 | BytePositionInLine: 110.
}
if (vCodeKeyModel == null)
{
// 验证码无效,被篡改导致解密失败
Expand All @@ -90,7 +98,7 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
rtnResult.message = "验证码过期, 获取新验证码";
RemoveCacheVCodeKey(verifyInfo.UserId);
return rtnResult;
}
}
#endregion

#region 效验点触位置数据
Expand Down Expand Up @@ -125,6 +133,7 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use

#endregion

#region 未通过->错误次数达到上限?
if (!isPass)
{
// 本次没通过验证 -> 错误次数+1
Expand All @@ -144,9 +153,7 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
// 错误 -> 1.code:-1 验证码错误 且 错误次数未达上限 -> message: 点错啦,请重试
string vCodekeyJsonStrTemp = JsonHelper.Serialize(vCodeKeyModel);
// AES加密 vCodekeyJsonStrTemp
// TODO: 解密有误
//string vCodeKeyStrTemp = AesHelper.EncryptEcbMode(vCodekeyJsonStrTemp, _options.AesKey);
string vCodeKeyStrTemp = vCodekeyJsonStrTemp;
string vCodeKeyStrTemp = AesHelper.EncryptEcbMode(vCodekeyJsonStrTemp, _options.AesKey);
// 更新 Cache 中的 vCodeKey
_cacheHelper.Insert<string>(CachePrefixVCodeKey + verifyInfo.UserId, vCodeKeyStrTemp);

Expand All @@ -155,9 +162,9 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
return rtnResult;
}
}
#endregion



#region 验证通过->下发ticket
// 正确 -> code:0 下发票据 ticket
TicketModel ticketModel = new TicketModel { IP = userIp, IsPass = true, TS = DateTimeHelper.NowTimeStamp13() };
string ticketJsonStr = JsonHelper.Serialize(ticketModel);
Expand All @@ -167,7 +174,8 @@ public VCodeCheckResponseModel VCodeCheck(VerifyInfoModel verifyInfo, string use
rtnResult.code = 0;
rtnResult.message = "验证通过";
rtnResult.data = new VCodeCheckResponseModel.DataModel { appId = verifyInfo.AppId, ticket = ticket };
return rtnResult;
return rtnResult;
#endregion
}
#endregion

Expand Down Expand Up @@ -274,9 +282,7 @@ public Task<VCodeResponseModel> VCode()
TS = DateTimeHelper.NowTimeStamp13(),
VCodePos = model.VCodePos
});
// TODO: 解密有误
//string vCodeKey = AesHelper.EncryptEcbMode(vCodekeyJsonStr, _options.AesKey);
string vCodeKey = vCodekeyJsonStr;
string vCodeKey = AesHelper.EncryptEcbMode(vCodekeyJsonStr, _options.AesKey);
// 答案 保存到 此次用户会话对应的 Cache 中
_cacheHelper.Insert<string>(CachePrefixVCodeKey + userId, vCodeKey);
}
Expand Down Expand Up @@ -327,7 +333,7 @@ private VCodeImgModel CreateVCodeImg()
VCodeImgModel rtnResult = new VCodeImgModel { VCodePos = new List<PointPosModel>() };
string code = RandomCode.Create(6);
rtnResult = VCodeImage.Create(code, 200, 200);
// TODO: 没有正确答案位置

return rtnResult;
}
#endregion
Expand Down

0 comments on commit 32aac38

Please sign in to comment.