c - C 中的正则表达式 - 搜索信用卡号 - PCI 合规性

标签 c regex pcre

大家好,我需要满足特定客户对 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(&regex, "^a[[:alnum:]]", 0);
if (reti) {
    fprintf(stderr, "Could not compile regex\n");
    exit(1);
}

/* Execute regular expression */
reti = regexec(&regex, "abc", 0, NULL, 0);
if (!reti) {
    puts("Match");
}
else if (reti == REG_NOMATCH) {
    puts("No match");
}
else {
    regerror(reti, &regex, msgbuf, sizeof(msgbuf));
    fprintf(stderr, "Regex match failed: %s\n", msgbuf);
    exit(1);
}

/* Free memory allocated to the pattern buffer by regcomp() */
regfree(&regex);

我在上面看到的问题是它使用(从我收集到的)旧正则表达式,它不支持删除空格和破折号。它似乎也只是真正执行一些匹配并寻找合适的例子没有在谷歌上为我提供很多结果。所以我进一步查看,在答案中(上面的问题)提到了 PCRE 的使用。

我找到了一些演示Here

正如我之前所说,我不想重新发明轮子。我认为,当可能存在一些干净简单的东西时,编写自己的正则表达式来处理可能包含潜在缺陷的内容是很糟糕的。

PCI 问题来自客户,我们需要能够监控系统如何/在何处存储 PAN 等。这有点像 DLP,审计范围,并证明 CCNS 存储正确。

如何使用 C 中的正则表达式来搜索信用卡号?

PS。我对这个正则表达式很满意,并且愿意寻求更好的方法来执行这个正则表达式。

最佳答案

好吧,我最终使用了 PCRE2,它运行得非常好。

源代码我想我在Github上看到过,但它也是Here也是。

我下载了它,编译它,然后安装它。执行以下操作.. 请记住,有 8、16 和 32 位格式。我看到的所有示例都使用 8 位,我发现它最适合我正在做的事情。

./configure --enable-pcre2-8
make
make install

我还必须使其生成的库可通过使用链接进行搜索。

ldconfig

当然,当您编译程序时,您需要将程序链接到库。使用 -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;

}

关于c - C 中的正则表达式 - 搜索信用卡号 - PCI 合规性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50306856/

相关文章:

C 警告 : incompatible pointer types passing

regex - 使用 unix 重命名来保留任意数字

regex - Perl 正则表达式 : How to grab the part that is the same

unicode - libpcre2 代码单元宽度

c - 我们在哪里可以在 C 中使用函数指针,函数指针有什么用途

c - 如何构建 ARMv8 aarch32 二进制文件?

c++ - 带超时的 C/C++ recv()

python-3.x - 需要找到完全匹配并使用正则表达式替换

c# - 匹配 HTML 和 Javascript 文件中的文件路径

regex - 如何将一组值与组 1 相匹配