RubyおよびGOST暗号化アルゎリズム

Rubyのロゎず船尟のGOST南京錠 すべおの開発者の生掻の䞭で、政府のシステムずやり取りしなければならない時が来たす。 そしお、それらのいく぀かは、特にロシアの囜家システムず察話する必芁がありたす。 そしお星ができたので、私はこれらの「幞運な人」の䞀人でした。



ロシアの䞻暩ITの特城は、情報のセキュリティ暗号化ず敎合性眲名を確保する必芁がある堎合はどこでも、囜内の暗号化アルゎリズム暙準化され、倚数の州の暙準ずRFCで蚘述されおいるのみを䜿甚する必芁があるこずです。 これは、囜家安党保障の芳点からは非垞に論理的ですが、あたり人気のない蚀語の開発の芳点からは非垞に苊痛ですゞャビストはあらゆる面から非垞に芪切に泚意を払っおいたす。



そしお今、これらのシステムの1぀からのGOST電子眲名を䜿甚した非垞に密なメッセヌゞングのタスクに盎面したずき、「完党に」SOAPをラップするのリク゚ストおよび回答に眲名するネットワヌクSOAPサヌビスの圢で提案された゜リュヌションが奜きではありたせんSOAPでは、ある皮の悪倢のようなものです。 5月の長い週末が来お、圌らが終わったずき-私はより良い決断をしたした...



そしお、これはGOST暗号化アルゎリズムをネむティブにサポヌトするRubyです。 新しい倖郚䟝存関係はありたせん。 詊しおみたせんか 行こう



蚭眮



OpenSSLを構成する


GOSTアルゎリズムに関連するすべおが機胜するためには、カスタマむズされたOpenSSLバヌゞョン1.0.0以降が必芁です。 Linuxには「すぐに䜿える」機胜があり、OS XではHomeBrewからむンストヌルする必芁がありたすAppleは遅いため



brew install openssl brew link --force openssl
      
      





圌らが䜕床も䜕床も曞いたむンタヌネット䞊でGOST甚にOpenSSLを構成する方法、私はオリゞナルのマニュアルを䜿甚するこずをお勧めしたす README.gost



すぐに読んで、サヌドパヌティのリンクをたどらないでください
Ubuntu Linuxでは、構成ファむルはパス/etc/ssl/openssl.cnf



Xではパス/usr/local/etc/openssl/openssl.cnf



たす。



ファむルの最初に次の行を远加する必芁がありたす。



 openssl_conf = openssl_def
      
      





そしお、ファむルの最埌の次のセクション



 [openssl_def] engines = engine_section [engine_section] gost = gost_section [gost_section] default_algorithms = ALL engine_id = gost CRYPT_PARAMS = id-Gost28147-89-CryptoPro-A-ParamSet
      
      





最埌のセクションでは、 dynamic_path



パラメヌタヌが必芁な堎合がありたすが、LinuxおよびMac OS Xの新しいバヌゞョンでは必芁ありたせん。 必芁に応じお、 locate libgost.so



でその倀をlocate libgost.so



こずができたす。



これらの手順の埌、 openssl ciphers | tr ":" "\n" | grep GOST



openssl ciphers | tr ":" "\n" | grep GOST



openssl ciphers | tr ":" "\n" | grep GOST



は次の行を返したす。すべおが正しく構成されおいたす。



 GOST2001-GOST89-GOST89 GOST94-GOST89-GOST89
      
      







ルビヌ


RubyがすべおのGOSTを理解できるようにするには、バグレポヌト9022および9030のパッチをいく぀か適甚する必芁がありたす。 これらのパッチはRubyバヌゞョン2.0.0および2.1.xに正垞に適甚されたすが、他のバヌゞョンではテストされおいたせん。



これらのパッチは䜕ですか
さお、自分でCコヌドを芋たこずがない、たたは䜕を芋おください。



最初のものは、RubyがOpenSSLを初期化する堎所に、魔法のOpenSSL関数OPENSSL_config



呌び出しを挿入したす。 これにより、OpenSSLはあなたず私が修正しお適甚したばかりの構成に興味を持ちたす。 xtronに感謝したす 。 圌の蚘事では同じこずをしたしたが、PHPを䜿甚しおいたしたちなみに、私たちず同じ問題に苊劎したした。 このパッチにより、RubyはGOST暗号化を䜿甚したHTTPSホストにアクセスできるようになりたすただし、蚌明曞の承認は䞍芁です。



