use*_*697 15 openssl asn.1 ssl-certificate
我怎样才能转换ASN1_TIME成time_t格式?我想将返回值转换X509_get_notAfter()为秒.
小智 8
时间在内部,格式YYmmddHHMMSS或存储为字符串YYYYmmddHHMMSS.
在字符串的末尾有几分之一秒和时区的空间,但是现在让我们忽略它,并且有一些(未经测试的)代码.
注意:请参阅下面的Bryan Olson的回答,该回答讨论了由于i++s的未定义行为.另请参阅Seak的回答,该回答删除了未定义的行为.
static time_t ASN1_GetTimeT(ASN1_TIME* time)
{
struct tm t;
const char* str = (const char*) time->data;
size_t i = 0;
memset(&t, 0, sizeof(t));
if (time->type == V_ASN1_UTCTIME) /* two digit year */
{
t.tm_year = (str[i++] - '0') * 10 + (str[++i] - '0');
if (t.tm_year < 70)
t.tm_year += 100;
}
else if (time->type == V_ASN1_GENERALIZEDTIME) /* four digit year */
{
t.tm_year = (str[i++] - '0') * 1000 + (str[++i] - '0') * 100 + (str[++i] - '0') * 10 + (str[++i] - '0');
t.tm_year -= 1900;
}
t.tm_mon = ((str[i++] - '0') * 10 + (str[++i] - '0')) - 1; // -1 since January is 0 not 1.
t.tm_mday = (str[i++] - '0') * 10 + (str[++i] - '0');
t.tm_hour = (str[i++] - '0') * 10 + (str[++i] - '0');
t.tm_min = (str[i++] - '0') * 10 + (str[++i] - '0');
t.tm_sec = (str[i++] - '0') * 10 + (str[++i] - '0');
/* Note: we did not adjust the time based on time zone information */
return mktime(&t);
}
Run Code Online (Sandbox Code Playgroud)
从openssl代码,它似乎是一个坏主意:
/*
* FIXME: mktime assumes the current timezone
* instead of UTC, and unless we rewrite OpenSSL
* in Lisp we cannot locally change the timezone
* without possibly interfering with other parts
* of the program. timegm, which uses UTC, is
* non-standard.
* Also time_t is inappropriate for general
* UTC times because it may a 32 bit type.
*/
Run Code Online (Sandbox Code Playgroud)
请注意,您可以使用ASN1_TIME_diff()来获取两个ASN1_TIME*之间的天数/秒.如果从ASN1_TIME*传递NULL,则可以获得与当前时间的差异.
小智 7
好吧,我不知道其余的,但是对于ASN1_TIME采用UTCTime格式的情况,该代码是错误的:YYMMDDHHMMSSZ.
我尝试并返回错误的值,即使从++ i到i ++的更正,然而......代码不是良好编码的示例.
我设法修复它,它是char类型的总和:
static time_t ASN1_GetTimeT(ASN1_TIME* time){
struct tm t;
const char* str = (const char*) time->data;
size_t i = 0;
memset(&t, 0, sizeof(t));
if (time->type == V_ASN1_UTCTIME) {/* two digit year */
t.tm_year = (str[i++] - '0') * 10;
t.tm_year += (str[i++] - '0');
if (t.tm_year < 70)
t.tm_year += 100;
} else if (time->type == V_ASN1_GENERALIZEDTIME) {/* four digit year */
t.tm_year = (str[i++] - '0') * 1000;
t.tm_year+= (str[i++] - '0') * 100;
t.tm_year+= (str[i++] - '0') * 10;
t.tm_year+= (str[i++] - '0');
t.tm_year -= 1900;
}
t.tm_mon = (str[i++] - '0') * 10;
t.tm_mon += (str[i++] - '0') - 1; // -1 since January is 0 not 1.
t.tm_mday = (str[i++] - '0') * 10;
t.tm_mday+= (str[i++] - '0');
t.tm_hour = (str[i++] - '0') * 10;
t.tm_hour+= (str[i++] - '0');
t.tm_min = (str[i++] - '0') * 10;
t.tm_min += (str[i++] - '0');
t.tm_sec = (str[i++] - '0') * 10;
t.tm_sec += (str[i++] - '0');
/* Note: we did not adjust the time based on time zone information */
return mktime(&t);
}
Run Code Online (Sandbox Code Playgroud)
小智 5
我不同意Jan和Jack的观点.实际上有人在我工作的地方复制并使用了给定的代码,但它失败了.这就是为什么,从C99标准:
在前一个和下一个序列点之间,一个对象的存储值最多只能通过表达式的评估修改一次." - ISO/IEC 9899:1999,"编程语言 - C",第6.5节,第1条.
在编译给定代码时,gcc(版本4.1.2)说九次,
警告:'i'上的操作可能未定义.
代码具有未定义的行为.我实际看到的错误是年份"13"被读为11.这是因为:
postfix ++运算符的结果是操作数的值.获得结果后,操作数的值递增.[...]更新操作数的存储值的副作用应发生在前一个和下一个序列点之间. - 同上,第6.5.2.4节,第2条.
str [i ++]的两个实例都在:
t.tm_year =(str [i ++] - '0')*10 +(str [i ++] - '0');
读"13"中的'1',因为它们都发生在i的更新之前.多次更新i的所有行都有相同的问题.
简单的解决方法是摆脱'i'并通过一次调用sscanf()来替换所有这些行.
即使有了这个修复,我也不喜欢这些代码.除了忽略时区后缀之外,它不会检查错误或意外值.证书是一种安全机制,安全代码对健壮性有严格的要求.您的程序未正确处理的极端情况是攻击者填充的情况.
| 归档时间: |
|
| 查看次数: |
11754 次 |
| 最近记录: |