ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

MD5 Checksums

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • MD5 Checksums

    Has anyone a function that can be called from a RPGLE program that will return the MD5 Checksum (or SHA-1) of a string.

    Or can anyone thing of another way of encrypting a password stored on an i5 from casual browsing, don't want to have to re-invent the wheel
    Life is a constant struggle against maturity

  • #2
    Re: MD5 Checksums

    found this but have no idea if it works

    PHP Code:
    Here is a sample RPG program which takes into consideration the EBCDIC to ASCII conversionthe hash generation, and the creation of a
    suitable text string
    .  The program assumes that EBCDIC means CCSID 37 and ASCII CCSID 819.  These assumptions may not hold true for all languages.

    Bruce

         H DFTACTGRP
    (*NOACTGRP('QILE'BNDDIR('QC2LE')
         
    DCipher           PR                  EXTPROC('_CIPHER')
         
    D                                 *   VALUE
         D                                 
    *   VALUE
         D                                 
    *   VALUE
         DConvert          PR                  EXTPROC
    ('_XLATEB')
         
    D                                 *   VALUE
         D                                 
    *   VALUE
         D                               10u 0 VALUE
         Dcvthc            PR                  EXTPROC
    ('cvthc')
         
    D                                1
         D                                1
         D                               10i 0 VALUE
         DControls         DS
         D 
    Function                       5i 0 inz(5)
         
    D HashAlg                        1    inz(x'00')
         
    D Sequence                       1    inz(x'00')
         
    D DataLngth                     10i 0 inz(15)
         
    D Unused                         8    inz(*LOVAL)
         
    D HashCtxPtr                      *   inz(%addr(HashWorkArea))
         
    DHashWorkArea     S             96    inz(*LOVAL)
         
    DMsg              S             50
         DReceiverHex      S             16
         DReceiverPtr      S               
    *   inz(%addr(ReceiverHex))
         
    DReceiverChr      S             32
         DSourcePtr        S               
    *   inz(%addr(Msg))
         
    DStartMap         s            256
         DTo819            s            256
         DCCSID1           s             10i 0 inz
    (37)
         
    DST1              s             10i 0 inz(0)
         
    DL1               s             10i 0 inz(%size(StartMap))
         
    DCCSID2           s             10i 0 inz(819)
         
    DST2              s             10i 0 inz(0)
         
    DGCCASN           s             10i 0 inz(0)
         
    DL2               s             10i 0 inz(%size(To819))
         
    DL3               s             10i 0
         DL4               s             10i 0
         DFB               s             12
         D                 ds
         D x                              5i 0
         D LowX                    2      2
         D
    Get all single byte ebcdic hex values
         C     0             
    do        255           x
         C                   
    eval      %subst(StartMap:x+1:1) = LowX
         C                   enddo
         C
    Get conversion table for 819 from 37
         C                   call      
    'QTQCVRT'
         
    C                   parm                    CCSID1
         C                   parm                    ST1
         C                   parm                    StartMap
         C                   parm                    L1
         C                   parm                    CCSID2
         C                   parm                    ST2
         C                   parm                    GCCASN
         C                   parm                    L2
         C                   parm                    To819
         C                   parm                    L3
         C                   parm                    L4
         C                   parm                    FB
         C
    Set message text
         C                   
    eval      Msg 'message digest'
         
    C                   eval      DataLngth = %len(%trimr(Msg))
         
    CNow Change Msg to 819 from 37 using MI
         C                   callp     Convert
    ( %addr(Msg)
         
    C                                     :%addr(To819)
         
    C                                     :%size(Msg))
         
    CGet MD5 for Msg
         C                   callp     Cipher
    ( %addr(ReceiverPtr)
         
    C                                    :%addr(Controls)
         
    C                                    :%addr(SourcePtr))
         
    CConvert nibbles to characters
         C                   callp     cvthc
    ReceiverChr
         C                                   
    :ReceiverHex
         C                                   
    :%size(ReceiverChr))
         
    CDisplay the "proof"
         
    C     ReceiverChr   dsply
         C                   
    eval      *INLR '1'
         
    C                   return 
    All my answers were extracted from the "Big Dummy's Guide to the As400"
    and I take no responsibility for any of them.

    www.code400.com

    Comment


    • #3
      Re: MD5 Checksums

      Thanks Jamie,

      I'll check that out
      Life is a constant struggle against maturity

      Comment


      • #4
        Re: MD5 Checksums

        Originally posted by tonyserzin View Post
        Thanks Jamie,

        I'll check that out
        I believe the solution given will work for a "Message" or character string. I need a MD5 Checksum solution for a database file or even a stream file from the IFS. I am transmitting XML data to the IRS from the iSeries, and the IRS requirement is to provide them with an MD5 Checksum for the file.

        Comment


        • #5
          Re: MD5 Checksums

          Originally posted by Gcoxusa View Post
          I believe the solution given will work for a "Message" or character string. I need a MD5 Checksum solution for a database file or even a stream file from the IFS. I am transmitting XML data to the IRS from the iSeries, and the IRS requirement is to provide them with an MD5 Checksum for the file.
          No idea how you would calculate an MD5 checksum for a database file. I've been using this routine (tip of the hat to Scott Klement) for several years to calculate the MD5 for an IFS stream file

          Code:
          P*--------------------------------------------------     
          P* Procedure name: calculateMD5Checksum                  
          P* Purpose:                                              
          P* Returns:        MD5 checksum value                    
          P* Parameter:      ifsobj => IFS object                  
          P*--------------------------------------------------     
          P calculateMD5Checksum...                                
          P                 B                                      
          D calculateMD5Checksum...                                
          D                 PI            32A                      
          D  streamfile                 5000A   CONST              
          D                                     OPTIONS(*VARSIZE)  
                                                                   
                                                                   
          D* Local fields                                          
          D md5value        S             32A                      
           *                                                       
           * _CIPHER MI builtin.  Allows access to cryptographic   
           *    functions in the licensed internal code.           
           *                                                        
          D cipher          PR                  extproc('_CIPHER')  
          D  receiver                       *   value               
          D  control                        *   value               
          D  source                         *   value               
                                                                     
          D HASH            C                   const(5)            
          D MD5             C                   const(x'00')        
          D SHA1            C                   const(x'01')        
          D ONLY            C                   const(x'00')        
          D FIRST           C                   const(x'01')
          D MIDDLE          C                   const(x'02')
          D FINAL           C                   const(x'03')                                                  
           *                                                
           * These control how the system creates a hash    
           *                                                
          D HashCtrl        DS                  qualified   
          D  Function                      5I 0 inz(HASH)   
          D  HashAlg                       1A   inz(x'00') 
          D  Sequence                      1A   inz(x'00')             
          D  Length                       10I 0 inz                    
          D  Output                        1A   inz(x'00')             
          D  Reserved                      7A   inz(x'00000000000000') 
          D  CtxPtr                         *   inz(%addr(WorkArea))   
                                                                       
          D WorkArea        S            160A   inz(*loval)            
                                                                       
           *                                                           
           * MI builtin to create a hex dump of a spot in memory 
           *                                                        
          D hexdump         PR                  EXTPROC('cvthc')    
          D  output                       40A                       
          D  input                        20A                       
          D  output_len                   10I 0 value               
                                                                    
          D fsstats         ds                  likeds(ds_statvfs)  
          D ReadBuf         S               *                       
          D BufSize         s             10I 0                     
          D Len             s             10I 0                     
          D fd              s             10I 0                     
          D BinHash         S             20A   inz(*loval)         
          D hexHash         S             40A   inz(*loval)         
          D p_BinHash       s               *   inz(%addr(BinHash)) 
                                                                    
                                                                    
           /FREE                                                    
                                                                    
              if (statvfs( %trimr(StreamFile): fsstats ) = -1);
                ReportError();                                       
              endif;                                                 
                                                                     
              BufSize = fsstats.f_bsize * 8;                         
              ReadBuf = %alloc(BufSize);                             
                                                                     
              //                                                     
              // Open the stream file for reading                    
              //                                                     
                                                                     
              fd = open( %trimr(StreamFile) : O_RDONLY+O_LARGEFILE );
              if (fd < 0);                                           
                 dealloc readbuf;                                    
                 ReportError();                                      
              endif;                                                 
                                                                     
              //  Read stream file, calculate hash on each chunk     
              //   of data.                                          
                                                                     
              len = read(fd: readBuf: bufSize);
                  hashCtrl.Sequence = FIRST;                          
                                                                  
              dow (len > 0);                                      
                                                                  
                  hashCtrl.Length = len;                          
                                                                  
                  cipher( %addr(p_BinHash)                        
                        : %addr(HashCtrl)                         
                        : %addr(ReadBuf) );                       
                                                                  
                  len = read(fd: readBuf: bufSize);               
                  hashCtrl.Sequence = MIDDLE;                     
              enddo;                                              
                                                                  
                                                                  
              //  At the very end, call cipher with Sequence=FINAL
              //  to get back the MD5 hash                        
                                                                  
              hashCtrl.Sequence = FINAL;                          
              hashCtrl.Length   = 0;                               
              cipher( %addr(p_BinHash)                             
                : %addr(HashCtrl)                              
                : %addr(ReadBuf) );                            
                                                               
             dealloc readbuf;                                     
             callp close(fd);                                     
                                                               
                                                               
            //  Apps that use MD5 hashes usually want them to be 
            //  hexidecimal and lowercase.  Here, that is done... 
                                                                    
              hexdump( HexHash : BinHash : %size(HexHash) );        
              HexHash = %xlate('ABCDEF': 'abcdef': HexHash);        
              md5value= %subst(hexhash : 1: 32);                    
          
             RETURN md5value;                                       
                                                                    
           /END-FREE                                                
          P calculateMD5Checksum...                                 
          P                 E

          Comment


          • #6
            Re: MD5 Checksums

            This discussion is originally from 2006 -- 10 years ago. Back then, MD5 made a lot of sense. Kind of surprisng to see someone asking for it in 2016, though!

            Having said that, IBM has made the 'openssl' command-line tool available as one of the options for the 5733-SC1 licensed program option. You can use that from PASE or QShell to calcuate an MD5 hash (as well as more modern/secure hashes) very easily.

            Jackc's approach will also work, and is written to be very efficient. (He's using statvfs to determine optimal buffer sizes and everything -- don't see that often.) I would update it to use the QC3CALHA API, however, rather than the old _CIPHER builtin, unless you still need compatibility with old V5R2 or earlier releases. (I hope not!)

            Comment


            • #7
              Hi,
              I'm a newbee to as400 and trying to implement MD5 hash for files present in IFS. @jackc thanks for the code!
              @ScottKlement, thanks for your input, but is there a way to use QC3CALHA API for IFS objects? And if you could provide any information on how to use it from PASE/ QSH, it would be very helpful!

              Comment


              • #8
                I would use the 'openssl' command, as described above. This is ideal for use in PASE. There may be other utilities for PASE available as well, I haven't looked.

                If you had to use QC3CALHA, you would have to write your own code to read the IFS object and feed it into QC3CALHA, and write your own code to print the output in a way that would be readable from QShell or PASE. I don't see any point in writing such a program when its already available at no charge in the other utilities such as openssl.

                Comment

                Working...
                X