0

特定の方法で署名/暗号化された EDI メッセージを政府機関に送信する必要があります。

https://docs.google.com/document/d/1xOxsZG7nCXdd3ucFKJObheW4G6kFwflGFkzURS_haTY/edit?usp=sharingによると

このコードを試していますが、暗号化された S/MIME が政府のゲートウェイに従って正しくフォーマットされていません。

彼らからのメール返信:

取得しているエラー コードは、復号化の失敗です。
まず、ゲートキーパー証明書を使用して EDI メッセージに署名しておく必要があります。これにより、S/MIME blob が生成されます。これを「署名付き」 S/MIME と呼びます。
次に、署名済みの BLOB を取得し、貨物の Web サイトからダウンロードした税関ゲートウェイ証明書を使用して暗号化します。
これにより、「暗号化された」S/MIME と呼ばれる別の S/MIME が生成されます。

正しい暗号化証明書を使用して署名および暗号化しています。

これまでのところ、サードパーティのライブラリである ActiveUp と Chilkat も試してみましたが、役に立ちませんでした。

Customs Spec を解釈し、私が間違っていた可能性のある場所を調整する際の助けをいただければ幸いです。私はこの問題に 1 週​​間以上取り組んできました。

    public static void SendEmail(string ediMsg, string clientCertificatePath,
        string clientCertificatePassword, string sender, string receiver, string subject, SmtpClient smtp,
        string customsCertificatePath)
    {
        //Load the certificate
        X509Certificate2 EncryptCert = new X509Certificate2(customsCertificatePath);

        X509Certificate2 SignCert =
           new X509Certificate2(clientCertificatePath, clientCertificatePassword);

        //Build the body into a string
        StringBuilder Message = new StringBuilder();

        ediMsg = "UNB+IATB:1+6XPPC+LHPPC+940101:0950+1' ...";

        /*The EDI document is first formatted as a MIME message [MIME], 
         * as the EDI Document may contain special characters, non-printable ASCII and binary data. */

        byte[] arrayToEncode = System.Text.Encoding.UTF8.GetBytes(ediMsg);
        ediMsg = Convert.ToBase64String(arrayToEncode);

        /*Within the MIME message, the Content-Transfer-Encoding header must be either “quoted-printable” 
         * or “base64”, and the Content-Type header should be set to “Application/EDIFACT”. */
        Message.AppendLine("Content-Type: Application/EDIFACT");
        Message.AppendLine("Content-Transfer-Encoding: base64");

        //The file name of the attachment for inbound e-mails (to Customs) must be the same as the Subject Line
        //(section 3.3) with the .edi suffix.
        Message.AppendLine("Content-Disposition: attachment; filename=\"" + subject + ".edi\"");

        /*I have tried this with 
         * (a) the raw ediMsg, 
         * (b) the base64 version of (a)
         * (c) quoted-printable version of (a)
         * (d) base64 version of (c)
         */ 
        Message.AppendLine(ediMsg);

        //Text must not be included in the body of the e-mail. EDI documents must be sent as an attachment.

        //Convert the body to bytes
        byte[] BodyBytes = Encoding.UTF8.GetBytes(Message.ToString());

        //sign
        var signedBytes = SignMsg(BodyBytes, SignCert);

        //Build the e-mail body bytes into a secure envelope
        EnvelopedCms Envelope = new EnvelopedCms(new ContentInfo(signedBytes));
        CmsRecipient Recipient = new CmsRecipient(
            SubjectIdentifierType.IssuerAndSerialNumber, EncryptCert);
        Envelope.Encrypt(Recipient);
        byte[] EncryptedBytes = Envelope.Encode();

        //Create the mail message
        MailMessage Msg = new MailMessage();
        Msg.To.Add(new MailAddress(receiver));
        Msg.From = new MailAddress(sender);
        Msg.Subject = subject;

        //Attach the encrypted body to the email as and ALTERNATE VIEW
        MemoryStream ms = new MemoryStream(EncryptedBytes);
        AlternateView av =
            new AlternateView(ms,
            "application/pkcs7-mime; smime-type=signed-data;name=smime.p7m");
        Msg.AlternateViews.Add(av);

        //SmtpClient smtp = new SmtpClient(MailServer, 25);
        //send the email                                       
        smtp.Send(Msg);
    }
4

1 に答える 1

1

私が指摘しようとしている問題が問題であるかどうかはわかりませんが、調べる価値があるかもしれません...

まず、Convert.ToBase64String(arrayToEncode);MIME で必要に応じて行を折り返しません。使用する必要があるのは、このバリアントBase64FormattingOptions.InsertLineBreaks.

次に、SignMsg() が何をするのかわかりませんが、適切な Content-Type、Content-Transfer-Encoding、および (おそらく) Content-Disposition ヘッダーも先頭に追加するようにしてください。base64 でデータをエンコードしたら、 Content-Type はapplication/pkcs7-mime; smime-type=signed-data; name=smime.p7s、Content-Transfer-Encoding である必要があります。base64

第三に、暗号化された外側の部分に与えた Content-Type ヘッダーが間違っています。である必要がありますapplication/pkcs7-mime; smime-type=enveloped-data; name=smime.p7m

4 番目に、暗号化されたデータが base64 でエンコードされ、AlternativeView が の Content-Transfer-Encoding を取得することを確認しますbase64

代替ビューとして追加することが必ずしも機能するかどうかはわかりません。生成された MIME を確認する必要があります。

ペイウェアである IP*Works の代わりに使用を検討できるものは、S/MIME メッセージの生成を既にサポートしているMimeKitと呼ばれる私のオープン ソース ライブラリです。あなたが使用しているように見えるSMTPをサポートするMailKitというライブラリもあります。

どちらのライブラリも NuGet を介して簡単に利用できます: MimeKitMailKit

あなたがすることは次のようなものです:

// Note: if the email addresses do not match the certificates, you can
// use a SecureMailboxAddress instead, which allows you to specify the
// Fingerprint (aka Thumbprint) of the certificate to use for signing
// or encrypting.
var recipient = new MailboxAddress ("Receiver Name", "receiver@example.com");
var sender = new MailboxAddress ("Sender Name", "sender@example.com");

var message = new MimeMessage ();
message.To.Add (recipient);
message.From.Add (sender);
message.Subject = subject;

// create the application/edifact MIME part
var edifact = new MimePart ("application", "edifact");

// set the filename of the MIME part (adds a Content-Disposition header
// if not already present)
edifact.FileName = subject + ".edi";

// create the content stream of the MIME part
var content = new MemoryStream (Encoding.UTF8.GetBytes (ediMsg), false);

// set the content of the MIME part (we use ContentEncoding.Default because
// it is not encoded... yet)
edifact.ContentObject = new ContentObject (content, ContentEncoding.Default);

// encode the content using base64 *and* set the Content-Transfer-Encoding header
edifact.ContentTransferEncoding = ContentEncoding.Base64;

using (var ctx = new TemporarySecureMimeContext ()) {
    ctx.Import (clientCertificatePath, clientCertificatePassword);
    ctx.Import (customsCertificatePath);

    // sign and then encrypt the edifact part and then set the result as the
    // message body.
    message.Body = ApplicationPkcs7Mime.SignAndEncrypt (ctx, sender,
        DigestAlgorithm.Sha1, new [] { recipient }, edifact);
}

// MailKit's SMTP API is very similar to System.Net.Mail's SmtpClient API,
// so that shouldn't pose a problem.
于 2014-04-16T22:33:17.003 に答える