how to manage passwords

J

Junkone

many of my ruby apps have the password hard coded. i am looking for a
way so that i can control the password not to be stored as text file.
what are the ruby options that are available.
 
Y

yu.ching.tien

many of my ruby apps have the password hard coded. i am looking for a
way so that i can control the password not to be stored as text file.
what are the ruby options that are available.

could use String#crypt

mypassword = "visible_to_everyone"
hash = mypassword.crypt(mypassword)


"some_other_password".crypt(hash) == hash >> false
mypassword.crypt(hash) == hash) >> true
 
J

Justin Collins

Junkone said:
many of my ruby apps have the password hard coded. i am looking for a
way so that i can control the password not to be stored as text file.
what are the ruby options that are available.

Do you need to know what the stored password is, or do you just need to
validate passwords?

If the latter, you can use the MD5, SHA1, or SHA2 libraries that come
with Ruby:

require 'digest/sha1'

#Could load the hash from a file instead
hash = Digest::SHA1.new.update("mypassword")

print "Enter password: "
input_password = gets.strip

if hash == Digest::SHA1.new.update(input_password)
puts "Access granted."
else
puts "Access denied."
end


-Justin
 
J

Junkone

Do you need to know what the stored password is, or do you just need to
validate passwords?

If the latter, you can use the MD5, SHA1, or SHA2 libraries that come
with Ruby:

require 'digest/sha1'

#Could load the hash from a file instead
hash = Digest::SHA1.new.update("mypassword")

print "Enter password: "
input_password = gets.strip

if hash == Digest::SHA1.new.update(input_password)
        puts "Access granted."
else
        puts "Access denied."
end

-Justin

i just store passwords in text files. i am looking for a secure way of
keeping these passwords and using it thro ruby as my progs need the
pass.
for eg. i send auto IM using bot and need my IM pass to be kept
secure.
 
T

Tod Beardsley

Hmm, that'd be quite the trick. Not even the professional-grade IM
clients (Trillian and Pidgin) have figured out how to do that yet.

:/
 
S

Sandor Szücs

It's a month ago but maybe it helps anyway.

i just store passwords in text files. i am looking for a secure way =20=
of
keeping these passwords and using it thro ruby as my progs need the
pass.
for eg. i send auto IM using bot and need my IM pass to be kept
secure.

I don't know for sure if the following can help:
http://pog.rubyforge.org/doc/


Otherwise I had a similar problem in a daemon.
I solved it like that:
M::main_loop() # entry point
M::passwd_eventloop() # daemon mode, use an UNIX domain socket
M::set_password_interactive() # interactive mode (CLI without socket)
M::passwordStorage saves the username password tuple in the memory by
encrypting the tuple. It has all methods you need to get and set =20
passwords.
It uses OpenSSL::Cipher::Cipher.new("AES-256-CBC") and a generated =20
random
key with key length 52 to save the tuple in memory.

If you just need an interactive way to set your passsword then just =20
use the
*_interactive() methods from M, without the client and without =20
M::passwd_eventloop().

Disclaimer:
I am not a crypto expert and maybe there are a few timing issues in the
following code!

#server:
require 'rubygems'
require 'termios'
require 'openssl'

module M
class ShutdownException < StandardError; end

@@pw_storage =3D nil # safe password storage if anyone can read your =20=

memory

# If you change the next line, don't forget to change it in =20
client.rb, too!
PASS_UNIX_SOCK=3D"/tmp/my.sock"

class PasswordStorage

def initialize
@secret =3D {}
@shared_key =3D {}
end

# PasswordStorage::get_password returns the cleartext password =20
for a user.
def get_password(username=3Dnil)
decode(@secret[username], username) if username
end

def set_password_interactive(username=3D"")
# get password from prompt at the start
print "provide password for #{username}: "
begin
M::echo(false)
passwd =3D STDIN.gets.strip
ensure
M::echo(true)
end
if passwd.empty?
STDERR.puts("An empty password is not allowed.")
exit
end
@secret[username] =3D encode(passwd,username)
passwd=3D""
puts ""
end

