duanmei1930 2018-06-20 06:39
浏览 40
已采纳

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

A string parameter is passed to the function – below are various samples of possible input data The function receives this data as a string, not an array, json or other data formats The function should parse the string and mask sensitive data. Sensitive data should be masked (replaced) with an Asterix (*) character. Sensitive data includes the fields below, but new sensitive fields should be easily added to the function as needed:

The credit card number

The credit card expiry date

The credit card CVV value

The function returns the parsed string in the same format that it was provided, but with the sensitive data now masked.

  <?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("
", $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:

"; //print results
    helcimTest($testData1, $parseNew);
    echo "Data set 2:

";
    helcimTest($testData2, $parseNew);
    echo "Data set 3:

";
    helcimTest($testData3, $parseNew);
    echo "Data set 4:

";
    helcimTest($testData4, $parseNew);

The output appears as such, some of the values are correctly parsed, and some feel totally random. The first part of the function handles the credit card number alone, which is consistently parsed correctly, it's when the function reaches its bottom half that the patterns I've laid out just don't make any sense when compared to the results:

    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条回答 默认 最新

  • donglinli2027 2018-06-20 08:12
    关注

    One Question: Are you sure that your XML Data is correct?

     <CardDataNumber>5454545454545454</AccountNum>
    

    Shouldn't it look like this:

     <CardDataNumber>5454545454545454</CardDataNumber>
    

    or like this:

     <AccountNum>5454545454545454</AccountNum>
    

    same Problem in this Line:

     <CVVCVCSecurity>300</Exp>
    

    so if you change your code-part from:

    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]);
    }
    

    to this:

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

    Let me explain my solution: The if Statement checks now that if $f is not 0 (the first match in the brackets) and not count of matches - 1 (so the last match in the brackets). If so, it's the content and this is changed with the fitting length of Asterix (*) characters.

    In my Test it do the work right, please comment if you have any questions!

    HINT! CurrencyExponent is matched because it contains Exp as you see: CurrencyExponent

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 如何用脚本实现输入法的热键设置
  • ¥20 我想使用一些网络协议或者部分协议也行,主要想实现类似于traceroute的一定步长内的路由拓扑功能
  • ¥30 深度学习,前后端连接
  • ¥15 孟德尔随机化结果不一致
  • ¥15 apm2.8飞控罗盘bad health,加速度计校准失败
  • ¥15 求解O-S方程的特征值问题给出边界层布拉休斯平行流的中性曲线
  • ¥15 谁有desed数据集呀
  • ¥20 手写数字识别运行c仿真时,程序报错错误代码sim211-100
  • ¥15 关于#hadoop#的问题
  • ¥15 (标签-Python|关键词-socket)