Created
April 12, 2014 13:27
-
-
Save upsuper/10535796 to your computer and use it in GitHub Desktop.
Secure password - Implementation of a challenge-style password checking flow based on ECDSA. By this method, server will never know the password while it is still able to verify.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| require "socket" | |
| require "OpenSSL" | |
| Group = OpenSSL::PKey::EC::Group.new("secp160k1") | |
| def send(server, data) | |
| puts ">>> #{data}" | |
| server.puts data | |
| end | |
| def recv(server) | |
| data = server.gets | |
| puts "<<< #{data}" | |
| data | |
| end | |
| def generate_private_key(password) | |
| order = Group.order.to_i | |
| begin | |
| digest = OpenSSL::Digest::SHA1.digest(password) | |
| num = OpenSSL::BN.new(digest, 2).to_i | |
| password = digest | |
| end while num == 0 or num >= order | |
| OpenSSL::BN.new(digest, 2) | |
| end | |
| def generate_public_key(priv_key) | |
| Group.generator.mul(priv_key) | |
| end | |
| def decode_nonce(hex) | |
| OpenSSL::BN.new(hex, 16).to_s 2 | |
| end | |
| def sign_data(priv_key, data) | |
| pub_key = generate_public_key(priv_key) | |
| signer = OpenSSL::PKey::EC.new(Group) | |
| signer.private_key = priv_key | |
| signer.public_key = pub_key | |
| OpenSSL::BN.new(signer.dsa_sign_asn1(data), 2) | |
| end | |
| cmd = ARGV[0] | |
| password = ARGV[1] | |
| priv_key = generate_private_key(password) | |
| puts "private key: #{priv_key.to_s 16}" | |
| server = TCPSocket.new 'localhost', 9000 | |
| case ARGV[0] | |
| when "set-password" | |
| pub_key = generate_public_key(priv_key) | |
| puts "public key: #{pub_key.to_bn.to_s 16}" | |
| send server, "set-pubkey #{pub_key.to_bn.to_s 16}" | |
| when "verify" | |
| send server, "verify" | |
| _, nonce = recv(server).split | |
| sign = sign_data(priv_key, decode_nonce(nonce)) | |
| send server, "sign #{sign.to_s 16}" | |
| _, result = recv(server) | |
| end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| require "socket" | |
| require "OpenSSL" | |
| Group = OpenSSL::PKey::EC::Group.new("secp160k1") | |
| Verifier = OpenSSL::PKey::EC.new(Group) | |
| def send(client, data) | |
| puts ">>> #{data}" | |
| client.puts data | |
| end | |
| def recv(client) | |
| data = client.gets | |
| puts "<<< #{data}" | |
| data | |
| end | |
| def decode_public_key(hex) | |
| bn = OpenSSL::BN.new(hex, 16) | |
| OpenSSL::PKey::EC::Point.new(Group, bn) | |
| end | |
| def generate_nonce | |
| OpenSSL::BN.new(Random.rand(2 ** 160).to_s) | |
| end | |
| def decode_sign(hex) | |
| OpenSSL::BN.new(hex, 16).to_s 2 | |
| end | |
| server = TCPServer.new 9000 | |
| loop do | |
| client = server.accept | |
| addr = client.peeraddr | |
| puts "new client at #{addr[2]}:#{addr[1]}" | |
| cmd, arg = recv(client).split | |
| case cmd | |
| when "set-pubkey" | |
| Verifier.public_key = decode_public_key(arg) | |
| when "verify" | |
| nonce = generate_nonce | |
| send client, "nonce #{nonce.to_s 16}" | |
| _, sign = recv(client).split | |
| result = Verifier.dsa_verify_asn1( | |
| nonce.to_s(2), decode_sign(sign)) | |
| send client, "result #{result}" | |
| end | |
| client.close | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment