spec/bitcoin/key_spec.rb in bitcoin-ruby-0.0.1 vs spec/bitcoin/key_spec.rb in bitcoin-ruby-0.0.2
- old
+ new
@@ -1,5 +1,7 @@
+# encoding: ascii-8bit
+
require_relative 'spec_helper'
describe "Bitcoin::Key" do
before do
@@ -61,14 +63,46 @@
@key.sign("foobar").size.should >= 69
end
it "should verify signature" do
sig = @key.sign("foobar")
- key2 = Bitcoin::Key.new(nil, @key.pub)
- @key.verify("foobar", sig).should == true
+ key = Bitcoin::Key.new(nil, @key.pub)
+ key.verify("foobar", sig).should == true
end
+ it "recovers public keys from compact signatures" do
+ tests = [
+ # normal
+ { address: "16vqGo3KRKE9kTsTZxKoJKLzwZGTodK3ce",
+ signature: "HPDs1TesA48a9up4QORIuub67VHBM37X66skAYz0Esg23gdfMuCTYDFORc6XGpKZ2/flJ2h/DUF569FJxGoVZ50=",
+ message: "test message",
+ expected: true },
+
+ # different message
+ { address: "16vqGo3KRKE9kTsTZxKoJKLzwZGTodK3ce",
+ signature: "HPDs1TesA48a9up4QORIuub67VHBM37X66skAYz0Esg23gdfMuCTYDFORc6XGpKZ2/flJ2h/DUF569FJxGoVZ50=",
+ message: "not what I signed",
+ expected: false },
+
+ # different address
+ { address: "1JbYZRKyysprVjSSBobs8LX6QVjzsscQNU",
+ signature: "HPDs1TesA48a9up4QORIuub67VHBM37X66skAYz0Esg23gdfMuCTYDFORc6XGpKZ2/flJ2h/DUF569FJxGoVZ50=",
+ message: "test message",
+ expected: false },
+
+ # compressed
+ { address: "18uitB5ARAhyxmkN2Sa9TbEuoGN1he83BX",
+ signature: "IMAtT1SjRyP6bz6vm5tKDTTTNYS6D8w2RQQyKD3VGPq2i2txGd2ar18L8/nvF1+kAMo5tNc4x0xAOGP0HRjKLjc=",
+ message: "testtest",
+ expected: true },
+ ]
+ tests.each do |test|
+ key = Bitcoin::Key.recover_compact_signature_to_key(test[:message], test[:signature])
+ test[:expected].should == (key.addr == test[:address])
+ end
+ end
+
it "should export private key in base58 format" do
Bitcoin.network = :bitcoin
str = Bitcoin::Key.new("e9873d79c6d87dc0fb6a5778633389f4453213303da61f20bd67fc233aa33262").to_base58
str.should == "5Kb8kLf9zgWQnogidDA76MzPL6TsZZY36hWXMssSzNydYXYB9KF"
Bitcoin.network = :testnet
@@ -87,18 +121,75 @@
key.priv.should == "d21fa2c7ad710ffcd9bcc22a9f96357bda1a2521ca7181dd610140ecea2cecd8"
key.addr.should == "n3eH91H14mSnGx4Va2ngtLFCeLPRyYymRg"
Bitcoin.network = :bitcoin
end
+ it "should export private key in compressed base58 format" do
+ Bitcoin.network = :bitcoin
+ Bitcoin::Key.new("98e4483a197fb686fe9afb51389f329aabc67964b1d0e0a5340c962a0d63c44a",
+ nil, true).to_base58.should == "L2LusdhGSagfUVvNWrUuPDygn5mdAhxUDEANfABvBj36Twn1mKgQ"
+ Bitcoin.network = :testnet3
+ Bitcoin::Key.new("e3ff5d7e592669d0c1714f1496b260815edd0c3a00186e896dc7f36ede914dd2",
+ nil, true).to_base58.should == "cVDu6aXUWHTM2vpztZW14BMnKkCcd5th6177VnCsa8XozoMyp73C"
+ Bitcoin.network = :bitcoin end
+
+ it "should import private key in compressed base58 format" do
+ Bitcoin.network = :bitcoin
+ key = Bitcoin::Key.from_base58("L2LusdhGSagfUVvNWrUuPDygn5mdAhxUDEANfABvBj36Twn1mKgQ")
+ key.priv.should == "98e4483a197fb686fe9afb51389f329aabc67964b1d0e0a5340c962a0d63c44a"
+ key.pub.should == "02e054ee811165ac294c992ff410067db6491228725fe09db2a415493c897973a8"
+ key.addr.should == "1C7Ni4zuV3zfLs8T1S7s29wNAtRoDHHnpw"
+ Bitcoin.network = :testnet3
+ key = Bitcoin::Key.from_base58("cVDu6aXUWHTM2vpztZW14BMnKkCcd5th6177VnCsa8XozoMyp73C")
+ key.priv.should == "e3ff5d7e592669d0c1714f1496b260815edd0c3a00186e896dc7f36ede914dd2"
+ key.pub.should == "0390bb61c062266a1e8460ec902379749ae30f569013d82bd448a61591f20b8ee2"
+ key.addr.should == "mjh9RgZh14FfJQ2pFpRSqEQ5BH1nHo5To7"
+ Bitcoin.network = :bitcoin
+ end
+
+ it "should hanlde compressed and uncompressed pubkeys" do
+ compressed = "0351efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da78"
+ uncompressed = "0451efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da787f71a2e8ac5aacedab47904d4bd42f636429e9ce069ebcb99f675aad31306a53"
+ Bitcoin::Key.new(nil, compressed).compressed.should == true
+ Bitcoin::Key.new(nil, compressed).pub.should == compressed
+ Bitcoin::Key.new(nil, compressed).addr.should == "1NdB761LmTmrJixxp93nz7pEiCx5cKPW44"
+ Bitcoin::Key.new(nil, uncompressed).compressed.should == false
+ Bitcoin::Key.new(nil, uncompressed).pub.should == uncompressed
+ Bitcoin::Key.new(nil, uncompressed).addr.should == "19FBCg9295EBQ4P6bSLTGyz2BdbbPcqQD"
+
+ key = Bitcoin::Key.new(nil, compressed)
+ key.pub_compressed.should == compressed
+ key.pub_uncompressed.should == uncompressed
+
+ sig = @key.sign(msg="foobar")
+ Bitcoin::Key.new(nil, @key.pub_compressed ).verify(msg, sig).should == true
+ Bitcoin::Key.new(nil, @key.pub_uncompressed).verify(msg, sig).should == true
+
+ compressed = "02f01984446a994a9e422c9ba9c6f33f1f40c01d9d872064a49679d702fae33064"
+ Bitcoin::Key.new(nil, compressed).pub.should == compressed
+ Bitcoin::Key.new(nil, compressed).addr.should == "18TWywxjESkg4pzJqBYNDo39S2QMPaWWJ5"
+
+ k = Bitcoin::Key.new(nil, nil)
+ k.instance_eval{ set_pub("02f01984446a994a9e422c9ba9c6f33f1f40c01d9d872064a49679d702fae33064") }
+ k.compressed.should == true
+
+ k = Bitcoin::Key.new(nil, nil)
+ k.instance_eval{ set_pub("0351efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da78") }
+ k.compressed.should == true
+
+ k = Bitcoin::Key.new(nil, nil)
+ k.instance_eval{ set_pub("0451efb6e91a31221652105d032a2508275f374cea63939ad72f1b1e02f477da787f71a2e8ac5aacedab47904d4bd42f636429e9ce069ebcb99f675aad31306a53") }
+ k.compressed.should == false
+ end
+
end
begin
describe "Bitcoin::OpenSSL_EC" do
Bitcoin::OpenSSL_EC
it 'resolves public from private key' do
- Bitcoin.network = :testnet
privkey = ["56e28a425a7b588973b5db962a09b1aca7bdc4a7268cdd671d03c52a997255dc"].pack("H*")
pubkey = ["04324c6ebdcf079db6c9209a6b715b955622561262cde13a8a1df8ae0ef030eaa1552e31f8be90c385e27883a9d82780283d19507d7fa2e1e71a1d11bc3a52caf3"].pack("H*")
Bitcoin::OpenSSL_EC.regenerate_key(privkey).should == [privkey, pubkey].map{|i| i.unpack("H*")[0] }
@@ -114,9 +205,43 @@
250.times.map{
keypair = Bitcoin.generate_key;
Bitcoin::OpenSSL_EC.regenerate_key(keypair.first) == keypair
}.all?.should == true
+ end
+
+ it 'recover public key from compact signature' do
+ args = [
+ "\x12&\x17\x9D\xDFc\x83\xFB\xCFQ\x02\xC9I%8\xB7 ls\x9A\xE7\x9E\xB0d@\x8C*\xBDg\xD3\x9B\xED",
+ "\x1C\xF0\xEC\xD57\xAC\x03\x8F\x1A\xF6\xEAx@\xE4H\xBA\xE6\xFA\xEDQ\xC13~\xD7\xEB\xAB$\x01\x8C\xF4\x12\xC86\xDE\a_2\xE0\x93`1NE\xCE\x97\x1A\x92\x99\xDB\xF7\xE5'h\x7F\rAy\xEB\xD1I\xC4j\x15g\x9D",
+ 1, false
+ ]
+ expected = "047840b97f46d4c32c62119f9e069172272592ec7741a3aec81e339b87387350740dce89837c8332910f349818060b66070b94e8bb11442d49d3f6c0d7f31ba6a6"
+
+ # 10_000.times{|n| # enable for memory leak testing
+ # puts 'RAM USAGE: ' + `pmap #{Process.pid} | tail -1`[10,40].strip if (n % 1_000) == 0
+ Bitcoin::OpenSSL_EC.recover_public_key_from_signature(*args).should == expected
+ # }
+ end
+
+ it 'sign and verify text messages' do
+ [
+ ["5HxWvvfubhXpYYpS3tJkw6fq9jE9j18THftkZjHHfmFiWtmAbrj", false],
+ ["5KC4ejrDjv152FGwP386VD1i2NYc5KkfSMyv1nGy1VGDxGHqVY3", false],
+ ["Kwr371tjA9u2rFSMZjTNun2PXXP3WPZu2afRHTcta6KxEUdm1vEw", true],
+ ["L3Hq7a8FEQwJkW1M2GNKDW28546Vp5miewcCzSqUD9kCAXrJdS3g", true],
+ ].each{|privkey_base58,expected_compression|
+ k = Bitcoin::Key.from_base58(privkey_base58)
+ k.compressed.should == expected_compression
+ k2 = Bitcoin::Key.new(nil, k.pub)
+ k2.compressed.should == expected_compression
+ 16.times{|n|
+ msg = "Very secret message %d: 11" % n
+ signature = k.sign_message(msg)
+ k2.verify_message(signature, msg).should == true
+ Bitcoin::Key.verify_message(k.addr, signature, msg).should == true
+ }
+ }
end
end
rescue LoadError
end