4D Write Pro – 文書に署名して保護

Deeplからの自動翻訳

この記事の目的は、簡単に実装できる方法で、文書を透過的に署名・検証する方法を紹介することです。
このアプローチの明らかな利点は、ドキュメントを再び開いたときに、その間に変更されていないという知識で安心できることです。

これは、4Dコードを含むスマートテンプレートとして4D Write Proドキュメントをディスク上の外部ファイルとして保存する場合に特に重要です。このコードを実行する前に、ファイルが外部から変更されていないことを確認したいものです。

あるいは、外部ドキュメントの場合、それが正しい送信者から来たものであり、そのデジタル・ジャーニーの間に変更されていないことを確認します。
これから説明する原則は、4D Write Proのドキュメントに適用されますが、少し修正を加えるだけで、他のタイプのドキュメントにも適用されます。

サンプルデータベース

暗号化か署名か?

ここでは、ドキュメントの認証、つまり、オリジナルの所有者(法的/公式/その他)によって登録された瞬間から、受信者によって読まれる(または所有者によって再読される!)瞬間の間に、ドキュメントが変更されていないことを確認する方法に集中します。ここでは暗号化について話しているのではない!(暗号に興味のある方は、このブログを参照してください。)

署名の作成

署名を作成するプロセスはいたって簡単です。元の文書から、「秘密」鍵を使って文書全体(BLOBとして)に基づいて署名を作成します。この署名は(そしてこの署名だけが)文書自体に、通常は文書の最後に保存される。

署名を読み直す

文書を開く前に、正式な署名が読み直される。文書全体から新しいBLOBが作成され(終了鍵はないので、理論的にはオリジナルと同じ)、今度は署名の作成に使われた秘密鍵と密接に結びついた公開鍵を使って検証される。この検証の結果によって、次に何が起こるかが決まる!

この段階では、3つの可能性がある。

文書が署名されていると仮定したが、必ずしもそうではない。文書に署名がない場合、必ずしも破損しているわけではありませんが、注意が必要です。
文書を開くかどうかは、開発者、ユーザー、状況、環境……によって異なります。要するに、どうするかは自分で決めなければならない!

つ目の可能性は、署名と内容が一致していることです。それなら朗報だ。あなたは、その文書があなたが作成したもの、あるいはあなたに託されたもの、あなたに送られたもの、などであること、そして何よりも、その文書が作成以来変更されていないことを確信することができます。つまり、送信者を信頼していれば、安心して文書を開くことができるのです。その後、今後の用途に応じて、自由に修正、保存、再署名を行うかどうか決めることができます。もしそれを修正し、送信者に送り返す必要がある場合は、自分で署名しておくと、将来の受信者が同じ操作を行えるようになる。

最後に、3つ目の可能性は、転送中に文書が変更された(あるいは破損した)可能性である。わずかなカンマの追加や削除、わずかな数式の変更などで、署名が一致しなくなります!
すぐにわかるので、適切な処置をとることができます。

さっそく始めましょう!

この例では、すでに4D Write Proフォーマットで保存されている1つまたは複数の既存ファイル、つまり.4wpの拡張子に署名します。ファイルを管理するので、4D.Fileと4D.FileHandleクラスを使います。また、暗号化キー、署名キー、検証キーを管理するので、4D.CryptoKeyも使います(これらのクラスについてまだよく知らない場合は、対応するBLOGを参照してください…)。

SAFEデフォルトキーの作成

まず最初に、秘密鍵と公開鍵のペアを作成し、データベースにエンティティとして保存します(このペアの鍵は後ほど「デフォルト」鍵として使用します)。

$cryptoKey:=ds.CryptoKey.new()
$keyOptions:={type: "RSA"; size: 2048}
$key:=4D.CryptoKey.new($keyOptions)

$cryptoKey.privateKey:=$key.getPrivateKey()
$cryptoKey.publicKey:=$key.getPublicKey()

$cryptoKey.save()

SAFE 署名文書

次に、秘密鍵を使ってファイル(4D.File)の末尾に署名を追加する必要があります。
まとめると、以下のようになります:

// create a new key based on private key
$keyOptions:={type: "PEM"; pem: $privateKey}
$key:=4D.CryptoKey.new($keyOptions)

//…
// create the signature with the .sign() function
$signOptions:={hash: "SHA512"; encodingEncrypted: "Base64URL"}
$signature:=$key.sign($documentAsBlob; $signOptions)

// append signature (as a BLOB) at the end of the document
TEXT TO BLOB($signature; $blobSignature; UTF8 text without length)
$fileHandle.offset:=$documentSize
$fileHandle.writeBlob($blobSignature)

SAFE 署名の確認

最後に、ドキュメントを開く前に、その署名をチェックする必要があります。これは以下のメソッドで行います。ファイル(4D.File)と、オプションで公開鍵を渡します。

// create a new key based on public key
$signOptions:={hash: "SHA512"; encodingEncrypted: "Base64URL"}
$type:={Type; "PEM"; pem; $publicKey}
$key:=4D.CryptoKey.new($type)

// read the real signature 	
//…
$fileHandle.offset:=$documentSize-$length
$blobSignature:=$fileHandle.readBlob($length)
$textSignature:=BLOB to text($blobSignature; UTF8 text without length)

// check the signature using the .verify() function
$check:=$key.verify($documentAsBlob; $signature; $signOptions)
If ($check.success)
	$result:=1
Else 
	$result:=-1
End if 

これは.4wpでは機能しますが、他の文書ではどうでしょうか?

4D Write Proが.4wpドキュメントを読み込むと、ドキュメントの終わりが自動的に検出されるので、どこで停止すればよいかがわかります。ファイルの最後に追加された署名は、それを混乱させません。言い換えれば、文書に署名があろうとなかろうと、署名が正しかろうと正しくなかろうと、.4wpは問題なく読み込まれるので、事前に署名をチェックする必要があります。

他のタイプの文書では、最後に署名を追加することで読み込みが中断される可能性があります(可能性さえあります)ので、署名を削除する必要があるかもしれません-もちろん、検証した後で-。

SAFE署名解除文書

このため、このメソッドは逆の操作を行うために作成されました。
文書から署名を削除して元の状態に戻し、文書に署名がない場合は単に何もしません。

$fileHandle:=$file.open("write")  
//…  calculate signature length then…
$fileHandle.setSize($documentSize-$length)

結論

この単純な例では、文書に署名し、それを開く前に署名を検証する方法を示しました。2つのサイト間で文書を交換する場合、公開鍵と秘密鍵のペアが2つ必要になるが、原理は変わらない。文書作成者は秘密鍵で署名し、読者は作成者から提供された公開鍵でそれを検証する。
公開鍵と秘密鍵は、署名と認証の両方を可能にする貴重な資産であるため、データ・ファイル自体に保存することが望ましい!

Roland Lannuzel
- プロダクトオーナー&4Dエキスパート -電子工学を学んだ後、産業用ITの分野で開発者兼コンサルタントとして、さまざまなデータベースやテクノロジーを使って顧客のためのソリューションを構築。80年代後半に4Dに惚れ込み、会計、請求書作成、メールシステムなどのビジネスアプリケーションの作成に4Dを使用してきました。現在も、新機能やデータベース開発ツールの定義など、4Dの未来を積極的に切り開いています。