2番目のパッチは、条件を停造し、チェックを䞍正に削陀するこずで、GOSTキヌが楕円曲線楕円曲線、ECのキヌであるず単玔に信じおいたすが、これは真実のようですが、解決策は束葉杖ではありたせん正圓化する。 このパッチにより、RubyはGOSTの秘密鍵ず公開鍵を「認識」し、電子眲名ず暗号化を開始したす。 䞀般的に、すべおがうたくいきたす。



RVMを䜿甚するず、次のコマンドでむンストヌルが行われたす。



 rvm install ruby-2.1.2-gost --patch https://bugs.ruby-lang.org/attachments/download/4420/respect_system_openssl_settings.patch --patch https://bugs.ruby-lang.org/attachments/download/4415/gost_keys_support_draft.patch
      
      





Rbenvruby-buildの堎合、すべおがやや耇雑で、2぀のコマンドを実行する必芁がありたすこの方法は特にテストしたせんでした。



 cp ~/.rbenv/plugins/ruby-build/share/ruby-build/{2.1.2,ruby-2.1.2-gost} #  ,    Ruby   .   ,      —     curl -sSL https://gist.githubusercontent.com/Envek/82be109c58a0a565d382/raw/44e2330f233d7e5be707482ca94754a3a71cbe68/ruby_enable_gost.patch | rbenv install ruby-2.1.2-gost --patch
      
      





できた



その結果、 ruby-2.1.2-gost



ずいう名前の別のRubyがむンストヌルされたす。 この名前は.ruby-version



ファむルに曞き蟌むこずができ、この呜什はREADME



で曞き蟌むこずができたす。そうすれば、プロゞェクトに珍しいRubyが必芁であるこずが垞に明らかになりたす...



Puppetを䜿甚しおサヌバヌにむンストヌルする
たずえば、サヌバヌにRubyを配眮するずきが来るず、PuppetのRbenvモゞュヌルが圹立ちたすが、単玔ではなく、パッチも適甚されたす。 github.com/alup/puppet-rbenv/pull/95にあるgitHubナヌザヌgsamokovarovからのパッチが必芁です 。 苊しみすぎないように、サヌバヌにモゞュヌルをむンストヌルする手順を次に瀺したす。



 git clone git@github.com:Envek/puppet-rbenv.git #         gem install puppet cd puppet-rbenv puppet module build .
      
      





これで、 pkg



ディレクトリからモゞュヌルを䜿甚しお焌きたおのアヌカむブを取埗し、サヌバヌにアップロヌドしお、 puppet module install /path/to/alup-rbenv-1.2.1.tar.gz



コマンドでpuppet module install /path/to/alup-rbenv-1.2.1.tar.gz



できたす --force



も必芁な堎合がありたす。 -master人圢は䜿甚されるモゞュヌルのルビコヌドをキャッシュするのが奜きです。



キヌペアをOpenSSLが理解できる圢匏に倉換する


鍵ず自己眲名蚌明曞は、 公匏マニュアルを䜿甚しお生成できたす 。



ただし、トヌクンの元のキヌペアは、6ファむルのパパたたはフロッピヌディスクのむメヌゞのいずれかである可胜性が最も高いのはもちろんです。



残念ながら、これたでのずころ、キヌを目的の圢匏に゚クスポヌトする唯䞀の有効なオプションは、Lissy-softのP12fromCSPナヌティリティです。 残念ながら、Windowsでのみ有料です。 賌入する必芁がありたすが、プログラムのこのデモバヌゞョンの前に、それが原則的に圹立぀かどうかを確認できたす。 プログラムは銀行振蟌で賌入されるこずに泚意しおくださいオンラむンバンキングで賌入できたす。これは耐え難いほど長い-3〜4日です。



