2
votes

I'm trying to write a Cobol program with the following interface:

Objective

Receives a clear encryption key and a clear text and returns a cyphered text using the 3DES algorithm.

Inputs:

  • CLEAR_KEY: A 32-character string of hexadecimal characters to be used as the encryption key.
  • CLEAR_TEXT: A 16-character string.

Output:

  • CYPHERED_TEXT: A 16-character string.

I have access to DB2 and ICSF callable services.

I tried these three approaches:

Using CSNBSYE

77 CSNBSYE                  PIC X(7) VALUE 'CSNBSYE'.
01 CSNBSYE-PARAMETERS.
   02 RETURN-CODE           PIC 9(8) COMP.
   02 REASON-CODE           PIC 9(8) COMP.
   02 EXIT-DATA-LENGTH      PIC 9(8) COMP.
   02 EXIT-DATA             PIC X(32).
   02 RULE-ARRAY-COUNT      PIC 9(8) COMP.
   02 RULE-ARRAY            PIC X(8).
   02 KEY-IDENTIFIER-LENGTH PIC 9(8) COMP.
   02 KEY-IDENTIFIER        PIC X(32).
   02 KEY-PARMS-LENGTH      PIC 9(8) COMP.
   02 KEY-PARMS             PIC X(32).
   02 BLOCK-SIZE            PIC 9(8) COMP.
   02 INIT-VECTOR-LENGTH    PIC 9(8) COMP.
   02 INIT-VECTOR           PIC X(8).
   02 CHAIN-DATA-LENGTH     PIC 9(8) COMP.
   02 CHAIN-DATA            PIC X(16).
   02 CLEAR-TEXT-LENGTH     PIC 9(8) COMP.
   02 CLEAR-TEXT            PIC X(16).
   02 CYPHERED-TEXT-LENGTH  PIC 9(8) COMP.
   02 CYPHERED-TEXT         PIC X(16).
   02 OPTIONAL-DATA-LENGTH  PIC 9(8) COMP.
   02 OPTIONAL-DATA         PIC X(32).

INITIALIZE CSNBSYE-PARAMETERS.

MOVE 1                                  TO RULE-ARRAY-COUNT.
MOVE 'DES     '                         TO RULE-ARRAY.
MOVE 16                                 TO KEY-IDENTIFIER-LENGTH.
MOVE '2DF65FD88EA9E17E3C66950387F91DE2' TO KEY-IDENTIFIER.
MOVE 8                                  TO BLOCK-SIZE
                                           INIT-VECTOR-LENGTH.
MOVE ALL ZEROS                          TO INIT-VECTOR.
MOVE 16                                 TO CHAIN-DATA-LENGTH.
MOVE LOW-VALUES                         TO CHAIN-DATA.
MOVE 16                                 TO CLEAR-TEXT-LENGTH
                                           CYPHERED-TEXT-LENGTH.
MOVE ALL ZEROS                          TO CLEAR-TEXT.

CALL CSNBSYE USING RETURN-CODE,
                   REASON-CODE,           
                   EXIT-DATA-LENGTH,      
                   EXIT-DATA,             
                   RULE-ARRAY-COUNT,      
                   RULE-ARRAY,            
                   KEY-IDENTIFIER-LENGTH, 
                   KEY-IDENTIFIER,        
                   KEY-PARMS-LENGTH,      
                   KEY-PARMS,             
                   BLOCK-SIZE,           
                   INIT-VECTOR-LENGTH,    
                   INIT-VECTOR,           
                   CHAIN-DATA-LENGTH,    
                   CHAIN-DATA,            
                   CLEAR-TEXT-LENGTH,     
                   CLEAR-TEXT,            
                   CYPHERED-TEXT-LENGTH,  
                   CYPHERED-TEXT,         
                   OPTIONAL-DATA-LENGTH,  
                   OPTIONAL-DATA.

Using CSNBECO

