解析敏感数据会将星号放在错误的位置

时间:2018-06-20 06:39:34

标签: php regex

字符串参数传递给函数-以下是可能的输入数据的各种示例   函数接收此数据作为字符串,而不是数组,json或其他数据格式   该函数应解析字符串并屏蔽敏感数据。   敏感数据应使用Asterix(*)字符屏蔽(替换)。   敏感数据包括以下字段,但应根据需要轻松将新的敏感字段添加到函数中:

信用卡号

信用卡有效期

信用卡CVV值

该函数以与提供的格式相同的格式返回已解析的字符串,但现在已屏蔽了敏感数据。

  <?php

        $testData1 = "[orderId] => 212939129
        [orderNumber] => INV10001
        [salesTax] => 1.00
        [amount] => 21.00
        [terminal] => 5
        [currency] => 1
        [type] => purchase
        [avsStreet] => 123 Road
        [avsZip] => A1A 2B2
        [customerCode] => CST1001
        [cardId] => 18951828182
        [cardHolderName] => John Smith
        [cardNumber] => 5454545454545454
        [cardExpiry] => 1025
        [cardCVV] => 100";

    $testData2 = "Request=Credit Card.Auth Only&Version=4022&HD.Network_Status_Byte=*&HD.Application_ID=TZAHSK!&HD."
            . "Terminal_ID=12991kakajsjas&HD.Device_Tag=000123&07."
            . "POS_Entry_Capability=1&07.PIN_Entry_Capability=0&07.CAT_Indicator=0&07."
            . "Terminal_Type=4&07.Account_Entry_Mode=1&07.Partial_Auth_Indicator=0&07.Account_Card_Number="
            . "4242424242424242&07.Account_Expiry=1024&07.Transaction_Amount=142931&07."
            . "Association_Token_Indicator=0&17.CVV=200&17.Street_Address=123 Road SW&17.Postal_Zip_Code=90210&17.Invoice_Number=INV19291";


    $testData3 = '{
            "MsgTypId": 111231232300,
            "CardNumber": "4242424242424242",
            "CardExp": 1024,
            "CardCVV": 240,
            "TransProcCd": "004800",
            "TransAmt": "57608",
            "MerSysTraceAudNbr": "456211",
            "TransTs": "180603162242",
            "AcqInstCtryCd": "840",
            "FuncCd": "100",
            "MsgRsnCd": "1900",
            "MerCtgyCd": "5013",
            "AprvCdLgth": "6",
            "RtrvRefNbr": "1029301923091239",
        }';

    $testData4 = "<?xml version='1.0' encoding='UTF-8'?>
                <Request>
                        <NewOrder>
                                <IndustryType>MO</IndustryType>
                                <MessageType>AC</MessageType>
                                <BIN>000001</BIN>
                                <MerchantID>209238</MerchantID>
                                <TerminalID>001</TerminalID>
                                <CardBrand>VI</CardBrand>
                                <CardDataNumber>5454545454545454</AccountNum>
                                <Exp>1026</Exp>
                                <CVVCVCSecurity>300</Exp>
                                <CurrencyCode>124</CurrencyCode>
                                <CurrencyExponent>2</CurrencyExponent>
                                <AVSzip>A2B3C3</AVSzip>
                                <AVSaddress1>2010 Road SW</AVSaddress1>
                                <AVScity>Calgary</AVScity>
                                <AVSstate>AB</AVSstate>
                                <AVSname>JOHN R SMITH</AVSname>
                                <OrderID>23123INV09123</OrderID>
                                <Amount>127790</Amount>
                        </NewOrder>
                </Request>";

    $parseNew = array("name", "amt", "amount"); //some optional fields to parse
    //this function will take a provided string, $data, and replace all credit card information including 16-digit numbers, expiry dates and 3-digit CVV numbers.
    //$parseNew is an optional field to parse other sensitive information that matches the type of information entered into $parseNew, such as the transaction amount.
    //if the strings in $parseNew matches any field in the data given, then that data will be parsed as well
    //assign each piece of given test data to a variable for each to be passed into helcimTest

    function helcimTest($data, $parseNew) {

        $lines = explode("\n", $data); //split data by new lines into an array

        if (count($lines) == 1) { //if there aren't any new lines, then periods are used
            $lines = explode(".", $data); //different splits can also be added with another if, like a ,
            //print_r($lines);
        }

        for ($currLine = 0; $currLine < count($lines); $currLine++) { //loop through the lines and check for credit card information keywords as well as if theres any matches in $parseNew

            $nonos = array("cvv", "exp", "expiry", "expire", "CVV", "Exp"); //keywords of default fields to be parsed, credit card numbers need to be searched for differently
            $nonos = array_merge($nonos, $parseNew); //take optional parse data types and add it to array of default credit card data types
            //checking credit card number first
            $cardPos = strpos($lines[$currLine], "card"); //find "card" as part of Card Number 

            if ($cardPos === false) {

                $cardPos = strpos($lines[$currLine], "Card");
            }

            if ($cardPos > 0) { //if "card" is in the line, we check if "number" is also
                $numberPos = strpos($lines[$currLine], "Number");

                if ($numberPos === false) {
                    $numberPos = strpos($lines[$currLine], "number");
                }

                if ($numberPos > 0) {

                    $matches = array();
                    preg_match_all('!\d+!', $lines[$currLine], $matches); //grabs all numbers in the line and throws them in an array
                    $numberLength = 0;

                    $digits = $matches[0]; //unpack array inside matches array

                    for ($i = 0; $i < count($digits); $i++) {

                        if (strlen($digits[$i]) == 16) {

                            $theNumber = $digits[$i];
                            $numberLength = strlen($digits[$i]);
                        }
                    }

                    if ($numberLength == 16) { //when all of these things are true then this number is definitely a credit card number

                        $lines[$currLine] = str_replace($theNumber, "****************", $lines[$currLine]);
                        //print_r($lines);         
                    }
                }
            }

            //credit card number check complete

            //now to check for everythign else
            for ($i = 0; $i < count($nonos); $i++) {

                $currNono = $nonos[$i]; //current type of data we are looking to parse

                if(strpos($lines[$currLine], $currNono) > 0){ //check to see if current parsing field exists on current line

                    preg_match_all("/\d+\.\d+|\d+|[A-Za-z]+/", $lines[$currLine], $matches);
                    $sensData = $matches[0]; //unpack array from wihtin another array

                    print_r($sensData);

                    for($f = 0; $f < count($sensData); $f++){ //if we find any fields we want to parse

                        if (strcmp($sensData[$f], $currNono) == true && $f+1 != count($sensData)){

                            $hash = str_repeat("*", strlen($sensData[$f+1]));
                            $lines[$currLine] = str_replace($sensData[$f+1], $hash, $lines[$currLine]);
                        }
                    }
                }
            }
        }

        print_r($lines);
    }

    echo "Data set 1:\n\n"; //print results
    helcimTest($testData1, $parseNew);
    echo "Data set 2:\n\n";
    helcimTest($testData2, $parseNew);
    echo "Data set 3:\n\n";
    helcimTest($testData3, $parseNew);
    echo "Data set 4:\n\n";
    helcimTest($testData4, $parseNew);

