ibmi-brunch-learn

Announcement

Collapse
No announcement yet.

Encryption/Decryption between IBM i and the ASCII world

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

  • Encryption/Decryption between IBM i and the ASCII world

    I have a project where I have created a web service on the i which will be consumed by a PHP program also on the i. Here is the problem. The PHP program needs to send the customers Social Security Number with the call to the web service, but before it sends it it will encrypt the SSN using AES algorithm and then encode that in HEX before sending. The problem is that when I try to decrypt the SSN I get an error saying that the item was not encrypted.

    My RPGLE program first translates the ASCII Hex to EBCDIC hex and then converts the hex to the characters and they attempts to decrypt the SSN.

    To test, I wrote a program in RPGLE to encrypt, using AES, the SSN using the same key and IV as the the PHP program used and the first thing that I noticed is that the characters in the two encrypted fields, one from the RPGLE program and the other from the PHP program, do not match. I can't figure out whether the problem is in the details and setting of the encryption algorithms on each side or what.

    I can't seam to find any information on the internet specifically addressing decrypting something on the IBM i that was encrypted in the ASCII world and sent to the IBM i.

    Thanks in advance for any help or direction.

  • #2
    Have you tried decrypting the ASCII? It would make sense to me that you would not want to convert to EBCDIC before decrypting although I'm definitely not an expert on this subject.

    Comment


    • Douggie
      Douggie commented
      Editing a comment
      Once the Social Sec number is encrypted on the PHP(ASCII) side it is then encoded to ASCII Hex which is different than EBCDIC Hex. When my RPG program receives it is is in ASCII hex. Then when I convert it to EBCDIC Hex and then convert that into characters those characters match the characters in the ASCII encypted Social Sec number field on the PHP side. For example if the PHP ASCII encrypted Social Sec number is 2■¶\_ê`u ùó ■q ■, after it is encoded to ASCII Hex, sent through the web service to my RPG program, converted to EBCDIC hex and finally converted to characters it is also 2■¶\_ê`u ùó ■q ■. The problem is it won't decrypt and when I tested the encrypting in an RPG program with the same key and IV the characters are not 2■¶\_ê`u ùó ■q ■. In other words the two programs (PHP - ASCII RPG - EBCDIC) come up with two different character sets even though they are both using AES algorithm and the same key and IV.

  • #3
    I agree with Scott but would add that it is possible (depending on how your RPG interacts with PHP that the value is being converted to EBCDIC before the RPG code sees it.

    Why not modify the code temporarily so that the SIN is passed unencrypted so that you can more readily compare the values. Always good idea to break the process down into pieces when you have this kind of problem.

    Comment


    • Douggie
      Douggie commented
      Editing a comment
      If I try this whole thing with out encryption the plain text Social Sec number comes into RPG program correctly. In other words if the PHP program sends 555111234 the RPG program receives 555111234.

  • #4
    OK. Did you need to do any conversion on the RPG side or was the SIN directly readable? If so then the Apache config is doing an ASCII -> EBCDIC conversion.

    If that is the case then you need to start by converting the hex to ASCII (not to EBCDIC). Then decrypt the ASCII and then finally convert the resulting ASCII to EBCDIC.

    Comment


    • Douggie
      Douggie commented
      Editing a comment
      I see what you are saying but How do you convert ASCII Hex to ASCII characters on the IBM i within an RPGLE program. Also I don't think the IBM i built in encrypt/decript functions would be able to deal with ASCII data.

  • #5
    It would have to be custom code - I can't think of a way to do it via any regular APIs. It is not a difficult job. something like this should do it. NOT TESTED

    Code:
    dcl-ds  convertStuff;
       values  char(16)  Inz('0123456789ABCDEF');
       value  char(1)  Dim(16)  overlay(values);
    
       resultsASCII  char(nn);  // However long the ASCII string should be
       results  int(3)  dim(nn)  overlay(resultsASCII);
    end-ds;
    
    // Loop through the input hex values 
    For x = 1 to whatever by 2;
      index += 1;
      results ( index ) =  ( (  %Lookup( inputHex(x) : values  ) - 1 )   * 16 ) + (  %Lookup( inputHex( x + 1 ) : values  ) - 1 );
    EndFor;

    Comment


    • #6
      That said - I can't help feeling there has to be an easier way of doing this. Not really clear why given that this is an internal function you need to encrypt in the first place. Does it have to be a web service? The PHP could sit on the end of a dataqueue for example.

      Comment


      • #7
        You mention that your social security number starts as "2■¶\_ê`u ùó ■q ■". I assume what you're showing us is the raw value of the encrypted number *if* those raw byte values were viewed as ASCII text. (Which it should never be, as it is not text.)

        You see... bytes can be used for many things. Yes, they can be used to represent text, and yes there are many different encodings and code pages that are for text and stored in bytes. However, these are NOT the only things bytes can do. If you look at an image (jpeg, png, gif, etc) you'll see that they are not made up of text characters. If you look at sound files (wav, mp3, ogg, etc) they are not text. If you look at videos.... I could go on for a very long time... you see what I'm saying, though? Bytes don't always represent textual values.

        Instead of looking at "2■¶\_ê`u ùó ■q ■" as text, look at the actual values of the bytes. Your goal should be to get the exact same byte values in your RPG program.

        The problem as I understand it is that when you send the bytes to the http server, it is automatically running them through an ASCII to EBCDIC conversion -- which isn't good, since they are not text. This changes the byte values, and therefore the decryption may fail (or worse, might succeed but result in the wrong value.)

        One way to work around a problem like that is to convert them to hex. This is a little hard to explain because you're using the word "hex" in your description but I *think* you're using it differently. When I say "convert it to hex", I mean create text characters from the raw byte values. So if your data is 16 bytes of encrypted data, you should create a hex string that is 32 bytes long. It will be text characters that look like "a4b2c9d15532"... etc... it will be human readable characters in ASCII that represent the values of the raw bytes, but will be in ASCII characters. When that is sent to the IBM i, they will be translated to EBCDIC, but will be the exact same string if viewed by a human being. You would then convert this back to raw bytes (using a function like cvtch, etc) and then decrypt it. It should now decrypt successfully -- the result of the decryption will still be in ASCII if the source was ASCII, so your final step will be to convert it to EBCDIC.

        Instead of converting the byte values to a hex text string, another approach might be to convert them to base64 text. Its the same concept, but will result in fewer bytes. If your data is always only 16 bytes to begin with (so 32 bytes after conversion) its probably not worth bothering with base64 since the data is so small, but when working with larger pieces of data this can make a big difference.

        Comment


        • Douggie
          Douggie commented
          Editing a comment
          Scott I really appreciate your comments. I think however that I may have asked my question wrong in the first place. Here is whats happening. The PHP programmer is using the AES algorithm to encrypt a Social Security number he is then encoding this to hex and then sending it through my web service to my program. To test my side(the RPG side) I used Postman to call my web service and entered an ASCII Hex encoded(32 long), AES encrypted Social Security Number(16 long). In my RPGLE web service program I take the ASCII Hex encoded AES encrypted Social Security Number and I convert it to EBCDIC Hex. Then I convert the EBCDIC Hex to character. I then decrypt the resulting character field back to the original Social Security Number and all of that worked perfectly. The problem we are having is when the PHP programmer tries to encrypt the Social Security Number using AES and the same Mode, key, IV and block length, he is coming up with a different encrypted value than I do when I use the same AES encrypting with the same Key and IV and Mod and block length on the IBM i. Consequently when he Hex encodes it and send it to me through my web service and I convert it to EBCDIC Hex and then decrypt it with the same Mode,Key, IV, and block length, it fails. In other words we can't figure out why, when using the same encrypting algorithm(AES) and all the same parameters, he in PHP(ASCII) and me in RPG(EBCDIC), we come up with different encrypted values. I hope all of this make sense.

      • #8
        Yup - Scott for the win with the simpler way! I had it fixed in my head that cvtch would convert to EBCDIC but of course it is just raw binary and in fact will actually be the ASCII code points.

        I'm tempted to edit my hack approach but the base technique may be useful for other purposes so I'll swallow my pride and leave it there.

        Comment

        Working...
        X