77 CSNBECO                  PIC X(7) VALUE 'CSNBECO'.
01 CSNBECO-PARAMETERS.
   02 RETURN-CODE           PIC 9(8) COMP.
   02 REASON-CODE           PIC 9(8) COMP.
   02 EXIT-DATA-LENGTH      PIC 9(8) COMP.
   02 EXIT-DATA             PIC X(32).
   02 CLEAR-KEY             PIC X(32).
   02 CLEAR-TEXT            PIC X(16).
   02 CYPHERED-TEXT         PIC X(16).

INITIALIZE CSNBECO-PARAMETERS.

MOVE '2DF65FD88EA9E17E3C66950387F91DE2' TO CLEAR-KEY.
MOVE ALL ZEROS                          TO CLEAR-TEXT.

CALL CSNBSYE USING RETURN-CODE,
                   REASON-CODE,           
                   EXIT-DATA-LENGTH,      
                   EXIT-DATA,             
                   CLEAR-KEY,          
                   CLEAR-TEXT,            
                   CYPHERED-TEXT.

Using DB2's ENCRYPT_TDES

01 WS.
   02 CLEAR-TEXT            PIC X(16).
   02 CYPHERED-TEXT         PIC X(16).

   MOVE ALL ZEROS TO CLEAR-TEXT.

   EXEC SQL
        SELECT ENCRYPT_TDES(:CLEAR-TEXT, '2DF65FD88EA9E17E3C66950387F91DE2')
        INTO   :CYPHERED-TEXT
        FROM   SYSIBM.SYSDUMMY1
   END-EXEC.

But none of these approaches returned the result I expected. The result I'm expecting is the same obtained from testing in this website: http://tripledes.online-domain-tools.com/ , with the following data:

Input type: Text

Input Text: 0000000000000000 (HEX)

Function: 3DES

Mode: CBC

Key: 2DF65FD88EA9E17E3C66950387F91DE2 (HEX)

Init Vector: 00 00 00 00 00 00 00 00

Encrypt!

Encrypted Text (result): 87 30 e1 ef 98 3d f2 b4 (HEX) | . 0 á ï = ò ´ (STRING)

My question is: how can I obtain the result above in a Cobol program, using any of the tools provided by IBM?

Thank you!

2

2 Answers

5
votes

Most of your confusion seems to come from the fact that you mistake hex-strings for byte-values. E.g. you think you pass CSNBSYE a 16-byte key of '2DF65FD88EA9E17E3C66950387F91DE2'X while you are passing a 32-byte string starting with 'F2C4C6F6F5C6C429F8'X - i.e. the EBCDIC-representation of the characters you passed. To use actual hex-representation of the byte-values you have to append a X after the closing apostrophe of your literals.

Also note that moving ZERO into a PIC X item resulte in 'F0'X while using LOW-VALUE results in '00'.

Another point is that you seem to be comparing the 3DES results from the website with the DES results from CSNBECO or CSNBSYE - but they are different ciphers and so should return different results.

Last but not least ENCRYPT_TDES: this function is using 3DES but it does not accept a plain key. Instead the second argument is a password that is hashed to obtain the final encryption key.

So of your investigated alternatives it seems that only CSNBSYE is compatible with your requirements but you have to study its exact parameter-formats and usage.

-1
votes

I did it! The code was the following:

