0

現在、第三者からのメッセージを検証しようとしています。私が抱えている問題は、信頼の連鎖を作成できないことです。これは、サブジェクト名 (X509SubjectName) 内の項目の順序が、含まれている証明書から抽出した場合と同様に、証明書内で異なるためです。

例: xades-t メッセージでは、x509SubjectName タグには「C=NL,O=Test company,CN=testuser,SERIALNUMBER=1」があり、証明書に含まれる x509SubjectName には「SERIALNUMBER=1,CN=testuser」があります。 ,O=テスト会社,C=NL"

私の質問は、これが許可されているかどうかです。また、Xades4j の動作を変更してこれらの署名付きメッセージを検証するにはどうすればよいですか。SignatureUtils クラスに証明書がないようです。コードは処理できるようですが、使用されたマップは空です。

よろしく、ピム

4

2 に答える 2

1

RFC2253ドキュメントのセクション2.1には、次のように記載されています。

2.1。RDNSequenceの変換

RDNSequenceが空のシーケンスの場合、結果は空または長さゼロの文字列になります。


それ以外の場合、出力は、RDNSequence(2.2による)の各RelativeDistinguishedNameの文字列エンコーディングで構成され
、シーケンスの最後の要素から始まり、最初の要素に
向かって逆方向に移動します。

隣接するRelativeDistinguishedNamesのエンコーディングは、コンマ文字('、' ASCII 44)で区切られます。

したがって、順序が何であれ、順序を逆にする必要があります。したがって、最初に実装を確認し、相対識別名の順序を逆にする必要があると思います。

于 2012-12-14T15:25:03.310 に答える
0

xades4jの動作を変更することによる回避策。

X509SubjectNameの属性の順序が、関連する証明書のDNの順序と同じである必要があるというドキュメントが見つからなかったためです。堅牢性のために次のパッチが必要だと思います。

xades4j.verification.SignatureUtil.javaがサブジェクト名に依存することを決定した場合。使用を継続するだけでなく、サブジェクト名が証明書のサブジェクト名と同一であるかどうかを確認する必要があります。これは、完全な文字列を比較することによって行うことはできません。代わりに、両方のサブジェクト名をマッシュオール解除し、関連するものに基づいて比較する必要があります。

まず、選択動作を少し変更する必要があります。サブジェクト名を使用するのではなく、最初に証明書からDNを取得してから、それらの値を比較します。完全な文字列を使用して一致しない場合は、実際のコンテンツと一致する可能性があります。そのため、両方のDNの属性を取得する必要があります。違いが見つからない場合でも、同じDNを処理しています。この場合、フレームワークはサブジェクト名に依存して証明書ストアから証明書を取得することはできません。代わりに、KeyInfoオブジェクトに証明書を渡します。(それは見つかります!)

        if (x509Data.containsIssuerSerial()) {
            issuerSerial = x509Data.itemIssuerSerial(0);
            certSelector.setIssuer(new X500Principal(issuerSerial.getIssuerName()));
            certSelector.setSerialNumber(issuerSerial.getSerialNumber());
        } else if (x509Data.containsSubjectName()) {
            String subjectName = x509Data.itemSubjectName(0).getSubjectName();
            X500Principal msgPrincipal = new X500Principal(subjectName);
            String name = msgPrincipal.getName();

            X509Certificate crt = x509Data.itemCertificate(0).getX509Certificate();
            X500Principal crtPrincipal = crt.getSubjectX500Principal();

            X500Principal prinFromCrt = crt.getSubjectX500Principal();
            if(prinFromCrt.getName().equals(msgPrincipal.getName())){
                // Continue using the xades specified subjectname
                 certSelector.setSubject(msgPrincipal);
            } else {
                //so the subject names are not equal.
                //However the ietf specifications indicate you cannot rely on the order of the attributed.
                //Therefor we need to compare all attributes seperately to know for sure.

               boolean hasSameKeyValues = compareUnmarshelledX500PrincipalAttr(crtPrincipal,msgPrincipal);
               if (hasSameKeyValues){

                   if (x509Data.containsCertificate()) {
                       certSelector.setCertificate(x509Data.itemCertificate(0).getX509Certificate());
                   }
               }    
            }

        } else if (x509Data.containsCertificate()) {
            certSelector.setCertificate(x509Data.itemCertificate(0).getX509Certificate());
            if (x509Data.containsSubjectName()){
                //if(!(isEqualX500Elements(new X500Principal(x509Data.itemSubjectName(0).getSubjectName()), x509Data.itemCertificate(0).getX509Certificate()))){
                //     throw new InvalidKeyInfoDataException("X509Subject name differs from Subject name in certificate.");
                //}
            }
        } else
        // No criteria to select the leaf certificate.
        // Improvement: search the SigningCertiticate property and try to
        // find the "bottom" certificate.
        {
            throw new InvalidKeyInfoDataException("No criteria to select the leaf certificate");
        }

以下は、DNを取得し、キーとその値を含むHashMapを要求するメソッドです。同一であるかどうかに関係なく、ブール値のみが返されます。

       private static boolean compareUnmarshelledX500PrincipalAttr(X500Principal DN1, X500Principal DN2) {
       HashMap attrDNCrt = splitDNAttr(DN1.getName());
       HashMap attrDNMsg = splitDNAttr(DN2.getName());

       if(attrDNCrt.keySet().equals(attrDNMsg.keySet())){
           Set ks = attrDNCrt.keySet();
           Iterator iKS = ks.iterator();
           while (iKS.hasNext()){
               String key = (String) iKS.next();
               if(!attrDNCrt.get(key).toString().equals(attrDNMsg.get(key).toString())){
                   //Value of attribute is different. So not identical
                   return false;
               }
           }
           //Yes, despite possible differences in order the key value pairs are identical.");
           return true;
       } else {
           //"KeySets differ so they are different"
           return false;
       }
}

splitDNAttrは、キーの名前に「、」が含まれないという事実に依存します。そのため、最初に「=」で分割し、次に最後の「、」で分割します。おそらく、そのトリックを実行する正規表現がそこにあります。(残念ながら、正規表現は私には完全に読めません。)メソッドは私には機能しますが、可能性のある末尾のスペースを削除する必要があるかどうか疑問に思います。

static private HashMap splitDNAttr(String inputStr){
    String[] strings;
    List looseElements;
    looseElements = new ArrayList();
    //First split on the = which normally isn't escaped.
    strings = inputStr.split("=");        
    looseElements.add(strings[0]);
    //Loop Through string members

    int i=1;
    while (i<strings.length){
        String[] subStrings;
        //Look for the last comma, everything after is a key! This is because we have splitted the string on '='
        int splitPos = strings[i].lastIndexOf(",");
        if(splitPos>=0){
            //Add all found items to a list. Order must be maintained!
            String A = strings[i].substring(0,splitPos);
            looseElements.add(strings[i].substring(0,splitPos));
            String B = strings[i].substring(splitPos+1);
            looseElements.add(strings[i].substring(splitPos+1));
        } else {
            looseElements.add(strings[i]);
        }
        i++;
    }

    // Put key and values in a HashMap
    HashMap dnAttr = new HashMap();
    Iterator iLooseElements;
    iLooseElements = looseElements.iterator();
    String a;
    String b;
    while(iLooseElements.hasNext()){
        a = (String) iLooseElements.next();
        b = (String) iLooseElements.next();
        dnAttr.put(a, b);
    }
    return dnAttr;
}
于 2012-12-14T14:48:18.833 に答える