How to manage passwords

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.

You may be looking for this:
http://www.ruby-doc.org/core/classes/Base64.html#M004726

On 19 set, 18:55, Junkone [email protected] wrote:

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

On Sun, Sep 21, 2008 at 12:52:05AM +0900, [email protected] wrote:

“some_other_password”.crypt(hash) == hash >> false
mypassword.crypt(hash) == hash) >> true

I don’t recommend relying on crypt if you want “real” security. The
cryptographic value of the algorithm used by crypt is pretty damned weak
by today’s standards.

Junkone wrote:

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

On Sep 22, 12:00 am, Justin C. [email protected] wrote:

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.

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.

:confused:

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

On 22.09.2008, at 16:58, Junkone wrote:

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.

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
passwords.
It uses OpenSSL::Cipher::Cipher.new(“AES-256-CBC”) and a generated
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
use the
*_interactive() methods from M, without the client and without
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 = nil # safe password storage if anyone can read your
memory

If you change the next line, don’t forget to change it in

client.rb, too!
PASS_UNIX_SOCK=“/tmp/my.sock”

class PasswordStorage

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

 # PasswordStorage::get_password returns the cleartext password

for a user.
def get_password(username=nil)
decode(@secret[username], username) if username
end

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

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

 # private Methods of PasswordStorage
 private

 def encode(s,username)
   cipher = OpenSSL::Cipher::Cipher.new("AES-256-CBC")
   @iv = @iv || cipher.random_iv
   cipher.iv = @iv
   # for each user we want to have a long random key to encrypt the
   # user/passwd storage
   @shared_key[username] = @shared_key[username] ||

OpenSSL::Random::random_bytes(52)
cipher.encrypt
@shared_key[username] << “\0” until
@shared_key[username].length == 52
cipher.key = @shared_key[username]
return (cipher.update(s) << cipher.final)
end

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

end # PasswordStorage

module_function

getter/setter

def getpass(username=nil)
@@pw_storage.get_password(username)
end
def setpass_interactive(username=nil)
@@pw_storage = @@pw_storage || M::PasswordStorage.new
@@pw_storage.set_password_interactive(username)
end
def setpass(username=nil, password=nil)
@@pw_storage = @@pw_storage || M::PasswordStorage.new
@@pw_storage.set_password(username,password) unless username.nil?
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 = ""
 server = UNIXServer.new(PASS_UNIX_SOCK)
 begin
   sock = server.accept_nonblock
   res = sock.readpartial(4096).split(" ")
   sock.close
 rescue Errno::EAGAIN, Errno::ECONNABORTED, Errno::EPROTO,

Errno::EINTR, EOFError
IO.select([server])
retry
end

 clean_unixsocket

 # res: [user passwd]
 if @@pw_storage.nil?
   b = []
   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=“/tmp/my.sock”
unless File.exists? PASS_UNIX_SOCK
puts “server is not running”
exit
end

enable/disable echo on prompt

def echo(on=true, masked=false)
term = Termios::getattr( $stdin )

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

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

print “user:”
user = Kernel.gets.strip
puts “”
print "#{user}'s password: "
echo(false)
passwd = 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ücs