Oracle FAQ Your Portal to the Oracle Knowledge Grid
HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US
 

Home -> Community -> Mailing Lists -> Oracle-L -> Re: C / external procedure puzzle for the C guru's (fwd)

Re: C / external procedure puzzle for the C guru's (fwd)

From: Jared Still <jkstill_at_bcbso.com>
Date: Tue, 6 Jun 2000 08:32:26 -0700 (PDT)
Message-Id: <10520.107897@fatcity.com>


Well, I found a solution to the problem.

Thanks to all the respondents that sent in their ideas.

The problem turns out to be how the data is handled between the time the library call exits, and Oracle returns the values to the calling PL/SQL function.

As you may or may not know, a string in C is terminated with an ASCII 0 ( zero ).

This is not a problem in the RC4 code, as the data is modified in memory as an array element, which is all a string is, albeit one with a character '\0' as the last element.

Integral to the RC4 algorithm is the use of XOR.

Bytes of data to be encrypted are XOR'd with values from the key. This is not the simple XOR encryption it might appear, as the key supplied by the caller is greatly mangled before use in RC4, and thereby rather secure.

The problem arises when the XOR'd value is equal to 0.

This puts a C null right in the middle of the string's buffer, causing Oracle to truncate the varchar2.

The solution is to ensure set the 8th bit in the encrypted values, causing them to always be some value > 127.

The side effect of this, is that the range of encodeable characters has just been reduced to 0 - 127.

This will work for most uses of RC4 within a database, as encryption is usually applied to readable text there.

The full RC4 code is included below, here is the snippet of what was changed.

I'll put this whole mess on www.teleport.com/~jkstill/util when in a few days.

Thanks

Jared

snippet:

                buffer_ptr[counter] ^= 128; /* set 8th bit in string to be encrypted */

		/* 
			replace this piece of code

				buffer_ptr[counter] ^= state[xorIndex];

			so that values in the buffer will always be > 127
		*/

		buffer_ptr[counter] ^= ( state[xorIndex] > 128 ? state[xorIndex] ^ 128 :  state[xorIndex] );


--------------------------------------

#include <stdio.h>

/*

	modified to work with normal ascii characters only
	this is to prevent any char(0) from being set in
	the string, as this a string terminator in C, and
	will truncate the varchar2 values

	all key values are < 128 in prepare_key and
	all data values are >= 128 in rc4 function

	this routine works with ascii values < 128 only

	Obviously suited for encrypting normal readable data only

*/

#define buf_size 1024

   /*rc4.c */
#include "rc4.h"

static void swap_byte(unsigned char *a, unsigned char *b);

void prepare_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) {

	unsigned char swapByte;
	unsigned char index1;
	unsigned char index2;
	unsigned char* state;
	short counter;     
 
	state = &key->state[0];         
	for(counter = 0; counter < 256; counter++)              
		state[counter] = counter;               
	key->x = 0;     
	key->y = 0;     
	index1 = 0;     
	index2 = 0;             
	for(counter = 0; counter < 256; counter++)      
	{               
		index2 = (key_data_ptr[index1] + state[counter] + index2) % 256;
		swap_byte(&state[counter], &state[index2]);            

		index1 = (index1 + 1) % key_data_len;  
	}       

}     

void rc4(unsigned char *buffer_ptr, int buffer_len, rc4_key *key) {

	unsigned char x;
	unsigned char y;
	unsigned char* state;
	unsigned char xorIndex;
	short counter;              
 
	x = key->x;     
	y = key->y;     
 
	state = &key->state[0];         
	for(counter = 0; counter < buffer_len; counter ++)      
	{               
		x = (x + 1) % 256;                      
		y = (state[x] + y) % 256;               
		swap_byte(&state[x], &state[y]);                        
 
		xorIndex = (state[x] + state[y]) % 256;                 
 

		buffer_ptr[counter] ^= 128; /* set 8th bit in values */


		/* 
			replace this piece of code

				buffer_ptr[counter] ^= state[xorIndex];

			so that values in the buffer will always be > 127
		*/

		buffer_ptr[counter] ^= ( state[xorIndex] > 128 ? state[xorIndex] ^ 128 :  state[xorIndex] );
	}               
	key->x = x;     
	key->y = y;

}     

static void swap_byte(unsigned char *a, unsigned char *b) {

        unsigned char swapByte;  

	swapByte = *a; 
	*a = *b;      
	*b = swapByte;

}    

int rc4p( unsigned char *key_data, unsigned char *crypt_text ) {
  unsigned char seed[256];
  unsigned char data[512];
  char digit[5];
  int hex,i;
  int n, text_len;
  rc4_key key;

  strcpy(data,key_data);
  n = strlen(data);
  if (n&1)
  {
    strcat(data,"0");
    n++;
  }
  n/=2;
  strcpy(digit,"AA");
  digit[4]='\0';
  for (i=0;i<n;i++)
  {
    digit[2] = data[i*2];
    digit[3] = data[i*2+1]; Received on Tue Jun 06 2000 - 10:32:26 CDT

Original text of this message

HOME | ASK QUESTION | ADD INFO | SEARCH | E-MAIL US