Encryption function for database fields
Posted in 1995
Topics: Storage & Space Management, Stored Procedures & SPL, Connectivity: ESQL/C, 4GL & Embedded SQL, Security, Permissions & Auditing, Licensing & Editions
I developed an EPOS system for the licenced 'pub' trade which required
the company name & program licence expiry date to be stored in an INFORMIX
database.
For obvious reasons I wanted these fields & certain others to be encrypted.
Encrypting the strings & writing them to the database did not work, so I have
written some C functions to do this which you may find useful.
It works as follows:
The source string is sent from 4GL to a C funtion which just does a simple XOR
encryption, (you could use a more elaborate DES type algorithm) , the resulting
encrypted string (8-bit) is them sent to a function that uuencodes it to
another string which is returned to the 4GL app'. The string returned from
cmencode() is 7 bit ASCII & can be written to the database without problem.
The decoding routine just does the reverse.
It's really just a hack of codon & uuencode for mail, altered to read & write
strings instead of files.
( An ASCII string is sent to the encodeing function & it returns an ASCII
string roughly 135% the size of the original - so be careful about string &
field sizes, they should be 35% larger that normal. )
Feel free to E-mail me with any comments at
chin@nihc.demon.co.uk
----- CUT HERE --- test.4gl ------------------------------------------------
MAIN
DEFINE stringtoencode,encodedstring,decodedstring,tmp CHAR(200)
DATABASE pub ### change to your database
{######
Just link 4glcrypt.c with this to test & change stringtoencode to
whatever you like.
#######}
WHENEVER ERROR CONTINUE
DROP TABLE testtable
WHENEVER ERROR STOP
CREATE TABLE testtable
(
licence CHAR(300) ## Be careful, encodedstring will be about 35%
## lager (sorry larger - too much beer ) than
## stringtoencode
)
LET stringtoencode="HEY HO LETS GO"
DISPLAY "STRING TO ENCODE <",stringtoencode clipped,">"
LET encodedstring=cmencode(stringtoencode ,LENGTH(stringtoencode)+1)
### Now store encdodedstring in database
INSERT INTO testtable VALUES (encodedstring )
#### WOW licence field now looks really weird !!
#### now get field from table & decode it
SELECT licence INTO tmp FROM testtable
LET decodedstring=cmdecode(tmp ,LENGTH(tmp)+1)
DISPLAY "DECODED STRING<",decodedstring CLIPPED,">"
END MAIN
--------- CUT END OF test.4gl --------------------------------------------
--------- CUT HERE 4glcrypt.c ---------------------------------------------
/* 4glcrypt.c
# @(#) 4glcrypt.c 1.0 Sat Jun 03 20:15:40 BST 1995
# 4glcrypt.c - generates encrypted/decrypted strings for INFORMIX 4GL.
# Copyright (C) 1995 Christopher Moore.
#
# This program is offered 'as is'; the author accepts no responsibility
# for any consequences of its use.
# You may freely distribute and use this code your own programs as long as this
# comment remains. You may NOT sell it or use it in
# software that is sold , and you must not claim you wrote it.
# If you modify the source code & distribute it to other people you must
# include change comments indicating the author of the change, & a description
# of the modification & the date of the change directly after this comment.
*/
/******
To encode a string, place the string in stringtoencode &;
LET encodedstring=cmencode(stringtoencode,length(stringtoencode)+1)
Then just write encodedstring to a database field.
--------------------------------------------------------
To decode the string;
Select stringtodecode from database field, then;
LET decodedstring=cmdecode(stringtodecode,length(stringtodecode)+1)
*******/
#include <stdio.h>
#define MAXSTRINGLEN 200 /*** Change this to suit 4GL var, should be at least
35% lager than the 4GL var you want to encode
*****/
void uuencode(),outdec(),outdecd();
int cmencode(n)
int n;
{
int len, i,cc;
char s[MAXSTRINGLEN];
unsigned char c;
char new[MAXSTRINGLEN];
static char uunew[MAXSTRINGLEN];
c = 0;
i = 150; /* this is the XOR seed can be anything. Someone
wanting to decrypt will have to know this or
try every combo. But the fact that it is uuencoded
as well makes this more difficult. This must match
the seed in cmdecode()
*/
popint(&len); /*** get length of source string ****/
popquote(s,len); /*** get string from 4GL to encode ***/
/*** Encryption routine - this is simple XOR but could be better,using
DES crypt or GNU crypt from libufc.a
****/
new[0]=NULL;
for (cc=0;cc<=len;cc++){
c=s[cc];
new[cc]=c ^ i;
i = c;
}
new[cc]=NULL;
/******
OK we now have an encrypted string, lets uuencode it
to produce uunew, which is sent back to 4GL.
******/
uuencode(new,len,uunew);
retquote(uunew);
return(1); /*** send it back to 4gl ****/
}
int cmdecode(n)
int n;
{
int len, i,cc;
char s[MAXSTRINGLEN];
static char new[MAXSTRINGLEN];
char uunew[MAXSTRINGLEN];
unsigned char c;
c = 0;
i = 150; /* This must match the seed used to encrypt */
popint(&len);
popquote(s,len); /*** Get uuencoded string from 4GL ****/
len=uudecode(s,uunew); /*** uudecode back to encrypted string **/
/******
Simple XOR decryption routine
*******/
new[0]=NULL;
for (cc=0;cc<=len;cc++){
c=uunew[cc];
c = c ^ i;
new[cc]=c;
i = c;
}
new[cc]=NULL;
/**** Ok got original 7 bit ASCII string send back to 4GL *****/
retquote(new);
return(1);
}
/*
* cmencode.c
*
* Encode a string so it can be filed to a database
*/
#include <stdio.h>
/* ENC is the basic 1 character encoding function to make a char printing */
#define ENC(c) (((c) & 077) + ' ')
#define DEC(c) (((c) - ' ') & 077)
/***#define buildout(c,outt) (outt[*(outpos)++]=c)**/
void uuencode(in,inlen, out)
char *in;
char *out;
int inlen;
{
char buf[80];
int i, n;
int inpos,outpos;
inpos=0; /*** Position in source string ****/
outpos=0; /*** Position in object string ****/
for (;;) {
/* 1 (up to) 45 character line */
n = breakstring(in, buf, 45,&inpos,inlen);
out[outpos++]=ENC(n); /*** length of chunk returned in buf **/
for (i=0; i<n; i += 3)
outdec(&buf[i], out,&outpos); /** uuencode data ***/
out[outpos++]='\\n'; /**** terminate chunk with newline ***/
if (n <= 0)
break;
}
out[outpos++]='\\0'; /*** OK all chunks processed NULL terminate ***/
}
/*
* output one group of 3 bytes, pointed at by p, on file f.
*/
void outdec(p, f,outpos)
char *p;
char *f;
int *outpos;
{
int c1, c2, c3, c4;
c1 = *p >> 2;
c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
c4 = p[2] & 077;
f[(*outpos)++]=ENC(c1);
f[(*outpos)++]=ENC(c2);
f[(*outpos)++]=ENC(c3);