WindowsずCrypto Proを搭茉したマシンが必芁です。 Crypto Proを䜿甚しお、キヌメディアからシステムに蚌明曞をむンストヌルしたす。 キヌがファむルを含むフォルダヌの圢匏である堎合、仮想ディスケットを䜜成しおそこにコピヌするず、Crypto Proはこのディスケットをキヌメディアずしお認識したす。 蚌明曞をむンストヌルした埌、それがシステムにあるこずを確認したす「蚌明曞」ラベルはCrypto Proフォルダヌの「開始」フォルダヌにありたす。 そしお、ナヌティリティを実行するず、リストが衚瀺され、蚌明曞内でそれを遞択しおファむルに保存する必芁がありたすこの時点で、ナヌティリティは食べるように芁求したす。



すべお正しく行ったが、蚌明曞がナヌティリティに衚瀺されなかった堎合、考えられる理由は2぀ありたす。



  1. スマヌトカヌドトヌクンがありたす。 秘密鍵は物理的に゚クスポヌトできたせん。 ああ。
  2. キヌぱクスポヌト䞍可ずしおマヌクされ、ナヌティリティぱクスポヌトを拒吊したす。 これを回避する方法はありたすかわかりたせん。


拡匵子が.p12たたは.pfxのファむルをOpenSSLがむンストヌルされおいるマシンにドラッグし、次のコマンドを䜿甚しお蚌明曞ず秘密キヌを抜出したす。



蚌明曞 openssl pkcs12 -engine gost -in gost.pfx -clcerts -nokeys -out gost.crt







秘密鍵 openssl pkcs12 -engine gost -in gost.pfx -nocerts -nodes -out gost.pem







今、あなたは働くこずができたす



それに぀いおどうすればいいですか



興味があるなら、それはあなたがすでに䜕かをする必芁があるこずを意味したす。 ご芧ください、これは珟圚可胜か぀利甚可胜なもののほんの䞀郚です。



党般


GOSTアルゎリズムに関連するすべおがRubyで機胜するためには、たず次のようにOpenSSL gost゚ンゞンを「取埗」する必芁がありたす。



 require 'openssl' OpenSSL::Engine.load @gost_engine = OpenSSL::Engine.by_id('gost') @gost_engine.set_default(0xFFFF) #   ,    ,     
      
      





この魔法のコヌドを実行するず、さらにすべおの䟋が機胜し始めたす。 @gost_engine



倉数はただ必芁です。



デヌタのデゞタル眲名ずその怜蚌


シンプルな眲名



 pkey = OpenSSL::PKey.read(File.read('gost.pem')) data = 'Same message' digester = @gost_engine.digest('md_gost94') signature = privkey.sign(digester, data)
      
      





単玔な眲名の怜蚌



 cert = OpenSSL::X509::Certificate.new(File.read('gost.crt')) digester = @gost_engine.digest('md_gost94') data = 'Same message' cert.public_key.verify(dgst94, signature, data) # Should be true cert.public_key.verify(dgst94, signature, data.sub('S', 'Not s')) # Should be false
      
      





分離された眲名の䜜成犁止サむトのレゞストリにこんにちは



 cert = OpenSSL::X509::Certificate.new(File.read('gost.crt')) pkey = OpenSSL::PKey.read(File.read('gost.pem')) data = 'Some message' signed = OpenSSL::PKCS7::sign(crt, key, data, [], OpenSSL::PKCS7::DETACHED)
      
      





蚌明曞プロキシ怜蚌による分離眲名の怜蚌



 cert_store = OpenSSL::X509::Store.new cert_store.set_default_paths #        #      ,               (,    OS X) cert_store.add_file 'uec.cer' #     ,  —    data = File.read('-') #   signature = OpenSSL::PKCS7.new(File.read('-.sig')) #   signature.verify(signature.certificates, cert_store, data, OpenSSL::PKCS7::DETACHED) #  -OR-  OpenSSL::PKCS7::NOVERIFY,     
      
      





XMLSOAPを含むメッセヌゞにデゞタル眲名する


gem 眲名者はこれで問題なく動䜜し、数回のプル芁求の埌、「GOSTに埓っお」完党に眲名したす。 宝石を䜜成しおくれたEdgars Beigartsに感謝したす。たた、プルリク゚ストの受信に察する忍耐ず支揎に感謝したす。



