SVX日記
2023-09-01(Fri) Maveでデジタル署名付きメールを検証する
Maveでデジタル署名付きメールを送信できるようになったら、当然、デジタル署名付きメールを受信できるようにもなるべきで、つまりそれは、メールの署名を検証する機能の追加である。
+ #--------------------------------------------- MaveMail ----
+ #
+ # メールの署名を検証する
+ #
+ def verify_sign
+ sender = (from =~ /(.*)<(.+)>/ ? $2 : from).strip
+ if(@header['Content-type'] =~ /^multipart\/signed/)
+ begin
+ pkcs7 = OpenSSL::PKCS7.read_smime(File.open(path).read)
+ addrs = []; pkcs7.certificates.each {|cert|
+ cert.subject.to_a.each {|name|
+ name[0] == 'emailAddress' and addrs << name[1]
+ }
+ }
+ if(sender != addrs[0])
+ yield([_('Digital Signature is NOT Valid. reason=[%s]'), 'Sender does not match Signer.'])
+ folder.invalid_sign(sq)
+ elsif(pkcs7.verify(nil, @configs[:CERTS_STORE]))
+ yield([_('Message is Signed.')])
+ folder.valid_sign(sq)
+ else
+ yield([_('Digital Signature is NOT Valid. reason=[%s]'), pkcs7.error_string])
+ folder.invalid_sign(sq)
+ end
+ rescue
+ yield([_('Digital Signature Verify Error. reason=[%s]'), $!.to_s])
+ folder.invalid_sign(sq)
+ end
+ else
+ yield([_('Mail has no signature.')])
+ end
+ end
署名を検証はpop時に行うようにし、結果は「@(添付あり)」の表示位置に押し込んだ。「C」なら署名が有効「?」なら無効だ。署名自体が添付ファイルではあるものの、添付ファイル付きの署名付きメールとの識別ができなくなるが、それはまぁよしとする。
pkcs12 = @account.pkcs12
- pkcs7 = OpenSSL::PKCS7.sign(pkcs12.certificate, pkcs12.key, data, [], OpenSSL::PKCS7::DETACHED)
+ pkcs7 = OpenSSL::PKCS7.sign(pkcs12.certificate, pkcs12.key, data, pkcs12.ca_certs, OpenSSL::PKCS7::DETACHED)
smime = OpenSSL::PKCS7.write_smime(pkcs7) # 署名付きメール(crlf, lf が混じっている)
解像度がないのでややモザイク状にはなるものの、端末画面に画像を表示する「catimg」というプログラムは既に存在していて、だいぶ前に自ら使いやすいラッパーを作って便利に使っていた。つうか、そのエントリで既にMaveに組み込むアイデアについて記述してあるじゃねぇか。
そこでcatimgの出力を流用しようとしたがうまくいかない。つうか、そんなことやるよりcatimgのコード読んでスクラッチからRubyで書くべきじゃないか?と、思い直してコードを読む。ほほーん。そういう原理だったのか。
端末には「文字色」と「背景色」を24bitカラーで指定できるエスケープシーケンスがある。それを使えば「文字単位」でドット表示ができる。しかし、それだと縦長のドットになってしまう。そこで「▀」という「上半分塗りつぶし」文字を使えば「文字色」と「背景色」とで上下を塗り分けることができ、ほぼ正方形のドット表示が可能になる。単純な原理だが、発想がすごいな。実にmz-700っぽく、不可能はないっぽい。
require 'rmagick'
png_image = Magick::Image.read('r9.png')
w = png_image[0].columns
h = png_image[0].rows
(h >> 1).times {|y|
w.times {|x|
cs = []
c = png_image[0].pixel_color(x, y * 2)
cs << (c.red >> 8); cs << (c.green >> 8); cs << (c.blue >> 8)
c = png_image[0].pixel_color(x, y * 2 + 1)
cs << (c.red >> 8); cs << (c.green >> 8); cs << (c.blue >> 8)
print("\e[38;2;%d;%d;%dm\e[48;2;%d;%d;%dm\u2580\e[m" % cs)
}
puts
}