77 CT-cENC-ROUTINE                  PIC X(7) VALUE 'CSNBSYE'.
05 WS-ENC.                                        
   10 WS-ENC-nRETURN-CODE           PIC 9(8) COMP.
   10 WS-ENC-nREASON-CODE           PIC 9(8) COMP.
   10 WS-ENC-nEXIT-DATA-LENGTH      PIC 9(8) COMP.
   10 WS-ENC-cEXIT-DATA             PIC X(4).     
   10 WS-ENC-nRULE-ARRAY-COUNT      PIC 9(8) COMP.
   10 WS-ENC-RULE-ARRAY.                          
      15 WS-ENC-cRULE-ALGO          PIC X(8).     
   10 WS-ENC-cKEY-IDENT-LENGTH      PIC 9(8) COMP.
   10 WS-ENC-cKEY-IDENT             PIC X(32).    
   10 WS-ENC-nKEY-PARMS-LENGTH      PIC 9(8) COMP.
   10 WS-ENC-nKEY-PARMS             PIC X(64).    
   10 WS-ENC-nBLOCK-SIZE            PIC 9(8) COMP.
   10 WS-ENC-nINIT-VECTOR-LENGTH    PIC 9(8) COMP.
   10 WS-ENC-cINIT-VECTOR           PIC X(16).    
   10 WS-ENC-nCHAIN-DATA-LENGTH     PIC 9(8) COMP.
   10 WS-ENC-cCHAIN-DATA            PIC X(32).    
   10 WS-ENC-nCLEAR-TEXT-LENGTH     PIC 9(8) COMP.
   10 WS-ENC-cCLEAR-TEXT            PIC X(16).    
   10 WS-ENC-nCYPHER-TEXT-LENGTH    PIC 9(8) COMP.
   10 WS-ENC-cCYPHER-TEXT           PIC X(16).    
   10 WS-ENC-nOPTIONAL-DATA-LENGTH  PIC 9(8) COMP.
   10 WS-ENC-cOPTIONAL-DATA         PIC X(32).    

INITIALIZE WS-ENC                                          

MOVE 1                          TO WS-ENC-nRULE-ARRAY-COUNT
MOVE 'DES'                      TO WS-ENC-cRULE-ALGO       

EXEC SQL                                                 
     SELECT VARCHAR_BIT_FORMAT('2DF65FD88EA9E17E3C66950387F91DE2')
     INTO   :WS-ENC-cKEY-IDENT                                
     FROM   SYSIBM.SYSDUMMY1                             
END-EXEC       

MOVE 16                         TO WS-ENC-cKEY-IDENT-LENGTH   
MOVE 8                          TO WS-ENC-nBLOCK-SIZE                                          
                                   WS-ENC-nINIT-VECTOR-LENGTH
MOVE ALL ZEROS                  TO WS-ENC-cINIT-VECTOR       

MOVE LENGTH OF WS-ENC-cCHAIN-DATA                            
                                TO WS-ENC-nCHAIN-DATA-LENGTH 
MOVE LOW-VALUES                 TO WS-ENC-cCHAIN-DATA        

MOVE LENGTH OF WS-ENC-cCLEAR-TEXT                            
                                TO WS-ENC-nCLEAR-TEXT-LENGTH 
                                   WS-ENC-nCYPHER-TEXT-LENGTH
MOVE '0000000000000000'         TO WS-ENC-cCLEAR-TEXT        

CALL CT-cENC-ROUTINE USING WS-ENC-nRETURN-CODE,         
                           WS-ENC-nREASON-CODE,         
                           WS-ENC-nEXIT-DATA-LENGTH,    
                           WS-ENC-cEXIT-DATA,           
                           WS-ENC-nRULE-ARRAY-COUNT,    
                           WS-ENC-RULE-ARRAY,           
                           WS-ENC-cKEY-IDENT-LENGTH,    
                           WS-ENC-cKEY-IDENT,           
                           WS-ENC-nKEY-PARMS-LENGTH,    
                           WS-ENC-nKEY-PARMS,           
                           WS-ENC-nBLOCK-SIZE,          
                           WS-ENC-nINIT-VECTOR-LENGTH,  
                           WS-ENC-cINIT-VECTOR,         
                           WS-ENC-nCHAIN-DATA-LENGTH,   
                           WS-ENC-cCHAIN-DATA,          
                           WS-ENC-nCLEAR-TEXT-LENGTH,   
                           WS-ENC-cCLEAR-TEXT,          
                           WS-ENC-nCYPHER-TEXT-LENGTH,  
                           WS-ENC-cCYPHER-TEXT          
                           WS-ENC-nOPTIONAL-DATA-LENGTH,
                           WS-ENC-cOPTIONAL-DATA    

So, what was missing was: 1) Convert the 32-byte string of hexadecimal characters to it's 16-byte string representation. 2) The chain data size was made to be 32.