Well That’s Random…


Increasingly we are asked to provide more secure passwords for accounts of all kinds. As I have written previously, because coming up with new ones that meet all complexity requirements can be a real pain, I try to avoid passwords whenever possible in favor of PKE authentication. Sometimes, however, they are unavoidable.

So how secure is “secure”? DISA STIG guidelines state that at a minimum, a secure password should have the following characteristics:

  • A length of at least 15 characters
  • At least one upper case character
  • At least one lower case character
  • At least one number
  • At least one special character

I prefer to take it up a notch, especially with passwords for application accounts for JDBC connection pools and the like. I generally require a minimum of 20 characters, and two each of upper case, lower case, numbers, and special characters. What happens when you need to provide passwords for dozens of accounts across multiple environments that must all be unique, and preferably not too predictable? You get random!

Both the Oracle database and the Linux operating system provide ways to generate random sets of characters which can be exploited to quickly generate fully compliant passwords. For example, the DBMS_RANDOM package in Oracle can be used something like this (example code available for download here):

create or replace package utl_password as
/*************************************************************

    Name: utl_password
    Purpose:

    The utl_password package allows you to generate a random   
    alphanumeric password (with special characters) of the 
    length specified in the input.

*************************************************************/

  function generate_random (p_length number) return varchar2;

end utl_password;
/

create or replace package body utl_password as

  function generate_random (p_length number) return varchar2
  as
     my_str   varchar2 (4000);
  begin
     /* Build a random alphanumeric string of the length 
        specified in the input */
     for i in 1 .. (p_length-1)
     loop
         my_str := my_str || 
                   dbms_random.string (
                       case 
                       when dbms_random.value (0, 1) < 0.5 
                       then 'l' 
                       else 'x' end,
                   1);
     end loop;

     /* Replace 12 random alphanumeric characters with 
        special characters */
     my_str := translate (my_str, 
               dbms_random.string ('A', 12),'_+/#)^!&*(%|');

     /* Ensure that our string starts with a character */
     my_str := dbms_random.string('a', 1) || my_str;

     return my_str;
  end generate_random;

end utl_password;
/


Package UTL_PASSWORD compiled

Elapsed: 00:00:00.281


Package Body UTL_PASSWORD compiled

Elapsed: 00:00:00.051

Once completed, the function can be called like this:

select utl_password.generate_random(20) from dual;

UTL_PASSWORD.GENERATE_RANDOM(20) 
---------------------------------------- 
GZgu_Wf3aim_mCz_pDFy                     


Elapsed: 00:00:00.049
1 rows selected.

And presto! One fully compliant password, ready to use. If by some fluke the password produced isn’t fully compliant, just run the function again.

But what if I need a lot of passwords, all at once? A slight modification of our query produces the desired effect:

select utl_password.generate_random(20) 
  from dual connect by level <= 10;

UTL_PASSWORD.GENERATE_RANDOM(20) 
-------------------------------- 
ubr_Oybp__Jhppuiqhu_                     
rGDNFah7wJ7iwZm_ib_0                     
K_tlUz_2NfW_GJ58OC_V                     
X_h__r____FDsFXQ8kuX                     
p_WXf1_2B9_p6TeyiDWn                     
W_qzbw__bp___8sp_8tH                     
Own___z3Ax1sbTTh_x_x                     
CznriX___auTzEOxhszY                     
fa9_eppq9_gD6_9d1lmQ                     
WsgY__7abDmldFDDjL_w                   


Elapsed: 00:00:00.005
10 rows selected.

But what if remembering the SQL is too complicated, or I just don’t like to type that much? Not to worry: a quick bash shell script (available here) can do pretty much the same thing.

#!/bin/bash
# mkpwd, version 1
# by Pete Magee

# This script generates a random password of 20 alphanumeric 
# and special characters. It takes the number of passwords  
# to be created as an argument.

# For the number of random passwords specified in the 
# command line
for (( i=1; i<=$1; i++ ))
do

  # Use the built-in random number generator to determine 
  # which characters to include. Add whatever special 
  # characters you wish to utilize in the template after 
  # "[:alnum:]".
  echo `head -n 10 /dev/urandom | 
        tr -cd "[:alnum:]_!@#$%^&*() " | 
        cut -c '1-20'`
done

This script is already coded to produce a 20-character password; rather than the length of the password, it accepts the number of passwords to generate:

$ ./mkpasswd 10
L##6qKi_W%cSuJ%yGaqS
5dn)CPotSlScI!9$zK0w
1mP3L5vU%6*0p56HcwD@
J71hN oNpz$J0pIrwVlH
xxUto#TM@kZ_jiI5Mm C
svo2_&MYhM5pP(_bIveI
sQY4Ru(whOricrq^06Zn
2E4GC3BVCKNt$RE%0QY(
P3xOs1NlX kTv6Mq9gOR
SS_Rel4Ph50_%h_OGe3b

Scripts like these can take an otherwise arduous chore and make it quick and relatively painless. For an extra bit of security – just in case the random generation isn’t quite random enough, check out this post for ensuring that passwords do not contain dictionary words, and this one for securing your new passwords in an Oracle Wallet.

One thought on “Well That’s Random…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.