Re: Column Encryption (LONG)
Posted in 1995
Michael L. Gonzales <76543.2600@CompuServe.COM> writes:
>I need a method to take entered data (passwords), encrypt the
>value, and store the value in a column. Obviously, I would need
>to decipher the stored value for future validations. The purpose
>of this is to merely keep any individual from scanning the
>database for passwords.
>Any recommendations on encrypting data?
>Mike.
Mike,
I'm not a C programmer, but unix-style encrypted passwords may be used within
a 4GL program with the help of some C routines I've written for the purpose.
The examples below contain a 4GL program that creates and stores crypt(3)
encrypted passwords within a Informix table, two C functions to encrypt and
validate passwords, and another C function to generate salt values for the
encryption routine. The examples were tested under Online 5.02 running on
an HP/9000 Series 800 with HP-UX. The column encryption is actually done
completely within the crypt(3) routine, supplied with most *nix operating
systems sold in the United States, subject to ITAR regulations.
#-------------------------------------------------------------------------------
# cryptval.4gl:
#-------------------------------------------------------------------------------
DATABASE stores2
MAIN
DEFINE username, plaintext,salt,cryptval CHAR(16),
checkcode INTEGER,
knt SMALLINT
#
#--- Create new table in stores database to hold passwords ---#
#
SELECT COUNT(*) INTO knt FROM SYSTABLES WHERE tabname = 'passwd'
IF knt IS NULL OR knt = 0 THEN
CREATE TABLE passwd(userid CHAR(16), passwd CHAR(16))
END IF
#
#--- Generate new salt value based on time and program name ---#
#
CALL mksalt(arg_val(0)) RETURNING salt
#
#--- Generate new password given plaintext and salt values ---#
#
DISPLAY "--- Creating a new password entry for a user ---"
PROMPT "username: " FOR username
SELECT COUNT(*) INTO knt FROM passwd WHERE passwd.userid = username
IF knt IS NOT NULL AND knt > 0 THEN
DELETE FROM passwd WHERE userid = username
LET knt = SQLCA.sqlerrd[3]
IF knt IS NULL OR knt = 0 THEN
DISPLAY "%%% cannot delete passwd entry for ", username CLIPPED, "!"
EXIT PROGRAM 1
END IF
END IF
PROMPT "password: " FOR plaintext ATTRIBUTE(INVISIBLE)
CALL cryptwd(plaintext,salt) RETURNING cryptval
INSERT INTO passwd VALUES(username,cryptval)
LET knt = SQLCA.sqlerrd[3]
IF knt IS NULL OR knt = 0 THEN
DISPLAY "%%% cannot create passwd entry for ", username CLIPPED, "!"
EXIT PROGRAM 1
END IF
DISPLAY " "
DISPLAY " "
#
#--- Validate password given plaintext and encrypted values ---#
#
DISPLAY "--- Validating a password entry for a user ---"
PROMPT "username: " FOR username
SELECT passwd.passwd INTO cryptval FROM passwd WHERE passwd.userid = username
LET knt = SQLCA.sqlerrd[3]
IF knt IS NULL OR knt = 0 THEN
DISPLAY "%%% cannot locate passwd entry for ", username CLIPPED, "!"
EXIT PROGRAM 1
END IF
PROMPT "password: " FOR plaintext ATTRIBUTE(INVISIBLE)
CALL checkwd(plaintext, cryptval) RETURNING checkcode
IF checkcode THEN
DISPLAY "correct."
ELSE
DISPLAY "incorrect!"
END IF
END MAIN
#-------------------------------------------------------------------------------
# cryptwd.c:
#-------------------------------------------------------------------------------
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
/* return a crypt(3) encrypted password given a plaintext value and salt */
cryptwd(int nargs)
{
char *usage="Usage: call cryptwd(plaintext,salt) returning cryptval";
char *cryptval,*crypt();
char plaintext[16];
char salt[16];
char junk[512];
int i;
if(nargs != 2) {
fprintf(stderr, "cryptwd: wrong number of parameters (%d)\\n", nargs);
fprintf(stderr, "%s\\n", usage);
for( i=0; i<nargs;i++ ) { popquote(junk,512); }
cryptval = '\\0';
retquote(cryptval);
return(1); }
popquote(salt,16);
popquote(plaintext,16);
cryptval = crypt(plaintext,salt);
retquote(cryptval);
return(1);
}
/* validate a crypt(3) encrypted password given plaintext, encrypted values */
checkwd(int nargs)
{
char *usage="Usage: call checkwd(plaintext,cryptwd) returning checkcode";
char *cryptval,*crypt();
char plaintext[16];
char cryptwd[16];
char junk[512];
int checkcode;
int i;
if(nargs != 2) {
fprintf(stderr, "checkwd: wrong number of parameters (%d)\\n", nargs);
fprintf(stderr, "%s\\n", usage);
for( i=0; i<nargs;i++ ) { popquote(junk,512); }
checkcode = 0;
retint(checkcode);
return(1); }
popquote(cryptwd,16);
for( i=0; i<16 && cryptwd[i] != ' ' ;i++ ) { }
cryptwd[i]='\\0';
popquote(plaintext,16);
cryptval = crypt(plaintext,cryptwd);
checkcode = 0;
i = strcmp(cryptval,cryptwd);
if(i == 0) { checkcode = 1; }
retint(checkcode);
return(1);
}
#-------------------------------------------------------------------------------
# mksalt.c:
#-------------------------------------------------------------------------------
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <time.h>
/* Create a new salt value for crypt(3), using a seed value and time of day */
mksalt(int nargs)
{
char *usage="Usage: call mksalt(seed) returning salt";
char alphas[64]=
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char *cryptval,*crypt();
char junk[512];
char seed[16];
char salt[2];
int i;
struct {
unsigned long tv_sec; /* seconds since Jan. 1, 1970 */
long tv_usec; /* and microseconds */
} tp;
struct {
int tz_minuteswest; /* of UTC */
int tz_dsttime; /* type of DST correction to apply */
} tzp;
if(nargs != 1) {
fprintf(stderr, "mksalt: wrong number of parameters (%d)\\n", nargs);
fprintf(stderr, "%s\\n", usage);
for( i=0; i<nargs;i++ ) { popquote(junk,512); }
cryptval = '\\0';
retquote(cryptval);
return(1); }
popquote(seed,16);
gettimeofday(&tp, &tzp);
i = tp.tv_sec % 64;
salt[1] = alphas[i];
i = tp.tv_usec % 64;
salt[0] = alphas[i];
cryptval = crypt(seed,salt);
salt[0] = cryptval[11];
salt[1] = cryptval[12];
retquote(salt);
return(1);
}
Dave Adams //dna// adamsd@cassens.com
-------------------------------------------------------------------------------
"Let's show this prehistoric bitch how we do things downtown!"
-- The Ghostbusters
DISCLAIMER: Not FCC Approved.