コード例 #1
0
 def extractOwnerInfo(self, data):
     if not data.has_key('5F1F') or not data.has_key('5F5B'):
         raise Exception("Could not extract name/mrz")
     mrz = data['5F1F'][44:88]
     name = (data['5F5B']).split("<<")
     name = helper.getItem(name[0]) + " " + helper.getItem(name[1])
     return (name,mrz)
コード例 #2
0
ファイル: overview.py プロジェクト: oroger/epassportviewer-1
 def loadDG13(self, fields, data):
     if data.has_key("9F01"):
         fields['height'].set(getItem(data['9F01']) + " m")
     if data.has_key("9F02"):
         fields['eyesColour'].set(getItem(data['9F02']))
     if data.has_key("9F03"):
         fields['residence'].set(getItem(data['9F03']))
コード例 #3
0
ファイル: overview.py プロジェクト: oroger/epassportviewer-1
    def loadDG1(self, fields, data):
        if data.has_key('5F1F'):
            mrz = data['5F1F']
            mrz = mrz[:44] + "\n" + mrz[44:]
            if len(data['5F1F']) > 88:
                mrz = mrz[:89] + "\n" + mrz[89:]
            fields['mrz'].set(mrz)

        if data.has_key('5F5B'):
            name = (data['5F5B']).split("<<")
            fields['name'].set(getItem(name[0]))
            fields['surname'].set(getItem(name[1]))

        if data.has_key('5F03'):
            fields['type'].set(getItem(data['5F03']))
        if data.has_key('5F28'):
            fields['issueCountry'].set(getItem(data['5F28']))
        if data.has_key('5A'):
            fields['passportNumber'].set(getItem(data['5A']))
        if data.has_key('5F2C'):
            fields['nationality'].set(getItem(data['5F2C']))
        if data.has_key('5F57'):
            fields['birthDate'].set(getItem(data['5F57']))
        if data.has_key('5F35'):
            fields['sex'].set(getItem(data['5F35']))
        if data.has_key('59'):
            fields['expiryDate'].set(getItem("20" + data['59'])) # 20 make a "real" date
コード例 #4
0
ファイル: overview.py プロジェクト: oroger/epassportviewer-1
 def loadDG11(self, fields, data):
     if data.has_key("5F2B"):
         fields['birthDate'].set(getItem(data['5F2B']))
     if data.has_key("5F11"):
         fields['birthPlace'].set(getItem(data['5F11']))
     # This DG keep the accents, contrary to the DG1
     # but beware some passports contain an empty or almost empty 5F0E (e.g. BE: 5F0E0120 or 5F0E00)
     if data.has_key("5F0E") and \
        len(data['5F0E']) > len(fields['name'].get()) + len(fields['surname'].get()):
         if "<<" in data['5F0E']:
           tmpname = (data['5F0E']).split("<<")
           fields['name'].set(getItem(tmpname[0]))
           fields['surname'].set(getItem(tmpname[1]))
         else:
           # no specific separator between name(s) and surname(s)
           tmpname = (data['5F0E']).split(" ")
           namewords = len(fields['name'].get().split(" "))
           fields['name'].set(getItem(' '.join(tmpname[:namewords])))
           fields['surname'].set(getItem(' '.join(tmpname[namewords:])))
     # French, nom d'usage, http://fr.wikipedia.org/wiki/Nom_d'usage_en_France
     if data.has_key("A0") and getItem(data['A0'])[0] != '\x02':
         # TODO: some Belgian passports contain
         # 5F0E 00 A0 06020101 5F0F 00
         # is there a better way to discard their A0??
         old = fields['name'].get()
         fields['name'].set(old + ", " + getItem(data['A0']))
コード例 #5
0
ファイル: overview.py プロジェクト: oroger/epassportviewer-1
 def loadDG12(self, fields, data):
     if data.has_key("5F19"):
         fields['authority'].set(getItem(data['5F19']))
     if data.has_key("5F26"):
         fields['issueDate'].set(getItem(data['5F26']))