输出看起来像这样,某些值已正确解析,有些则感觉完全是随机的。该函数的第一部分仅处理信用卡号,该信用卡号被正确正确地解析,这是当该函数到达其底部一半时,我布置的模式与结果相比毫无意义:

    Data set 1:

    Array
    (
        [0] => amount
        [1] => 21.00
    )
    Array
    (
        [0] => cardExpiry
        [1] => 1025
    )
    Array
    (
        [0] => cardCVV
        [1] => 100
    )
    Array
    (
        [0] => [orderId] => 212939129
        [1] =>             [orderNumber] => INV10001
        [2] =>             [salesTax] => 1.00
        [3] =>             [amount] => 21.00
        [4] =>             [terminal] => 5
        [5] =>             [currency] => 1
        [6] =>             [type] => purchase
        [7] =>             [avsStreet] => 123 Road
        [8] =>             [avsZip] => A1A 2B2
        [9] =>             [customerCode] => CST1001
        [10] =>             [cardId] => 18951828182
        [11] =>             [cardHolderName] => John Smith
        [12] =>             [cardNumber] => ****************
        [13] =>             [cardExpiry] => ****
        [14] =>             [cardCVV] => ***
    )
    Data set 2:

    Array
    (
        [0] => Account
        [1] => Expiry
        [2] => 1024
        [3] => 07
    )
    Array
    (
        [0] => Request=Credit Card
        [1] => Auth Only&Version=4022&HD
        [2] => Network_Status_Byte=*&HD
        [3] => Application_ID=TZAHSK!&HD
        [4] => Terminal_ID=12991kakajsjas&HD
        [5] => Device_Tag=000123&07
        [6] => POS_Entry_Capability=1&07
        [7] => PIN_Entry_Capability=0&07
        [8] => CAT_Indicator=0&07
        [9] => Terminal_Type=4&07
        [10] => Account_Entry_Mode=1&07
        [11] => Partial_Auth_Indicator=0&07
        [12] => Account_Card_Number=****************&07
        [13] => Account_******=****&**
        [14] => Transaction_Amount=142931&07
        [15] => Association_Token_Indicator=0&17
        [16] => CVV=200&17
        [17] => Street_Address=123 Road SW&17
        [18] => Postal_Zip_Code=90210&17
        [19] => Invoice_Number=INV19291
    )
    Data set 3:

    Array
    (
        [0] => CardExp
        [1] => 1024
    )
    Array
    (
        [0] => CardCVV
        [1] => 240
    )
    Array
    (
        [0] => {
        [1] =>                 "MsgTypId": 111231232300,
        [2] =>                 "CardNumber": "****************",
        [3] =>                 "CardExp": ****,
        [4] =>                 "CardCVV": ***,
        [5] =>                 "TransProcCd": "004800",
        [6] =>                 "TransAmt": "57608",
        [7] =>                 "MerSysTraceAudNbr": "456211",
        [8] =>                 "TransTs": "180603162242",
        [9] =>                 "AcqInstCtryCd": "840",
        [10] =>                 "FuncCd": "100",
        [11] =>                 "MsgRsnCd": "1900",
        [12] =>                 "MerCtgyCd": "5013",
        [13] =>                 "AprvCdLgth": "6",
        [14] =>                 "RtrvRefNbr": "1029301923091239",
        [15] =>             }
    )
    Data set 4:

    Array
    (
        [0] => Exp
        [1] => 1026
        [2] => Exp
    )
    Array
    (
        [0] => CVVCVCSecurity
        [1] => 300
        [2] => Exp
    )
    Array
    (
        [0] => CurrencyExponent
        [1] => 2
        [2] => CurrencyExponent
    )
    Array
    (
        [0] => AVSname
        [1] => JOHN
        [2] => R
        [3] => SMITH
        [4] => AVSname
    )
    Array
    (
        [0] => <?xml version='1.0' encoding='UTF-8'?>
        [1] =>                     <Request>
        [2] =>                             <NewOrder>
        [3] =>                                     <IndustryType>MO</IndustryType>
        [4] =>                                     <MessageType>AC</MessageType>
        [5] =>                                     <BIN>000001</BIN>
        [6] =>                                     <MerchantID>209238</MerchantID>
        [7] =>                                     <TerminalID>001</TerminalID>
        [8] =>                                     <CardBrand>VI</CardBrand>
        [9] =>                                     <CardDataNumber>****************</AccountNum>
        [10] =>                                     <***>1026</***>
        [11] =>                                     <CVVCVCSecurity>***</***>
        [12] =>                                     <CurrencyCode>124</CurrencyCode>
        [13] =>                                     <****************>*</****************>
        [14] =>                                     <AVSzip>A2B3C3</AVSzip>
        [15] =>                                     <AVSaddress1>2010 Road SW</AVSaddress1>
        [16] =>                                     <AVScity>Calgary</AVScity>
        [17] =>                                     <AVSstate>AB</AVSstate>
        [18] =>                                     <*******>**** * *****</*******>
        [19] =>                                     <OrderID>23123INV09123</OrderID>
        [20] =>                                     <Amount>127790</Amount>
        [21] =>                             </NewOrder>
        [22] =>                     </Request>
    )

1 个答案:

答案 0 :(得分:0)

一个问题:您确定您的XML数据正确吗?

 <CardDataNumber>5454545454545454</AccountNum>

应该不是这样的:

 <CardDataNumber>5454545454545454</CardDataNumber>

或类似这样:

 <AccountNum>5454545454545454</AccountNum>

此行中的相同问题:

 <CVVCVCSecurity>300</Exp>

因此,如果您从以下位置更改代码部分:

if (strcmp($sensData[$f], $currNono) == true && $f+1 != count($sensData)){
  $hash = str_repeat("*", strlen($sensData[$f+1]));
  $lines[$currLine] = str_replace($sensData[$f+1], $hash, $lines[$currLine]);
}

对此:

if ($f > 0 && $f < count($sensData)-1){
  $hash = str_repeat("*", strlen($sensData[$f]));
  $lines[$currLine] = str_replace($sensData[$f], $hash, $lines[$currLine]);
}

让我解释一下我的解决方案: if语句现在检查$ f是否为0(括号中的第一个匹配项)而不是匹配数-1(因此括号中的最后一个匹配项)。如果是这样,它就是内容,并且会根据Asterix(*)字符的合适长度进行更改。

在“我的测试”中,它可以正常工作,如果有任何疑问,请发表评论!

  

提示!已与CurrencyExponent匹配,因为它包含 Exp ,如下所示:Currency Exp onent