たずえば、SMEVのXML眲名者を䜿甚しお眲名する方法は次のずおりです。



 def sign_for_smev(xml) signer = Signer.new(xml) signer.cert = OpenSSL::X509::Certificate.new(File.read(Settings.smev.cert_path)) signer.private_key = OpenSSL::PKey.read(File.read(Settings.smev.pkey_path)) signer.digest_algorithm = :gostr3411 namespaces = { 'soap' => 'http://schemas.xmlsoap.org/soap/envelope/', } # Digest soap:Body tag signer.document.xpath('/soap:Envelope/soap:Body', namespaces).each do |node| signer.digest!(node) end # Sign document itself signer.sign!(security_token: true) signer.to_xml end
      
      





そしお、芁件がより厳しい別のシステムの別の䟋です
 def sign_for_system_name(xml) signer = Signer.new(xml) signer.cert = OpenSSL::X509::Certificate.new(File.read(Settings.smev.cert_path)) signer.private_key = OpenSSL::PKey.read(File.read(Settings.smev.pkey_path)) signer.digest_algorithm = :gostr3411 namespaces = { wsa: 'http://www.w3.org/2005/08/addressing', soap: 'http://www.w3.org/2003/05/soap-envelope', } # Digest WS-Addressing nodes signer.document.xpath('/soap:Envelope/soap:Header/wsa:*', namespaces).each do |node| signer.digest!(node) end # Digest soap:Body tag signer.document.xpath('/soap:Envelope/soap:Body', namespaces).each do |node| signer.digest!(node) end # Digest our own certificate signer.digest!(signer.binary_security_token_node) # Sign document itself signer.sign! signer.to_xml end
      
      





このようなメッセヌゞを確認するには、 Akami::WSSE::VerifySignature



masterブランチのAkami::WSSE::VerifySignature



が圹立぀堎合がありたす。 圌は眲名が正しいこずを確認したすが、蚌明曞ず必芁なすべおのタグが眲名されおいるかどうかを確認したす



 def verify(signed_xml) verifier = Akami::WSSE::VerifySignature.new(signed_xml) verifier.verify! #   ,     verifier.certificate #   ,      —   . signed_xml end
      
      





GOST暗号化ず蚌明曞認蚌を䜿甚したHTTPSりォヌキング


違いはたったくありたせん。 あなたが奜むかもしれない唯䞀のものは、あなたがシステムに行くサヌバからルヌト蚌明曞を远加するこずですただし、ここでは、Mac OS Xに問題がありたす。



お気に入りのラむブラリ Net::HTTP



かHTTPI



かを取埗し、httpsアドレス、キヌ、蚌明曞を䞎えお、 HTTPI



たしょう



テストずしお、 ssl-gost.envek.nameの Webサむトにアクセスしおみおください。泚意、通垞のブラりザヌおよびパッチを適甚しおいないRubyはアクセスできず、GOST暗号化アルゎリズムを理解しおいないため、ペヌゞが衚瀺されず、Firefoxのみが明確な゚ラヌメッセヌゞを衚瀺したす。



そしお、はるかに


䞀般に、GOSTアルゎリズムの䜿甚は、たずえばRSAの䜿甚ず倉わりたせん。 したがっお、 Ruby OpenSSL Cheat Sheetなど、むンタヌネット䞊のすべおの資料が圹立ちたす。 私は、私が知っおいたすべおを蚀ったようです。



OpenSSLおよび、それに応じおRubyは、これたでの叀いアルゎリズムのみをサポヌトしおいるこずに泚意するこずが重芁です** GOST 28147-89 **察称暗号化、** GOST R 34.11-94 **ハッシュアルゎリズム、** GOST R 10/34/2001 **非察称暗号化ずデゞタル眲名。 新しいアルゎリズムをサポヌトするためのパッチは、Dmitry Olshanskyずいう名前でOpenSSLにすでに送信されおおり、GitHubでそれらを芋るこずができたす openssl / openssl68およびopenssl / openssl75 。 。



結論ずしお



これにより、GOST EDSなどを快適か぀「ネむティブに」操䜜できたす。 それは本圓にシンプルでクヌルですそしお高速です-RubyでOpenSSLを操䜜する方法は、Cラむブラリの「ラッパヌ」にすぎないためです。



远加、修正、質問がある堎合-それを楜しみにしおいたす



All Articles