首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从Aadhaar卡的安全QR代码中验证移动电话和电子邮件id

如何从Aadhaar卡的安全QR代码中验证移动电话和电子邮件id
EN

Stack Overflow用户
提问于 2020-10-13 18:41:15
回答 2查看 864关注 0票数 3

关于如何从UIDAI Aadhaar卡的安全QR代码读取QR代码数据的正式文档:15032019.pdf

使用zxing扫描器扫描安全的QR代码,并在Github:https://github.com/dimagi/AadharUID中的以下项目的帮助下获得了aadhar卡的详细信息。

如何利用文档上的说明从转换后的字节数组中提取照片和bit_indicator_value

但是,我无法从Aadhar卡字节数组的安全QR代码中获得电子邮件和移动的精确哈希值来验证。

我对第6页上述文件的这一行感到有点困惑:

  • Post获取签名值,检查Email_mobile_present_bit_indicator_value的值:
  1. 如果它的3,然后首先从索引读取移动(字节数组长度- 1-256),然后从索引电子邮件(字节数组长度-1-256-32)以相反的顺序。每个值的固定大小为32字节。
  2. 如果Email_mobile_present_bit_indicator_value是1,那么只有移动设备才会出现。
  3. 如果Email_mobile_present_bit_indicator_value是2,那么只有电子邮件存在。
  4. 如果Email_mobile_present_bit_indicator_value为0,则没有移动或电子邮件。
  • 电子邮件和移动值将以字节为单位。转换成十六进制字符串。。

我还准备了第6页文档中的最后一步,但是用户移动/电子邮件哈希值和文档移动/电子邮件字节数组哈希值永远不匹配。

代码片段:

