CryptoGost3410¶ ↑
Ruby library implementing GOST 34.10-2012 ECC signature and VKO algorithms. Forked from github.com/wilddima/crypto_gost.
Installation¶ ↑
Add this line to your application’s Gemfile:
gem 'crypto_gost3410'
And then execute:
$ bundle
Or install it yourself as:
$ gem install crypto_gost3410
Or install it locally from source crypto_gost3410 project directory
$ bundle exec rake install
Usage¶ ↑
# All input and output data for CryptoGost3410 are big numbers only, not byte arrays nor strings. # As so, input CryptoGost3411 message digest should be converted to big number too. # We removed SecureRandom random number generations out of module to use any external generator. # In version 0.2.1 tests we use crypto_gost3411 gem instead of stribog gem for digest generation. require 'securerandom' require 'crypto_gost3411' require 'crypto_gost3410' group = CryptoGost3410::Group::Gost256tc26a puts group.opts[:name] puts group.opts[:id] puts group.opts[:oid] coord_size = group.opts[:coord_size] # in bytes generator = CryptoGost3410::Generator.new(group) # for sign and for vko verifier = CryptoGost3410::Verifier.new(group) # for verify # private_key is random number 0<n<group.order # you can use fixed number for debugging private_key = SecureRandom.random_number(1..group.order-1) puts "private_key: #{private_key.to_s(16)}" public_key = group.generate_public_key private_key puts "public_key.x: #{public_key.x.to_s(16)}" puts "public_key.y: #{public_key.y.to_s(16)}" # Signature: message = 'ruby' digest = CryptoGost3411::Gost3411.new(coord_size).update(message).final CryptoGost3410::Converter.printBytes(digest, coord_size * 2) digest_num = CryptoGost3410::Converter.bytesToBignum(digest.reverse) puts "digest_num: #{digest_num.to_s(16)}" # rnd_val is random number 0<n<group.order so as private_key # you can use fixed number for debugging rand_val = SecureRandom.random_number(1..group.order-1) puts "rand_val: #{rand_val.to_s(16)}" signature = generator.sign(digest_num, private_key, rand_val) puts "signature.x: #{signature.x.to_s(16)}" # x stands for r puts "signature.y: #{signature.y.to_s(16)}" # y stands for s signature_ok = verifier.verify(digest_num, public_key, signature) puts "signature_ok: #{signature_ok}" # VKO: receiver_private_key = SecureRandom.random_number(1..group.order-1) puts "receiver_private_key: #{receiver_private_key.to_s(16)}" receiver_public_key = group.generate_public_key receiver_private_key puts "receiver_public_key.x: #{receiver_public_key.x.to_s(16)}" puts "receiver_public_key.y: #{receiver_public_key.y.to_s(16)}" # ukm is random number 2**(coord_size*2)<=ukm<2**(coord_size*8) ukm = SecureRandom.random_number(2**(coord_size*2)..2**(coord_size*8)-1) puts "ukm: #{ukm.to_s(16)}" sender_vko = generator.vko(ukm, private_key, receiver_public_key) puts "sender_vko.x: #{sender_vko.x.to_s(16)}" puts "sender_vko.y: #{sender_vko.y.to_s(16)}" receiver_vko = generator.vko(ukm, receiver_private_key, public_key) puts "receiver_vko.x: #{receiver_vko.x.to_s(16)}" puts "receiver_vko.y: #{receiver_vko.y.to_s(16)}" puts "vko_ok: #{(sender_vko.x == receiver_vko.x) && (sender_vko.y == receiver_vko.y)}"
Converting GOST digest, public_key and signature strings to big numbers and vise versa¶ ↑
require 'crypto_gost3411' require 'crypto_gost3410' group = CryptoGost3410::Group::Gost256tc26test coord_size = group.opts[:coord_size] # in bytes # get tbs, signer public_key and signature byte strings from x509 certificate # ... # generate digest digest32 = CryptoGost3411::Gost3411.new(coord_size).update(tbs).final # little-endian digest32 -> reverse -> big-endian -> BigNum digest32_num = CryptoGost3410::Converter.bytesToBignum(digest32.reverse) # public key x||y little-endian -> reverse -> big-endian -> Point(x_num, y_num) public_key_x_num = CryptoGost3410::Converter.bytesToBignum(public_key[0...coord_size].reverse) public_key_y_num = CryptoGost3410::Converter.bytesToBignum(public_key[coord_size..-1].reverse) public_key_point = CryptoGost3410::Point.new(group, [public_key_x_num, public_key_y_num]) # signature s||r big-endian -> Point(r_num, s_num) signature_s_num = CryptoGost3410::Converter.bytesToBignum(signature[0...coord_size]) signature_r_num = CryptoGost3410::Converter.bytesToBignum(signature[coord_size..-1]) signature_point = CryptoGost3410::Point.new(group, [sig_r_num, sig_s_num]) signature_point_ok = CryptoGost3410::Verifier.new(group).verify(digest32_num, public_key_point, signature_point) puts "signature_point_ok: #{signature_point_ok}" # Converting signature point to byte string ( s||r, big-endian): signature_bytes_s = CryptoGost3410::Converter.bignumToBytes(signature_point.x, coord_size) signature_bytes_r = CryptoGost3410::Converter.bignumToBytes(signature_point.y, coord_size) signature_bytes = signature_bytes_s + signature_bytes_r # Print signature bytes in hex (64 symbols in line) CryptoGost3410::Converter.printBytes(signature_bytes, coord_size * 2)
List of TC 26 GOST 34.10-2012 elliptic curves:¶ ↑
Gost256tc26test - id-tc26-gost-3410-2012-256-paramSetTest (former id-GostR3410-2001-TestParamSet). Use for testing only! Gost256tc26a - id-tc26-gost-3410-2012-256-paramSetA (Edwards twisted curve) Gost256tc26b - id-tc26-gost-3410-2012-256-paramSetB (former id-GostR3410-2001-CryptoPro-A-ParamSet) Gost256tc26c - id-tc26-gost-3410-2012-256-paramSetC (former id-GostR3410-2001-CryptoPro-B-ParamSet) Gost256tc26d - id-tc26-gost-3410-2012-256-paramSetD (former id-GostR3410-2001-CryptoPro-C-ParamSet) Gost512test - id-tc26-gost-3410-2012-512-paramSetTest. Use for testing only! Gost512tc26a - id-tc26-gost-3410-2012-512-paramSetA Gost512tc26b - id-tc26-gost-3410-2012-512-paramSetB Gost512tc26c - id-tc26-gost-3410-2012-512-paramSetC (Edwards twisted curve) You can find group by name, by id, by oid and by der_oid: name = 'Gost256tc26test' group = CryptoGost3410::Group.findByName(name) id = 'id-tc26-gost-3410-2012-256-paramSetTest' group = CryptoGost3410::Group.findById(id) oid = '1.2.643.7.1.2.1.1.0' group = CryptoGost3410::Group.findByOid(oid) der_oid = "\x06\x09\x2a\x85\x03\x07\x01\x02\x01\x01\x00" group = CryptoGost3410::Group.findByDerOid(der_oid)
Testing¶ ↑
Run spec test from crypto_gost3410 source project directory:
$ bundle exec rake spec
Thanks¶ ↑
Thanks to WildDima for root crypto_gost project on GitHub at github.com/wilddima/crypto_gost.
Contributing¶ ↑
Bug reports and pull requests are welcome on GitHub at github.com/vblazhnovgit/crypto_gost3410. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](contributor-covenant.org) code of conduct.
License¶ ↑
The gem is available as open source under the terms of the [MIT License](opensource.org/licenses/MIT).