コード例 #6
0
ファイル: inOut.py プロジェクト: akpotter/epassportviewer
def toPDF(data, filename):
    """ Export doc9303 instance to PDF

        @param doc: doc9303
        @type doc: doc9303 instance (pyPassport)
        @param filename: output file
        @type filename: String
        @return: None
    """



    doc = SimpleDocTemplate(filename, pagesize=letter,
                            rightMargin=72, leftMargin=72,
                            topMargin=72, bottomMargin=18)
    Story=[]
    styles=getSampleStyleSheet()

    # NAME
    name = (data["EP"]["DG1"]["5F5B"]).split("<<")
    Story.append(Paragraph(getItem(name[1].upper())+" "+getItem(name[0].upper()), styles["Heading1"]))

    # PICTURE
    tag = None
    if data["EP"]["DG2"]["A1"].has_key("5F2E"): tag = "5F2E"
    elif data["EP"]["DG2"]["A1"].has_key("7F2E"): tag = "7F2E"
    if tag != None:
        path = None
        raw = data["EP"]["DG2"]["A1"][tag]
        profile = writeImageToDisk(raw, "~picture")
        img_file = PIL.Image.open(profile)
        width, height = img_file.size
        ratio = float(width)/float(2*inch)
        h_img = float(height)/ratio
        im = Image(profile, 2*inch, h_img)
        Story.append(im)

    try:
        if data["EP"].has_key("DG7") and data["EP"]["DG7"].has_key("5F43"):
            raw = data["EP"]["DG7"]["5F43"][0]
            signature = writeImageToDisk(raw, "~signature")
            img_signature = PIL.Image.open(signature)
            width, height = img_signature.size
            ratio = float(width)/float(2*inch)
            h_img = float(height)/ratio
            sign = Image(signature, 2*inch, h_img)
            Story.append(sign)
    except Exception:
        pass

    # OVERVIEW
    Story.append(Paragraph("Overview", styles["Heading2"]))
    Story.append(Paragraph("<font size=12>Type: " + getItemByTag(data["EP"], 'DG1','5F03') + "</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Passport #: "+str(getItemByTag(data["EP"],'DG1','5A'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Country: "+str(getItemByTag(data["EP"],'DG1','5F28'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Authority: "+str(getItemByTag(data["EP"],'DG12','5F19'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Issue Date: "+str(getItemByTag(data["EP"],'DG12','5F26'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Expiry Place: "+str(getItemByTag(data["EP"],'DG1','59'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Nationality: "+str(getItemByTag(data["EP"],'DG1','5F2C'))+"</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(Paragraph("<font size=12>Name: "+str(getItem(name[0]))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Surname: "+str(getItem(name[1]))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Birth Date: "+str(getItemByTag(data["EP"],'DG1','5F57'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Birth Place: "+str(getItemByTag(data["EP"],'DG11','5F11'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Sex: "+str(getItemByTag(data["EP"],'DG1','5F35'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Height: "+str(getItemByTag(data["EP"], 'DG13', '9F01'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Colour of eyes: "+str(getItemByTag(data["EP"], 'DG13', '9F02'))+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Residence: "+str(getItemByTag(data["EP"], 'DG13', '9F03'))+"</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(Paragraph("Basic Access Control", styles["Heading2"]))
    Story.append(Paragraph("<font size=12>Basic Access Control: "+data["bac"]+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Reading time: "+str(data["ReadingTime"])+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Data Groups size:</font>", styles["Normal"]))
    for key, value in data["DGs"]:
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp- " + str(key) + ": " + str(value) + " octets"+"</font>", styles["Normal"]))
    # PRESENT DATAGROUPS
    #Story.append(Paragraph("Present DataGroups", styles["Heading2"]))
    #k = map(toOrder, data["EP"].keys())
    #k.sort()
    #k = map(toDG,k)
    #for dg in k:
    #    Story.append(Paragraph("<font size=12>&nbsp;&nbsp;- "+str(dg)+"</font>", styles["Normal"]))
    #Story.append(Spacer(1, 20))

    # DUMP
    Story.append(Paragraph("MRZ information", styles["Heading3"]))
    for item in data["EP"]["DG1"]:
        try:
            tag_name = tagToName[item]
        except Exception:
            tag_name = item
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;"+tag_name+": "+getItemRaw(data["EP"], 'DG1', item)+"</font>",
                                styles["Normal"]))
    Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG11"):
        Story.append(Paragraph("Additional document holder details", styles["Heading3"]))
        for item in data["EP"]["DG11"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(Paragraph("<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;"+tag_name+": "+getItemRaw(data["EP"], 'DG11', item)+"</font>",
                                    styles["Normal"]))
        Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG12"):
        Story.append(Paragraph("Additional document information", styles["Heading3"]))
        for item in data["EP"]["DG12"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(Paragraph("<font size=12>    "+tag_name+": "+getItemRaw(data["EP"], 'DG12', item)+"</font>",
                                    styles["Normal"]))
        Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG13"):
        Story.append(Paragraph("Reserved for national specific data", styles["Heading3"]))
        for item in data["EP"]["DG13"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(Paragraph("<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;"+tag_name+": "+getItemRaw(data["EP"], 'DG13', item)+"</font>",
                                    styles["Normal"]))
        Story.append(Spacer(1, 12))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Passive Authentication", styles["Heading2"]))
    Story.append(Paragraph("DG integrity:", styles["Heading3"]))
    for dgi in data["Integrity"]:
        if data["Integrity"][dgi] == True:
            v = "Verified"
        elif data["Integrity"][dgi] == False:
            v = "Not verified"
        elif data["Integrity"][dgi] == None:
            v = "No hash present in SOD for this EF"
        else:
            v = "N/A"
        Story.append(Paragraph("<font size=12>  "+dgi+": "+v+"</font>", styles["Normal"]))
    Story.append(Paragraph("DG hashes:", styles["Heading3"]))
    for dgi in data["Hashes"]:
        Story.append(Paragraph("<font size=12>  "+dgi + ": " + binToHexRep(data["Hashes"][dgi])+"</font>", styles["Normal"]))

    Story.append(Paragraph("SOD", styles["Heading3"]))
    Story.append(Paragraph("<font size=10>"+data["SOD"].replace("\n", "<br/>")+"</font>", styles["Normal"]))

    Story.append(Paragraph("Certificate", styles["Heading3"]))
    Story.append(Paragraph("<font size=12>Certificate Serial Number:"+data["certSerialNumber"]+"</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Certificate Fingerprint:"+data["certFingerPrint"]+"</font>", styles["Normal"]))

    Story.append(Paragraph("Document Signer", styles["Heading3"]))
    data["DSCertificate"] = data["DSCertificate"].replace("\n", "<br/>")
    data["DSCertificate"] = data["DSCertificate"].replace(" ", "&nbsp;")
    Story.append(Paragraph("<font size=10>"+data["DSCertificate"]+"</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Active Authentication", styles["Heading2"]))
    Story.append(Paragraph("<font size=12>Active Authentication executed:"+data["activeAuth"]+"</font>", styles["Normal"]))
    Story.append(Paragraph("Public Key", styles["Heading3"]))
    data["pubKey"] = data["pubKey"].replace("\n", "<br/>")
    data["pubKey"] = data["pubKey"].replace(" ", "&nbsp;")
    Story.append(Paragraph("<font size=10>"+data["pubKey"]+"</font>", styles["Normal"]))

    Story.append(Paragraph("Extended Access Control", styles["Heading2"]))
    Story.append(Paragraph("<font size=12>EAC has not been implemented yet.</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Here is of DG that the reader cannot access:</font>", styles["Normal"]))
    for fdg in data["failedToRead"]:
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp;- " + fdg + "</font>", styles["Normal"]))
    if not data["failedToRead"]:
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp; List empty: No EAC implemented in passport</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Security investigation", styles["Heading2"]))
    Story.append(Paragraph("Security measures", styles["Heading3"]))
    Story.append(Paragraph("<font size=12>Delay security measure after a wrong BAC: " + str(data["delaySecurity"]) + "</font>", styles["Normal"]))
    Story.append(Paragraph("<font size=12>Block the communication after a wrong BAC: " + str(data["blockAfterFail"]) + "</font>", styles["Normal"]))

    Story.append(Paragraph("Potential vulnerabilities", styles["Heading3"]))
    (vuln, ans) = data["activeAuthWithoutBac"]
    Story.append(Paragraph("<font size=12>Active Authentication before BAC: " + str(vuln) + "</font>", styles["Normal"]))
    if vuln: Story.append(Paragraph("<font size=12>&nbsp;&nbsp;* Vulnerable to AA Traceability</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(Paragraph("<font size=12>Different response time for wrong message or MAC: " + str(data["macTraceability"]) + "</font>", styles["Normal"]))
    if data["macTraceability"]:
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp;* Vulnerable to MAC traceability</font>", styles["Normal"]))
        Story.append(Paragraph("<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;Note: If delay security measure implemented, this might be a false positive</font>", styles["Normal"]))
    Story.append(Spacer(1, 12))
    (vuln, error) = data["getChallengeNull"]
    Story.append(Paragraph("<font size=12>Passport answers to a GET CHALLENGE with the Le set to '01': " + str(vuln) + "</font>", styles["Normal"]))
    if vuln: Story.append(Paragraph("<font size=12>&nbsp;&nbsp;* Vulnerable to lookup brute force</font>", styles["Normal"]))

    Story.append(Paragraph("Error Fingerprinting", styles["Heading3"]))
    for ins in data["Errors"]:
        Story.append(Paragraph('<font size=12>APDU "00" "' + ins + '" "00" "00" "" "" "00": ' + data["Errors"][ins] + "</font>", styles["Normal"]))


    doc.build(Story)

    if tag != None:
        os.remove(profile)
        try:
            os.remove(signature)
        except NameError:
            pass
コード例 #7
0
ファイル: inOut.py プロジェクト: yangzhibo450/epassportviewer
def toPDF(data, filename):
    """ Export doc9303 instance to PDF

        @param doc: doc9303
        @type doc: doc9303 instance (pyPassport)
        @param filename: output file
        @type filename: String
        @return: None
    """

    doc = SimpleDocTemplate(filename,
                            pagesize=letter,
                            rightMargin=72,
                            leftMargin=72,
                            topMargin=72,
                            bottomMargin=18)
    Story = []
    styles = getSampleStyleSheet()

    # NAME
    name = (data["EP"]["DG1"]["5F5B"]).split("<<")
    Story.append(
        Paragraph(
            getItem(name[1].upper()) + " " + getItem(name[0].upper()),
            styles["Heading1"]))

    # PICTURE
    tag = None
    if data["EP"]["DG2"]["A1"].has_key("5F2E"): tag = "5F2E"
    elif data["EP"]["DG2"]["A1"].has_key("7F2E"): tag = "7F2E"
    if tag != None:
        path = None
        raw = data["EP"]["DG2"]["A1"][tag]
        profile = writeImageToDisk(raw, "~picture")
        img_file = PIL.Image.open(profile)
        width, height = img_file.size
        ratio = float(width) / float(2 * inch)
        h_img = float(height) / ratio
        im = Image(profile, 2 * inch, h_img)
        Story.append(im)

    try:
        if data["EP"].has_key("DG7") and data["EP"]["DG7"].has_key("5F43"):
            raw = data["EP"]["DG7"]["5F43"][0]
            signature = writeImageToDisk(raw, "~signature")
            img_signature = PIL.Image.open(signature)
            width, height = img_signature.size
            ratio = float(width) / float(2 * inch)
            h_img = float(height) / ratio
            sign = Image(signature, 2 * inch, h_img)
            Story.append(sign)
    except Exception:
        pass

    # OVERVIEW
    Story.append(Paragraph("Overview", styles["Heading2"]))
    Story.append(
        Paragraph(
            "<font size=12>Type: " + getItemByTag(data["EP"], 'DG1', '5F03') +
            "</font>", styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Passport #: " +
            str(getItemByTag(data["EP"], 'DG1', '5A')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Country: " +
            str(getItemByTag(data["EP"], 'DG1', '5F28')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Authority: " +
            str(getItemByTag(data["EP"], 'DG12', '5F19')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Issue Date: " +
            str(getItemByTag(data["EP"], 'DG12', '5F26')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Expiry Place: " +
            str(getItemByTag(data["EP"], 'DG1', '59')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Nationality: " +
            str(getItemByTag(data["EP"], 'DG1', '5F2C')) + "</font>",
            styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(
        Paragraph("<font size=12>Name: " + str(getItem(name[0])) + "</font>",
                  styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Surname: " + str(getItem(name[1])) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Birth Date: " +
            str(getItemByTag(data["EP"], 'DG1', '5F57')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Birth Place: " +
            str(getItemByTag(data["EP"], 'DG11', '5F11')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Sex: " +
            str(getItemByTag(data["EP"], 'DG1', '5F35')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Height: " +
            str(getItemByTag(data["EP"], 'DG13', '9F01')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Colour of eyes: " +
            str(getItemByTag(data["EP"], 'DG13', '9F02')) + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Residence: " +
            str(getItemByTag(data["EP"], 'DG13', '9F03')) + "</font>",
            styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(Paragraph("Basic Access Control", styles["Heading2"]))
    Story.append(
        Paragraph(
            "<font size=12>Basic Access Control: " + data["bac"] + "</font>",
            styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Reading time: " + str(data["ReadingTime"]) +
            "</font>", styles["Normal"]))
    Story.append(
        Paragraph("<font size=12>Data Groups size:</font>", styles["Normal"]))
    for key, value in data["DGs"]:
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp- " + str(key) + ": " + str(value) +
                " octets" + "</font>", styles["Normal"]))
    # PRESENT DATAGROUPS
    #Story.append(Paragraph("Present DataGroups", styles["Heading2"]))
    #k = map(toOrder, data["EP"].keys())
    #k.sort()
    #k = map(toDG,k)
    #for dg in k:
    #    Story.append(Paragraph("<font size=12>&nbsp;&nbsp;- "+str(dg)+"</font>", styles["Normal"]))
    #Story.append(Spacer(1, 20))

    # DUMP
    Story.append(Paragraph("MRZ information", styles["Heading3"]))
    for item in data["EP"]["DG1"]:
        try:
            tag_name = tagToName[item]
        except Exception:
            tag_name = item
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;" + tag_name + ": " +
                getItemRaw(data["EP"], 'DG1', item) + "</font>",
                styles["Normal"]))
    Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG11"):
        Story.append(
            Paragraph("Additional document holder details",
                      styles["Heading3"]))
        for item in data["EP"]["DG11"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(
                Paragraph(
                    "<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;" + tag_name +
                    ": " + getItemRaw(data["EP"], 'DG11', item) + "</font>",
                    styles["Normal"]))
        Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG12"):
        Story.append(
            Paragraph("Additional document information", styles["Heading3"]))
        for item in data["EP"]["DG12"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(
                Paragraph(
                    "<font size=12>    " + tag_name + ": " +
                    getItemRaw(data["EP"], 'DG12', item) + "</font>",
                    styles["Normal"]))
        Story.append(Spacer(1, 12))

    if data["EP"].has_key("DG13"):
        Story.append(
            Paragraph("Reserved for national specific data",
                      styles["Heading3"]))
        for item in data["EP"]["DG13"]["5C"]:
            try:
                tag_name = tagToName[item]
            except Exception:
                tag_name = item
            Story.append(
                Paragraph(
                    "<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;" + tag_name +
                    ": " + getItemRaw(data["EP"], 'DG13', item) + "</font>",
                    styles["Normal"]))
        Story.append(Spacer(1, 12))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Passive Authentication", styles["Heading2"]))
    Story.append(Paragraph("DG integrity:", styles["Heading3"]))
    for dgi in data["Integrity"]:
        if data["Integrity"][dgi] == True:
            v = "Verified"
        elif data["Integrity"][dgi] == False:
            v = "Not verified"
        elif data["Integrity"][dgi] == None:
            v = "No hash present in SOD for this EF"
        else:
            v = "N/A"
        Story.append(
            Paragraph("<font size=12>  " + dgi + ": " + v + "</font>",
                      styles["Normal"]))
    Story.append(Paragraph("DG hashes:", styles["Heading3"]))
    for dgi in data["Hashes"]:
        Story.append(
            Paragraph(
                "<font size=12>  " + dgi + ": " +
                binToHexRep(data["Hashes"][dgi]) + "</font>",
                styles["Normal"]))

    Story.append(Paragraph("SOD", styles["Heading3"]))
    Story.append(
        Paragraph(
            "<font size=10>" + data["SOD"].replace("\n", "<br/>") + "</font>",
            styles["Normal"]))

    Story.append(Paragraph("Certificate", styles["Heading3"]))
    Story.append(
        Paragraph(
            "<font size=12>Certificate Serial Number:" +
            data["certSerialNumber"] + "</font>", styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Certificate Fingerprint:" +
            data["certFingerPrint"] + "</font>", styles["Normal"]))

    Story.append(Paragraph("Document Signer", styles["Heading3"]))
    data["DSCertificate"] = data["DSCertificate"].replace("\n", "<br/>")
    data["DSCertificate"] = data["DSCertificate"].replace(" ", "&nbsp;")
    Story.append(
        Paragraph("<font size=10>" + data["DSCertificate"] + "</font>",
                  styles["Normal"]))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Active Authentication", styles["Heading2"]))
    Story.append(
        Paragraph(
            "<font size=12>Active Authentication executed:" +
            data["activeAuth"] + "</font>", styles["Normal"]))
    Story.append(Paragraph("Public Key", styles["Heading3"]))
    data["pubKey"] = data["pubKey"].replace("\n", "<br/>")
    data["pubKey"] = data["pubKey"].replace(" ", "&nbsp;")
    Story.append(
        Paragraph("<font size=10>" + data["pubKey"] + "</font>",
                  styles["Normal"]))

    Story.append(Paragraph("Extended Access Control", styles["Heading2"]))
    Story.append(
        Paragraph("<font size=12>EAC has not been implemented yet.</font>",
                  styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Here is of DG that the reader cannot access:</font>",
            styles["Normal"]))
    for fdg in data["failedToRead"]:
        Story.append(
            Paragraph("<font size=12>&nbsp;&nbsp;- " + fdg + "</font>",
                      styles["Normal"]))
    if not data["failedToRead"]:
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp; List empty: No EAC implemented in passport</font>",
                styles["Normal"]))
    Story.append(Spacer(1, 12))

    Story.append(Paragraph("Security investigation", styles["Heading2"]))
    Story.append(Paragraph("Security measures", styles["Heading3"]))
    Story.append(
        Paragraph(
            "<font size=12>Delay security measure after a wrong BAC: " +
            str(data["delaySecurity"]) + "</font>", styles["Normal"]))
    Story.append(
        Paragraph(
            "<font size=12>Block the communication after a wrong BAC: " +
            str(data["blockAfterFail"]) + "</font>", styles["Normal"]))

    Story.append(Paragraph("Potential vulnerabilities", styles["Heading3"]))
    (vuln, ans) = data["activeAuthWithoutBac"]
    Story.append(
        Paragraph(
            "<font size=12>Active Authentication before BAC: " + str(vuln) +
            "</font>", styles["Normal"]))
    if vuln:
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp;* Vulnerable to AA Traceability</font>",
                styles["Normal"]))
    Story.append(Spacer(1, 12))
    Story.append(
        Paragraph(
            "<font size=12>Different response time for wrong message or MAC: "
            + str(data["macTraceability"]) + "</font>", styles["Normal"]))
    if data["macTraceability"]:
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp;* Vulnerable to MAC traceability</font>",
                styles["Normal"]))
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp;&nbsp;&nbsp;Note: If delay security measure implemented, this might be a false positive</font>",
                styles["Normal"]))
    Story.append(Spacer(1, 12))
    (vuln, error) = data["getChallengeNull"]
    Story.append(
        Paragraph(
            "<font size=12>Passport answers to a GET CHALLENGE with the Le set to '01': "
            + str(vuln) + "</font>", styles["Normal"]))
    if vuln:
        Story.append(
            Paragraph(
                "<font size=12>&nbsp;&nbsp;* Vulnerable to lookup brute force</font>",
                styles["Normal"]))

    Story.append(Paragraph("Error Fingerprinting", styles["Heading3"]))
    for ins in data["Errors"]:
        Story.append(
            Paragraph(
                '<font size=12>APDU "00" "' + ins +
                '" "00" "00" "" "" "00": ' + data["Errors"][ins] + "</font>",
                styles["Normal"]))

    doc.build(Story)

    if tag != None:
        os.remove(profile)
        try:
            os.remove(signature)
        except NameError:
            pass