代码语言:javascript
复制
    public ScanResult(String input) {
        rawString = input;

        // copied from http://www.java-samples.com/showtutorial.php?tutorialid=152
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        Document dom;
        try {

            //Using factory get an instance of document builder
            DocumentBuilder db = dbf.newDocumentBuilder();
            // Replace </?xml... with <?xml...
            if (input.startsWith("</?")) {
                input = input.replaceFirst("</\\?", "<?");
            }
            // Replace <?xml...?"> with <?xml..."?>
            input = input.replaceFirst("^<\\?xml ([^>]+)\\?\">", "<?xml $1\"?>");
            //parse using builder to get DOM representation of the XML file
            dom = db.parse(new ByteArrayInputStream(input.getBytes("UTF-8")));

        } catch (ParserConfigurationException | SAXException | IOException e) {
            dom = null;
        }

        if (rawString.matches("[0-9]*")) {
            type = QR_CODE_TYPE_SECURE;
            byte[] msgInBytes = null;
            try {
                msgInBytes = decompressByteArray(new BigInteger(rawString).toByteArray());
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (msgInBytes != null) {
                int[] delimiters = locateDelimiters(msgInBytes);
                String referenceId = getValueInRange(msgInBytes, delimiters[0] + 1, delimiters[1]);
                uid = referenceId.substring(0, 4);
                name = getValueInRange(msgInBytes, delimiters[1] + 1, delimiters[2]);
                dob = formatDate(getValueInRange(msgInBytes, delimiters[2] + 1, delimiters[3]),
                        new String[] {"dd-MM-yyyy", "dd/MM/yyyy"});
                yob = dob.substring(0, 4);
                gender = getValueInRange(msgInBytes, delimiters[3] + 1, delimiters[4]);
                co = getValueInRange(msgInBytes, delimiters[4] + 1, delimiters[5]);
                dist = getValueInRange(msgInBytes, delimiters[5] + 1, delimiters[6]);
                lm = getValueInRange(msgInBytes, delimiters[6] + 1, delimiters[7]);
                house = getValueInRange(msgInBytes, delimiters[7] + 1, delimiters[8]);
                loc = getValueInRange(msgInBytes, delimiters[8] + 1, delimiters[9]);
                pc = getValueInRange(msgInBytes, delimiters[9] + 1, delimiters[10]);
                po = getValueInRange(msgInBytes, delimiters[10] + 1, delimiters[11]);
                state = getValueInRange(msgInBytes, delimiters[11] + 1, delimiters[12]);
                street = getValueInRange(msgInBytes, delimiters[12] + 1, delimiters[13]);
                subdist = getValueInRange(msgInBytes, delimiters[13] + 1, delimiters[14]);
                vtc = getValueInRange(msgInBytes, delimiters[14] + 1, delimiters[15]);
                statusCode = STATUS_SUCCESS;
            } else {
                statusCode = STATUS_PARSE_ERROR;
                uid = "";
                name = "";
                gender = "";
                yob = "";
                co = "";
                house = "";
                street = "";
                lm = "";
                loc = "";
                vtc = "";
                po = "";
                dist = "";
                subdist = "";
                state = "";
                pc = "";
                dob = "";
            }
        } else {
            type = QR_CODE_TYPE_UNKNOWN;
            statusCode = STATUS_PARSE_ERROR;
            uid = "";
            name = "";
            gender = "";
            yob = "";
            co = "";
            house = "";
            street = "";
            lm = "";
            loc = "";
            vtc = "";
            po = "";
            dist = "";
            subdist = "";
            state = "";
            pc = "";
            dob = "";
        }

        dobGuess = getDobGuess(dob, yob);
        statusText = getStatusText(statusCode);
    }

private static int[] locateDelimiters(byte[] msgInBytes) {
        int[] delimiters = new int[NUMBER_OF_PARAMS_IN_SECURE_QR_CODE + 1];
        int index = 0;
        int delimiterIndex;
        for (int i = 0; i <= NUMBER_OF_PARAMS_IN_SECURE_QR_CODE; i++) {
            delimiterIndex = getNextDelimiterIndex(msgInBytes, index);
            delimiters[i] = delimiterIndex;
            index = delimiterIndex + 1;
        }
        return delimiters;
    }


    private static String getValueInRange(byte[] msgInBytes, int start, int end) {
        return new String(Arrays.copyOfRange(msgInBytes, start, end), Charset.forName("ISO-8859-1"));
    }

    private static int getNextDelimiterIndex(byte[] msgInBytes, int index) {
        int i = index;
        for (; i < msgInBytes.length; i++) {
            if (msgInBytes[i] == -1) {
                break;
            }
        }
        return i;
    }

    private static byte[] decompressByteArray(byte[] bytes) throws IOException {
        java.io.ByteArrayInputStream bytein = new ByteArrayInputStream(bytes);
        java.util.zip.GZIPInputStream gzin = new GZIPInputStream(bytein);
        java.io.ByteArrayOutputStream byteout = new ByteArrayOutputStream();

        int res = 0;
        byte buf[] = new byte[1024];
        while (res >= 0) {
            res = gzin.read(buf, 0, buf.length);
            if (res > 0) {
                byteout.write(buf, 0, res);
            }
        }
        return byteout.toByteArray();
    }

    private String formatDate(String rawDateString, String[] possibleFormats) {
        if (rawDateString.equals("")) {
            return "";
        }
        SimpleDateFormat toFormat = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        ParseException parseException = null;
        for (String fromFormatPattern : possibleFormats) {
            try {
                SimpleDateFormat fromFormat = new SimpleDateFormat(fromFormatPattern);
                date = fromFormat.parse(rawDateString);
                break;
            } catch (ParseException e) {
                parseException = e;
            }
        }
        if (date != null) {
            return toFormat.format(date);
        } else if (parseException != null) {
            System.err.println("Expected dob to be in dd/mm/yyyy or yyyy-mm-dd format, got " + rawDateString);
            return rawDateString;
        } else {
            throw new AssertionError("This code is unreachable");
        }
    }

    @NonNull
    protected String formatGender(String gender) throws ParseException {
        String lowercaseGender = gender.toLowerCase();
        if (lowercaseGender.equals("male") || lowercaseGender.equals("m")) {
            return "M";
        } else if (lowercaseGender.equals("female") || lowercaseGender.equals("f")) {
            return "F";
        } else if (lowercaseGender.equals("other") || lowercaseGender.equals("o")) {
            return "O";
        } else {
            throw new ParseException("404 gender not found", 0);
        }
    }

    @NonNull
    private String getStatusText(int statusCode) {
        switch (statusCode) {
            case ScanResult.STATUS_SUCCESS:
                return "✓";
            default:
                return "✗";
        }
    }

    @NonNull
    private String getDobGuess(String dob, String yob) {
        if (dob.equals("")) {
            Integer yearInt;
            try {
                yearInt = Integer.parseInt(yob);
            } catch (NumberFormatException e) {
                return "";
            }
            // June 1 of the year
            return Integer.toString(yearInt) + "-06-01";
        } else {
            return dob;
        }
    }

Github代码链接

EN

回答 2

Stack Overflow用户

发布于 2020-10-14 06:25:08

刚刚得到了解决方案,从字节数组中获取精确的移动和电子邮件哈希值。

首先从字节数组中删除最后256个字节,

如果只有移动的存在,那么从移动字节数组中取出最后的32个字节,即(array.length - 32到array.length)

否则,如果仅存在电子邮件,则从字节数组获取电子邮件的最后32个字节,即(array.length - 32到array.length)。

否则,如果电子邮件和移动通信都来自移动字节数组的最后32个字节,则取后32个字节作为电子邮件,即( array.length - 32 to array.length,email = array.length - 64 to array.length - 32)。

票数 2
EN

Stack Overflow用户

发布于 2021-06-08 16:19:37

从字节数组中,您需要从索引byte_array_length - 256 - 32读取值到byte_array_length - 256,以获得以字节为单位的移动散列(您可以轻松地将字节转换为十六进制字符串),同样,对于电子邮件,您需要从索引byte_array_length - 256 - 32 - 32读取到byte_array_length - 256 - 32

我已经实现了一个用于解码的库,但是实现是用Python实现的。

这个问题有点老了,但未来的读者可能会发现这些资源很有用。

PyPI:阿达尔-比

Github:https://github.com/vishaltanwar96/aadhaar-py

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64341259

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档