Ich arbeite an einer Implementierung der C # SignedCms-Funktionalität in Java.
Ich benutze Bouncycastle-Bibliotheken. Das Problem ist, dass ich eine Java-Signatur bekomme, die sich von der unterscheidet, die mit SignedCms generiert wurde.
Beide enthalten keine x509-Zertifikate.
Länge = 434 308201AE06092A864886F70D010702A082019F3082019B020101310B300906052B0E03021A0500301306092 A864886F70D010701A006040474657874318201723082016E0201013081CB3081B6310B3009060355040613 02555331173015060355040A130E566572695369676E2C20496E632E311F301D060355040B1316566572695 369676E205472757374204E6574776F726B313B3039060355040B13325465726D73206F6620757365206174 2068747470733A2F2F7777772E766572697369676E2E636F6D2F7270612028632930393130302E060355040 31327566572695369676E20436C617373203320436F6465205369676E696E6720323030392D322043410210 1763F9A88334A01FFB3B7BAB384A9B93300906052B0E03021A0500300D06092A864886F70D0101010500048 1800B866A9A7045E3C86E5DB69CDAD5CED211A4A2362BCC4DDB2742BF0CDB65BC88556C97A6C08D68F8070D 89CC78ACD84A636F15B40D166E461411C6A04D5EC379283988DA4258B684FFEF9F08B293A03A0B40900E245 874D8C0587BBD58BDD915A50D27456E6EEB883846CAC485853BBA5E22E45D333C940A958E641A00C9602B9
Länge = 428 308006092A864886F70D010702A0803080020101310B300906052B0E03021A0500308006092A864886F70D0 107010000318201723082016E0201013081CB3081B6310B300906035504061302555331173015060355040A 130E566572695369676E2C20496E632E311F301D060355040B1316566572695369676E205472757374204E6 574776F726B313B3039060355040B13325465726D73206F66207573652061742068747470733A2F2F777777 2E766572697369676E2E636F6D2F7270612028632930393130302E06035504031327566572695369676E204 36C617373203320436F6465205369676E696E6720323030392D3220434102101763F9A88334A01FFB3B7BAB 384A9B93300906052B0E03021A0500300D06092A864886F70D01010105000481800B866A9A7045E3C86E5DB 69CDAD5CED211A4A2362BCC4DDB2742BF0CDB65BC88556C97A6C08D68F8070D89CC78ACD84A636F15B40D16 6E461411C6A04D5EC379283988DA4258B684FFEF9F08B293A03A0B40900E245874D8C0587BBD58BDD915A50 D27456E6EEB883846CAC485853BBA5E22E45D333C940A958E641A00C9602B9000000000000
Ich bleibe bei diesem Thema stecken. Um ehrlich zu sein, ich bin verzweifelt und habe keine Ahnung, was los ist.
Jede Hilfe ist willkommen.
UPD.
Die Java-Ausgabe war BER-codiert. Ich brauchte die DER-kodierte Signatur. Um BER in DER umzuwandeln benutzte ich
%Vor%Jetzt sind die Ausgaben gleich.
Vielen Dank, Jungs.
Die gute Nachricht: nichts ist falsch.
Sehen Sie sich den Anfang beider resultierenden DER-Kodierungen an:
%Vor% Die C # -Codierung hat eine bestimmte Länge, dh 30
gibt SEQUENCE
an, 82
gibt eine eindeutige Längencodierung an, die die nächsten zwei Bytes verwendet, und 01AE
ist der tatsächliche Längenwert von 430. 430 Bytes diese folgen plus die 4 gelesenen bis jetzt machen die insgesamt 434 Bytes aus.
Die Java-Codierung unterscheidet sich dagegen dadurch, dass sie eine Codierung mit unbestimmter Länge anzeigt ( 80
). Genau genommen handelt es sich nicht mehr um eine DER-Codierung, sondern um eine BER-Codierung. Dies bedeutet, dass für dieses Element keine explizite Länge angegeben wird, sondern dass das Element stattdessen mit einem speziellen Element END OF CONTENTS
endet, das als 0000
codiert ist. Am Ende der Java-Codierung werden Sie einige davon bemerken. Mehr zu den Details in diesem Leitfaden zu BER / DER.
Der Rest der beiden Strukturen ist exakt identisch, sogar der Signaturwert selbst. Es ist nur, dass die Java-Version unbestimmte Längen verwendet, während die C # -Version bestimmte Längen verwendet. Wenn die überprüfende Partei sowohl BER- als auch DER-Kodierungen versteht, sind die beiden Signaturen bis zur Kodierung identisch. Und die Codierung spielt keine Rolle bei der Signaturprüfung. Hier ist, was der CMS RFC dazu sagt:
Mit signedAttrs
vorhanden:
Insbesondere ist die anfängliche Eingabe die encapContentInfo eContent OCTET STRING, auf das der Signierungsprozess folgt wird angewandt. Nur die Oktette umfassen den Wert des eContent OCTET STRING werden in den Message Digest-Algorithmus und nicht in das Tag eingegeben oder die Länge Oktetts.
Ohne signedAttrs
:
Wenn das Feld "signedAttrs" nicht vorhanden ist, werden nur die Oktetts mit der Wert der SignedData encapContentInfo eContent OCTET STRING (z. B. Der Inhalt einer Datei) wird in die Message Digest-Berechnung eingegeben. Dies hat den Vorteil, dass die Länge des Inhalts signiert wird muss nicht vor dem Signaturerstellungsprozess bekannt sein.
Mit anderen Worten: Nur die Bytes, die den tatsächlichen Wert von eContent
enthalten, werden gehashed, und wirklich nur diese. Weder sein Tag noch seine Länge und auch nicht die Tags und Längen seiner Chunks (im Falle einer unbestimmten konstruierten Codierung) dürfen dabei gehashed werden. Ich gebe zu, es gibt Implementierungen, die das falsch verstehen und es ist eindeutig ein ziemlich kompliziertes Thema.
Obwohl es eine Menge Komplexitäts- und Interoperabilitätsprobleme mit sich bringt, ist es aus einem Grund sinnvoll (abgesehen davon, dass es ein paar Bytes kleiner ist): Wenn Sie "angehängte Signaturen" erzeugen (die, in denen das Originaldokument in EncapContentInfo
eingebettet ist) Element) ermöglicht die Auswahl unbestimmter Längen das Erstellen und Überprüfen der Signatur in einer Streaming-Weise: Sie können Chunk für Chunk lesen oder schreiben. Während man für bestimmte Längen das ganze Ding auf einmal lesen / schreiben muss, weil man die Länge im Voraus wissen muss, um das endgültige Tag-Length-Value-Format der DER-Codierung zu erzeugen. Die Idee, Streaming IO zu machen, ist in diesem Kontext sehr leistungsfähig: Stellen Sie sich vor, Sie möchten eine angehängte Signatur einer mehrere GB großen Protokolldatei erstellen - jede Nicht-Streaming-Methode wird schnell über wenig Speicher verfügen.
Die Java-Version von Bouncy Castle hat vor einiger Zeit Streaming-Unterstützung im Kontext von CMS hinzugefügt, die Chancen stehen gut, dass es nicht zu lange dauert, bis die C # -Version es aufnimmt.
Tags und Links java c# bouncycastle digital-signature asn.1