Reverse byte order of an 8-bit string from big-endian to little-endian

Hi,

I have a situation where I write a character stream to a file. The file content gets signed and the signature is sent to a service provider together with the file content.

The signing is done using openssl.

This works perfectly on a dev PC, which is runnning Windows and has a little-endian architecture.

The problem is as soon as I do this on the server, which has a big-endian architecture, the signed value is incorrect according to the service provider.

The content is signed using RSA SHA256 with PSS padding.

I've had a look at $nconvert, $sconvert, etc., but can't get to a solution.

Is there a way to convert the 8-bit character stream to little-endian format on the big-endian server using Cache or some other command?

  • 0
  • 0
  • 1347
  • 7
  • 1

Answers

To convert to Big Endian and Little Endian you can use $zcvt:

>zzdump $zcvt("12","O","UnicodeBig")
0000: 00 31 00 32                                             .1.2
>zzdump $zcvt("12","O","UnicodeLittle")
0000: 31 00 32 00                                             1.2.

Comments

Are you sure that this problem is due to endian? A byte stream does not in itself have a byte order; multi-byte data structures do, such as Unicode characters encoded as UTF-16. As for the signature itself, I would expect its encoding to be specified in a portable manner.

Is it possible that line endings are getting changed?

Thank you. I've also read up a bit and 8-bit contents will not be bothered by endianness.

You may have a point with the line endings. The value that is gettinhg encrypted has two \r\n in it - this works on Windows. I will try and change it to just \n for the Solaris server and see if that makes a difference.

Do you know if openssl uses the line-end to know up the where to sign and does it line by line, or does it include the line endings in the value that should be signed?

Apologies for all these questions. I am not very familiar with encryption, signing, openssl, etc.

 

It depends on the signing method.  I'd try to sign a stream without new lines at all.

Do you know if openssl uses the line-end to know up the where to sign and does it line by line, or does it include the line endings in the value that should be signed?

openssl signs incoming byte stream, not a character stream, so there's no distinction.

I need to have the newlines in. The only reason why files are used, is because Cache does not support the RSA PSS padding required to sign the web-service messages I need to send. I then write what needs to be signed to a file and use opensl to sign it.

The value that needs to be signed is:
X-Date:CurrentDate\r\n
x-Client-Key:KeyValue\r\n
MessageBody

See: https://community.intersystems.com/post/sha256-signing-rsa-pss-padding

So it builds up the file to sign using the values and $char(13,10).
Then signs it using SHA256 and RSA PSS padding into a new file.
The contents of the new file is then base64 encoded.
The base64 encoded value is then sent together with the file contents, date and Client Key.

This works on Windows, hence the question about openssl and the newlines.

Is the base64 encoding a possivle culprit?

Do you sign \r\n on Solaris? In your previous post you wrote that you need to sign:

{Date}{newline}{Password}{newline}{etc}{Message Body}

Maybe {newline} can only be \r\n?

 

Also, compare (using hex compare tool) {Message Body} you sign and {Message Body} you actually send. It seems like in your case they should be identical (that is not always the case).

When writing to the filecharacterstream, I use Write and not Writeline, as the string is built up with the newlines and I use $char(13,10) specifically.

I just compared the files between Windows and Solaris, and the Solaris files are two bytes smaller - so probably the \r($c(13)) getting dropped.

It seems like %Stream.FileCharacter does not use the LineTerminator that was set in the output file. Even when using Write and adding $char(13,10), it converts it to the OS setting.

I resolved this line terminator issue by using %Stream.FileBinary and converting my data to UTF8 prior to writing it to the binary stream.