Solved

Conversion from hexadecimal to decimal of 40+ bytes

Posted on 2003-12-05
5
2,010 Views
Last Modified: 2008-02-01
I need to convert hexadecimal digital signatures as received from a 2 dimensional barcode scans, these strings can be 40 to 80 bytes in length when received in hexadecimal.  How can I convert them easily into Decimal so that I can then validate them with their public keys.  I thought there was a HEX2DEC function, but I may constructing the select improperly.  Here is an example of a hexadecimal string that I must decrypt:

12CFB87157FCF25CD4FC511366867EE8A2E724D2550A15EAE602734CC669D9661479D2CA3FE74E18
0
Comment
Question by:atlvandyguy
  • 3
5 Comments
 
LVL 5

Accepted Solution

by:
DrJekyll earned 500 total points
ID: 9883982
From MetaLink, There may be new functions available that others can share.


 
Doc ID:       Note:45247.1      Content Type:       TEXT/PLAIN         
Subject:       RADIX CONVERSION PACKAGE (HEXADECIMAL SUPPORT)      Creation Date:       09-APR-1997         
Type:       BULLETIN      Last Revision Date:       20-NOV-2002         
Status:       PUBLISHED            
Abstract:           This package contains functions that will aid in
                    converting numbers to strings in different radix (base)
                    and vice versa.
 
 
How to use this package: Running this script will install the package and
grant execute privilege to public.  Check the package specification below
for purpose and syntax of each available function.
 
Error handling: Whenever the conversion cannot be done (due to invalid
number or string, or invalid radix), an ORA-6502: "PL/SQL: numeric or
value error" is raised.
*/
 
create or replace package Lang_Integer as
  /* The package is named loosely after a similar Java class,
     java.lang.Integer; in addition, all public package functions
     (except toRadixString() which has no Java equivalent) are named
     after equivalent Java methods in the java.lang.Integer class.
  */
 
  /* Convert a number to string in given radix.
     Radix must be in the range [2, 16].
  */
  function toRadixString(num in number, radix in number) return varchar2;
  pragma restrict_references (toRadixString, WNDS, WNPS, RNDS, RNPS);
 
  /* Convert a number to binary string. */
  function toBinaryString(num in number) return varchar2;
  pragma restrict_references (toBinaryString, WNDS, WNPS, RNDS, RNPS);
 
  /* Convert a number to hexadecimal string. */
  function toHexString(num in number) return varchar2;
  pragma restrict_references (toHexString, WNDS, WNPS, RNDS, RNPS);
 
  /* Convert a number to octal string. */
  function toOctalString(num in number) return varchar2;
  pragma restrict_references (toOctalString, WNDS, WNPS, RNDS, RNPS);
 
  /* Convert a string, expressed in decimal, to number. */
  function parseInt(s in varchar2) return number;
  pragma restrict_references (parseInt, WNDS, WNPS, RNDS, RNPS);
 
  /* Convert a string, expressed in given radix, to number.
     Radix must be in the range [2, 16].
  */
  function parseInt(s in varchar2, radix in number) return number;
  pragma restrict_references (parseInt, WNDS, RNDS);
end Lang_Integer;
/
 
create or replace package body Lang_Integer as
  /* Takes a number between 0 and 15, and converts it to a string (character)
     The toRadixString() function calls this function.
 
     The caller of this function is responsible for making sure no invalid
     number is passed as the argument.  Valid numbers include non-negative
     integer in the radix used by the calling function.  For example,
     toOctalString() must pass nothing but 0, 1, 2, 3, 4, 5, 6, and 7 as the
     argument 'num' of digitToString().
  */
  function digitToString(num in number) return varchar2 as
    digitStr varchar2(1);
  begin
    if (num<10) then
      digitStr := to_char(num);
    else
      digitStr := chr(ascii('A') + num - 10);
    end if;
 
    return digitStr;
  end digitToString;
 
  /* Takes a character (varchar2(1)) and converts it to a number.
     The parseInt() function calls this function.
 
     The caller of this function is responsible for maksing sure no invalid
     string is passed as the argument.  The caller can do this by first
     calling the isValidNumStr() function.
  */
  function digitToDecimal(digitStr in varchar2) return number as
    num number;
  begin
    if (digitStr >= '0') and (digitStr <= '9') then
      num := ascii(digitStr) - ascii('0');
    elsif (digitStr >= 'A') and (digitStr <= 'F') then
      num := ascii(digitStr) - ascii('A') + 10;
    end if;
 
    return num;
  end digitToDecimal;
 
  /* Checks if the given string represents a valid number in given radix.
     Returns true if valid; ORA-6502 if invalid.
  */
  function isValidNumStr(str in out varchar2,radix in number) return boolean
