C 中的正则表达式 - 搜索信用卡号 - PCI 合规性
Regex in C - search for credit card numbers - PCI compliance
大家好,我需要满足特定客户对 PCI 的需求。我在 C 中相当舒服,我真的不想在这里重做轮子。我在 python 中有一个正则表达式示例,我想在 C 中应用它。
pan_regexs = {'Mastercard': re.compile('(?:\D|^)(5[1-5][0-9]{2}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)'), \
'Visa': re.compile('(?:\D|^)(4[0-9]{3}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)'), \
'AMEX': re.compile('(?:\D|^)((?:34|37)[0-9]{2}(?:\ |\-|)[0-9]{6}(?:\ |\-|)[0-9]{5})(?:\D|$)')}
我找到了一些 POSIX 库 "regex.h ",这似乎使用了非常古老的正则表达式标准。
我找到了两个例子,其中一个使用 POSIX 正则表达式,这似乎充其量是有限的。盗自 Here
#include <regex.h>
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
我在上面看到的问题是它使用(从我收集到的)不支持删除空格的旧正则表达式,dashes.It 似乎也只是执行一些匹配并寻找合适的这方面的例子在 Google 中并没有为我带来很多结果。所以我进一步看了一下,在那个答案中(上面的问题)提到了 PCRE 的使用。
我找到了一些演示 Here
正如我之前所说,我不想重新发明轮子。我认为当可能存在干净简单的东西时,为可能包含潜在缺陷的东西编写自己的正则表达式会很糟糕。
PCI 问题来自一个客户,我们需要能够监控系统 how/where 他们正在存储 PAN 等。这是一种 DLP,审计范围,并证明 CCNS 存储正确。
如何在 C 中使用正则表达式来搜索信用卡号?
PS。我对这个正则表达式没问题,并愿意寻找更好的方法来做这个正则表达式。
好的,我最终使用了 PCRE2,而且效果非常好。
我想我在 Github 上看到的源代码,但它也是 Here。
我下载它,编译它,然后安装它。做以下..
请记住,这里有 8、16 和 32 位格式。我看到的所有示例都使用了 8 位,我发现它最适合我正在做的事情。
./configure --enable-pcre2-8
make
make install
我还必须让 linked 可以搜索它生成的库。
ldconfig
当然,当您编译程序时,您需要 link 将程序添加到库中。使用 -lpcre2-8 库将被命名为 pcre2-16 , pcre2-32 如果您使用这些版本。
之后我使用
编译了他们的 example
cc -Wall pcre2demo.c -lpcre2-8 -o pcre2demo
如果你不想阅读他们在他们巨大的例子中写的所有东西,我做了我自己的......警告我现在将它从几个函数中剥离出来所以你可能需要仔细检查对于问题。但是,我将提供的示例确实有效。
// YOU MUST SPECIFY THE UNIT WIDTH BEFORE THE INCLUDE OF THE pcre.h
#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <string.h>
#include <pcre2.h>
#include <stdbool.h>
int main(){
bool Debug = true;
bool Found = false;
pcre2_code *re;
PCRE2_SPTR pattern;
PCRE2_SPTR subject;
int errornumber;
int i;
int rc;
PCRE2_SIZE erroroffset;
PCRE2_SIZE *ovector;
size_t subject_length;
pcre2_match_data *match_data;
char * RegexStr = "(?:\D|^)(5[1-5][0-9]{2}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)";
char * source = "5111 2222 3333 4444";
pattern = (PCRE2_SPTR)RegexStr;// <<<<< This is where you pass your REGEX
subject = (PCRE2_SPTR)source;// <<<<< This is where you pass your bufer that will be checked.
subject_length = strlen((char *)subject);
re = pcre2_compile(
pattern, /* the pattern */
PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
0, /* default options */
&errornumber, /* for error number */
&erroroffset, /* for error offset */
NULL); /* use default compile context */
/* Compilation failed: print the error message and exit. */
if (re == NULL)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,buffer);
return 1;
}
match_data = pcre2_match_data_create_from_pattern(re, NULL);
rc = pcre2_match(
re,
subject, /* the subject string */
subject_length, /* the length of the subject */
0, /* start at offset 0 in the subject */
0, /* default options */
match_data, /* block for storing the result */
NULL);
if (rc < 0)
{
switch(rc)
{
case PCRE2_ERROR_NOMATCH: //printf("No match\n"); //
pcre2_match_data_free(match_data);
pcre2_code_free(re);
Found = 0;
return Found;
// break;
/*
Handle other special cases if you like
*/
default: printf("Matching error %d\n", rc); //break;
}
pcre2_match_data_free(match_data); /* Release memory used for the match */
pcre2_code_free(re);
Found = 0; /* data and the compiled pattern. */
return Found;
}
if (Debug){
ovector = pcre2_get_ovector_pointer(match_data);
printf("Match succeeded at offset %d\n", (int)ovector[0]);
if (rc == 0)
printf("ovector was not big enough for all the captured substrings\n");
if (ovector[0] > ovector[1])
{
printf("\K was used in an assertion to set the match start after its end.\n"
"From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
(char *)(subject + ovector[1]));
printf("Run abandoned\n");
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
for (i = 0; i < rc; i++)
{
PCRE2_SPTR substring_start = subject + ovector[2*i];
size_t substring_length = ovector[2*i+1] - ovector[2*i];
printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
}
}
else{
if(rc > 0){
Found = true;
}
}
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return Found;
}
大家好,我需要满足特定客户对 PCI 的需求。我在 C 中相当舒服,我真的不想在这里重做轮子。我在 python 中有一个正则表达式示例,我想在 C 中应用它。
pan_regexs = {'Mastercard': re.compile('(?:\D|^)(5[1-5][0-9]{2}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)'), \
'Visa': re.compile('(?:\D|^)(4[0-9]{3}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)'), \
'AMEX': re.compile('(?:\D|^)((?:34|37)[0-9]{2}(?:\ |\-|)[0-9]{6}(?:\ |\-|)[0-9]{5})(?:\D|$)')}
我找到了一些 POSIX 库 "regex.h ",这似乎使用了非常古老的正则表达式标准。
我找到了两个例子,其中一个使用 POSIX 正则表达式,这似乎充其量是有限的。盗自 Here
#include <regex.h>
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if (!reti) {
puts("Match");
}
else if (reti == REG_NOMATCH) {
puts("No match");
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free memory allocated to the pattern buffer by regcomp() */
regfree(®ex);
我在上面看到的问题是它使用(从我收集到的)不支持删除空格的旧正则表达式,dashes.It 似乎也只是执行一些匹配并寻找合适的这方面的例子在 Google 中并没有为我带来很多结果。所以我进一步看了一下,在那个答案中(上面的问题)提到了 PCRE 的使用。
我找到了一些演示 Here
正如我之前所说,我不想重新发明轮子。我认为当可能存在干净简单的东西时,为可能包含潜在缺陷的东西编写自己的正则表达式会很糟糕。
PCI 问题来自一个客户,我们需要能够监控系统 how/where 他们正在存储 PAN 等。这是一种 DLP,审计范围,并证明 CCNS 存储正确。
如何在 C 中使用正则表达式来搜索信用卡号?
PS。我对这个正则表达式没问题,并愿意寻找更好的方法来做这个正则表达式。
好的,我最终使用了 PCRE2,而且效果非常好。
我想我在 Github 上看到的源代码,但它也是 Here。
我下载它,编译它,然后安装它。做以下.. 请记住,这里有 8、16 和 32 位格式。我看到的所有示例都使用了 8 位,我发现它最适合我正在做的事情。
./configure --enable-pcre2-8
make
make install
我还必须让 linked 可以搜索它生成的库。
ldconfig
当然,当您编译程序时,您需要 link 将程序添加到库中。使用 -lpcre2-8 库将被命名为 pcre2-16 , pcre2-32 如果您使用这些版本。
之后我使用
编译了他们的 examplecc -Wall pcre2demo.c -lpcre2-8 -o pcre2demo
如果你不想阅读他们在他们巨大的例子中写的所有东西,我做了我自己的......警告我现在将它从几个函数中剥离出来所以你可能需要仔细检查对于问题。但是,我将提供的示例确实有效。
// YOU MUST SPECIFY THE UNIT WIDTH BEFORE THE INCLUDE OF THE pcre.h
#define PCRE2_CODE_UNIT_WIDTH 8
#include <stdio.h>
#include <string.h>
#include <pcre2.h>
#include <stdbool.h>
int main(){
bool Debug = true;
bool Found = false;
pcre2_code *re;
PCRE2_SPTR pattern;
PCRE2_SPTR subject;
int errornumber;
int i;
int rc;
PCRE2_SIZE erroroffset;
PCRE2_SIZE *ovector;
size_t subject_length;
pcre2_match_data *match_data;
char * RegexStr = "(?:\D|^)(5[1-5][0-9]{2}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4}(?:\ |\-|)[0-9]{4})(?:\D|$)";
char * source = "5111 2222 3333 4444";
pattern = (PCRE2_SPTR)RegexStr;// <<<<< This is where you pass your REGEX
subject = (PCRE2_SPTR)source;// <<<<< This is where you pass your bufer that will be checked.
subject_length = strlen((char *)subject);
re = pcre2_compile(
pattern, /* the pattern */
PCRE2_ZERO_TERMINATED, /* indicates pattern is zero-terminated */
0, /* default options */
&errornumber, /* for error number */
&erroroffset, /* for error offset */
NULL); /* use default compile context */
/* Compilation failed: print the error message and exit. */
if (re == NULL)
{
PCRE2_UCHAR buffer[256];
pcre2_get_error_message(errornumber, buffer, sizeof(buffer));
printf("PCRE2 compilation failed at offset %d: %s\n", (int)erroroffset,buffer);
return 1;
}
match_data = pcre2_match_data_create_from_pattern(re, NULL);
rc = pcre2_match(
re,
subject, /* the subject string */
subject_length, /* the length of the subject */
0, /* start at offset 0 in the subject */
0, /* default options */
match_data, /* block for storing the result */
NULL);
if (rc < 0)
{
switch(rc)
{
case PCRE2_ERROR_NOMATCH: //printf("No match\n"); //
pcre2_match_data_free(match_data);
pcre2_code_free(re);
Found = 0;
return Found;
// break;
/*
Handle other special cases if you like
*/
default: printf("Matching error %d\n", rc); //break;
}
pcre2_match_data_free(match_data); /* Release memory used for the match */
pcre2_code_free(re);
Found = 0; /* data and the compiled pattern. */
return Found;
}
if (Debug){
ovector = pcre2_get_ovector_pointer(match_data);
printf("Match succeeded at offset %d\n", (int)ovector[0]);
if (rc == 0)
printf("ovector was not big enough for all the captured substrings\n");
if (ovector[0] > ovector[1])
{
printf("\K was used in an assertion to set the match start after its end.\n"
"From end to start the match was: %.*s\n", (int)(ovector[0] - ovector[1]),
(char *)(subject + ovector[1]));
printf("Run abandoned\n");
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return 0;
}
for (i = 0; i < rc; i++)
{
PCRE2_SPTR substring_start = subject + ovector[2*i];
size_t substring_length = ovector[2*i+1] - ovector[2*i];
printf("%2d: %.*s\n", i, (int)substring_length, (char *)substring_start);
}
}
else{
if(rc > 0){
Found = true;
}
}
pcre2_match_data_free(match_data);
pcre2_code_free(re);
return Found;
}