def set_password(user=3Dnil, passwd=3Dnil)
if user.nil? or passwd.nil? or user.empty? or passwd.empty?
return false
else
@secret[user] =3D encode(passwd,user)
end
end

# private Methods of PasswordStorage
private

def encode(s,username)
cipher =3D OpenSSL::Cipher::Cipher.new("AES-256-CBC")
@iv =3D @iv || cipher.random_iv
cipher.iv =3D @iv
# for each user we want to have a long random key to encrypt the
# user/passwd storage
@shared_key[username] =3D @shared_key[username] || =20
OpenSSL::Random::random_bytes(52)
cipher.encrypt
@shared_key[username] << "\0" until =20
@shared_key[username].length =3D=3D 52
cipher.key =3D @shared_key[username]
return (cipher.update(s) << cipher.final)
end

def decode(key,username)
cipher =3D OpenSSL::Cipher::Cipher.new("AES-256-CBC")
cipher.iv =3D @iv
cipher.decrypt
cipher.key =3D @shared_key[username]
return (cipher.update( key ) << cipher.final)
end
end # PasswordStorage

module_function

# getter/setter
def getpass(username=3Dnil)
@@pw_storage.get_password(username)
end
def setpass_interactive(username=3Dnil)
@@pw_storage =3D @@pw_storage || M::passwordStorage.new
@@pw_storage.set_password_interactive(username)
end
def setpass(username=3Dnil, password=3Dnil)
@@pw_storage =3D @@pw_storage || M::passwordStorage.new
@@pw_storage.set_password(username,password) unless username.nil? =20=

or password.nil?
end
def clean_unixsocket
File.delete(PASS_UNIX_SOCK) if File.exists? PASS_UNIX_SOCK
end

# It reads the passwd from a unix domain socket.
def passwd_eventloop
clean_unixsocket

res =3D ""
server =3D UNIXServer.new(PASS_UNIX_SOCK)
begin
sock =3D server.accept_nonblock
res =3D sock.readpartial(4096).split(" ")
sock.close
rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO, =20
Errno::EINTR, EOFError
IO.select([server])
retry
end

clean_unixsocket

# res: [user passwd]
if @@pw_storage.nil?
b =3D []
b << setpass(res.shift,res.shift)

return b.all?
end

return false
end

# M::main_loop
# The daemon mode has two states, user/password set and not set.
def main_loop
begin
Signal.trap("INT") {raise ShutdownException }
Signal.trap("TERM") {raise ShutdownException }

# Comment out, if you want to use interactive mode
passwd_eventloop

# Uncomment, if you want to use it without reading from socket.
#set_password_interactive

loop do
#do your stuff...
end # loop
rescue ShutdownException
clean_unixsocket
end
end

end # module M

# interactive mode
#M::setpass_interactive("user")
#puts M::getpass("user")[
# daemon mode
M::main_loop()
# end server

# client
#!/usr/bin/env ruby -wKU

require 'socket'
require 'rubygems'
require 'termios'

PASS_UNIX_SOCK=3D"/tmp/my.sock"
unless File.exists? PASS_UNIX_SOCK
puts "server is not running"
exit
end

# enable/disable echo on prompt
def echo(on=3Dtrue, masked=3Dfalse)
term =3D Termios::getattr( $stdin )

if on
term.c_lflag |=3D ( Termios::ECHO | Termios::ICANON )
else # off
term.c_lflag &=3D ~Termios::ECHO
term.c_lflag &=3D ~Termios::ICANON if masked
end

Termios::setattr( $stdin, Termios::TCSANOW, term )
end

print "user:"
user =3D Kernel.gets.strip
puts ""
print "#{user}'s password: "
echo(false)
passwd =3D Kernel.gets.chomp

UNIXSocket.open PASS_UNIX_SOCK do |socket|
socket.write_nonblock("#{user} #{passwd}")
end

echo(true)
puts ""
puts "Thank you for providing the necessary information"
# end client


regards, Sandor Sz=FCcs
--=
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,197
Messages
2,571,041
Members
47,643
Latest member
ashutoshjha_1101

Latest Threads

Top