as
    validChars varchar2(16) := '0123456789ABCDEF';
    valid number;
    len number;
    i number;
    retval boolean;
  begin
    if (radix<2) or (radix>16) or (radix!=trunc(radix)) then
      i := to_number('invalid number');  /* Forces ORA-6502 when bad radix. */
    end if;
 
    str := upper(str);  /* a-f ==> A-F */
    /* determine valid characters for given radix */
    validChars := substr('0123456789ABCDEF', 1, radix);
    valid := 1;
    len := length(str);
    i := 1;
 
    while (valid !=0) loop
      valid := instr(validChars, substr(str, i, 1));
      i := i + 1;
    end loop;
 
    if (valid=0) then
      retval := false;
      i := to_number('invalid number');  /* Forces ORA-6502. */
    else
      retval := true;
    end if;
 
    return retval;
  end isValidNumStr;
 
  /* This function converts a number into a string in given radix.
     Only non-negative integer should be passed as the argument num, and
     radix must be a positive integer in [1, 16].
     Otherwise, 'ORA-6502: PL/SQL: numeric or value error' is raised.
  */
  function toRadixString(num in number, radix in number) return varchar2 as
    dividend number;
    divisor number;
    remainder number(2);
    numStr varchar2(2000);
  begin
    /* NULL NUMBER -> NULL hex string */
    if(num is null) then
      return null;
    elsif (num=0) then  /* special case */
      return '0';
    end if;
 
    /* invalid number or radix; force ORA-6502: PL/SQL: numeric or value err
*/
    if (num<0) or (num!=trunc(num)) or
       (radix<2) or (radix>16) or (radix!=trunc(radix)) then
      numStr := to_char(to_number('invalid number'));  /* Forces ORA-6502. */
      return numStr;
    end if;
 
    dividend := num;
    numStr := '';  /* start with a null string */
 
    /* the actual conversion loop */
    while(dividend != 0) loop
      remainder := mod(dividend, radix);
      numStr := digitToString(remainder) || numStr;
      dividend := trunc(dividend / radix);
    end loop;
 
    return numStr;
  end toRadixString;
 
  function toBinaryString(num in number) return varchar2 as
  begin
    return toRadixString(num, 2);
  end toBinaryString;
 
  function toHexString(num in number) return varchar2 as
  begin
    return toRadixString(num, 16);
  end toHexString;
 
  function toOctalString(num in number) return varchar2 as
  begin
    return toRadixString(num, 8);
  end toOctalString;
 
  /* The parseInt() function is equivalent to TO_NUMBER() when called
     without a radix argument.  This is consistent with what Java does.
  */
  function parseInt(s in varchar2) return number as
  begin
    return to_number(s);
  end parseInt;
 
  /* Converts a string in given radix to a number */
  function parseInt(s in varchar2, radix in number) return number as
    str varchar2(2000);
    len number;
    decimalNumber number;
  begin
    /* NULL hex string -> NULL NUMBER */
    if(s is null) then
      return null;
    end if;
 
    /* Because isValidNumStr() expects a IN OUT parameter, must use an
       intermediate variable str.  str will be converted to uppercase
       inside isValidNumStr().
    */
    str := s;
    if (isValidNumStr(str, radix) = false) then
      return -1;  /* Never executes because isValidNumStr forced ORA-6502. */
    end if;
 
    len := length(str);
    decimalNumber := 0;
 
    /* the actual conversion loop */
    for i in 1..len loop
      decimalNumber := decimalNumber*radix + digitToDecimal(substr(str, i,
1));
    end loop;
 
    return decimalNumber;
  end parseInt;
end Lang_Integer;
/
 
grant execute on Lang_Integer to public;  /* anyone can use this package */

.
0
 
LVL 23

Expert Comment

by:seazodiac
ID: 9885371
why don't you use programming language to do that?
Is that NOT an option? any 3GL programming language JAVA, C++ should have Hex to decimal conversion function.

if you prefer done in Oracle, follow DJ's solution
0
 
LVL 7

Expert Comment

by:grim_toaster
ID: 9895275
All seems very complicated to me!

What's wrong with:

SELECT to_number('FF', 'xx') FROM dual

The only problems that I know of with this is that you need at least 8i, and you need to specify an 'x' for every number.  But at least you could specify "SELECT to_number('FF', 'xxxxxxxxxx') FROM dual" and it would work fine for up to 10 hexadecimal characters (and you can extend that even further).
0
 
LVL 7

Expert Comment

by:grim_toaster
ID: 9895314
Ah, found one problem, you're limited to:

SELECT TO_NUMBER('12CFB87157FCF25CD4FC511366867EE8A2E724D2550A15EAE11111111111111',
                 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
FROM dual

Or 63 x's
0
 
LVL 7

Expert Comment

by:grim_toaster
ID: 9895465
This should get around the limit of 63 characters (I've done limited testing), but it would be clearer if you seperated out into your own function and split it out a bit more.  This allows up to 126 characters.  And is probably a lot more complicated than it needs to be...

mask -->
'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
val -->
'12CFB87157FCF25CD4FC511366867EE8A2E724D2550A15EAE602734CC669D9661479D2CA3FE74E18'

SELECT NVL(TO_NUMBER(SUBSTR(:val, 0, 63), :mask), 0) *
         DECODE(SIGN(LENGTH(:val) - 63), -1, 1, 0, 1,
         DECODE(NVL(TO_NUMBER(SUBSTR(:val, 0, 63), :mask), 0), 0, 0,
         DECODE(POWER(16, (LENGTH(:val) - 63)), 1, 0, POWER(16, (LENGTH(:val) - 63)))))
         + NVL(TO_NUMBER(SUBSTR(:val, 64), :mask), 0)
FROM dual
0

Featured Post

PRTG Network Monitor: Intuitive Network Monitoring

Network Monitoring is essential to ensure that computer systems and network devices are running. Use PRTG to monitor LANs, servers, websites, applications and devices, bandwidth, virtual environments, remote systems, IoT, and many more. PRTG is easy to set up & use.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Stay Alert! 13 63
compre toata in where clue oracle 4 44
PL/SQL Search for multiple strings 5 22
Oracle and DateTime math 6 15
Working with Network Access Control Lists in Oracle 11g (part 2) Part 1: http://www.e-e.com/A_8429.html Previously, I introduced the basics of network ACL's including how to create, delete and modify entries to allow and deny access.  For many…
Have you ever had to make fundamental changes to a table in Oracle, but haven't been able to get any downtime?  I'm talking things like: * Dropping columns * Shrinking allocated space * Removing chained blocks and restoring the PCTFREE * Re-or…
Via a live example, show how to take different types of Oracle backups using RMAN.
This videos aims to give the viewer a basic demonstration of how a user can query current session information by using the SYS_CONTEXT function

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now