Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

convert 7 bit even parity to 7 bit ascii

by bear0053 (Hermit)
on Mar 09, 2004 at 17:12 UTC ( #335194=perlquestion: print w/replies, xml ) Need Help??
bear0053 has asked for the wisdom of the Perl Monks concerning the following question:

fellow monks i have come across a situation that baffeled me. I posted this question a little while ago and only got a few responses. hopefully this post will help me determine a solution

i have an encryption object running from win32 that returns binary data in 7 bit Ascii (verified in .NET). When perl gets the property from the object and puts the value into a scalar it converts it to binary 7 bit ascii "even" parity. when .NET applications read this data from the encryption object it is simply read in as 7 bit ascii. why is this happening and what can i do to force it in as 7 bit ascii?

in .NET C# object returns an EOT Hex 04 in 7 bit ascii

in perl the object returns EOT Hex 84 in 7 bit ascii even parity

can it be forced to 7 bit ascii or can i convert the 7 bit ascii even parity to 7 bit ascii easily?

the convert route is not optimal for performance, the cpu is already hit from the auto conversion to 7 bit ascii even parity.

i am using a Win32::OLE object that works like this:
my $obj = lockpan(); //interacts with a vb6 dll my $enc_data = obj->encryptval($data); //returns binary val $enc_data = '0x' . unpack('H*', $enc_data); //bin -> hex #$enc_data is then written to a sql db as 7 bit ascii even parity
when the code is stored it is stored a 7 bit ascii even parity. so some how perl takes 7 bit ascii and turns it into 7 bit ascii even parity when it writes it to the database. why and how can i stop this? This would be fine if my .net application would read the data from the sql table in as 7 bit ascii even parity and not convert it. But it doesn't. Instead reads the value from the db as 7 bit ascii even parity and then when it is turned into a byte[] gets converted to 8bit and then cannot be decrypted.

Thanks in advance


This was previously asked here by me in a slightly different way: NODE 333378

I managed to solve this problem on the .net side using c# code for converting between formats. It wasn't what i was looking for but it bypasses the perl problem.
//enc_data is a hex formatted string generated by the the COM object m +y .net apps interact with. but in order for the .net app to decrypt t +he hex value returned by the same com object to perl the hex string m +ust be transformed into the appropriate parity format by doing the fo +llowing enc_data = Regex.Replace(enc_data, "^0x", ""); enc_data = FromUnicodeByteArray( hex_to_bin(enc_data) ); //now enc_data contains a value that my .net app can send to the com o +bject for decryption and get back the correct value private static byte[] hex_to_bin ( string s ) { int stringLength = s.Length; if ( (stringLength & 0x1) != 0 ) { Console.WriteLine("not even numbers"); } byte[] b = new byte[ stringLength / 2 ]; for ( int i=0 ,j= 0; i< stringLength; i+= 2,j ++ ) { int high= charToNibble( (s.Substring ( i,1 ).ToCharArr +ay())[0]); int low = charToNibble( (s.Substring(i+1,1).ToCharArra +y())[0] ); b[ j ] = (byte ) ( ( high << 4 ) | low ); } return b; } /** * convert a single char to corresponding nibble. * * @param c char to convert. must be 0-9 a-f A-F, no * spaces, plus or minus signs. * * @return corresponding integer */ private static int charToNibble ( char c ) { if ( '0' <= c && c <= '9' ) { return c - '0' ; } else if ( 'a' <= c && c <= 'f' ) { return c - 'a' + 0xa ; } else if ( 'A' <= c && c <= 'F' ) { return c - 'A' + 0xa ; } else { Console.WriteLine( "Invalid hex character: " + c ) ; return 0; } } private static string FromUnicodeByteArray(byte[] characters) { string constructedString = Encoding.Default.GetString(char +acters); return (constructedString); }

Replies are listed 'Best First'.
Re: convert 7 bit even parity to 7 bit ascii
by iburrell (Chaplain) on Mar 09, 2004 at 19:52 UTC
    What the heck is "7 bit even parity"? What is the real problem you are having? Are you getting bytes with the high bit set when you are expecting only ASCII? Where is data coming from? Perl deals with strings containing 8-bit bytes. It does not do any conversion (unless you are doing Unicode).

    My guess is that this is an encoding problem. 0x84 is DOUBLE LOW-9 QUOTATION MARK in CP1252. CP1252 is a common character set with Windows adds smart quotes and other stuff to Latin-1. My suspicion is that the data you are decoding is a string containing a smart quote. If you want 7-bit ASCII, then you will need to strip or convert the 8-bit bytes.

      ok here it is:
      a com object returns a binary string to perl in ascii 7 bit (8 bit for popular terms)

      perl converts this binary to ascii 7 bit even parity by default when the com objects return value is set to a scalar.
      binary data from com object looks something like this:
      79a30bf0ac64fc0e469f0568562e43e53f89a3f46f7437d44d96dcd5087b20056df7fcb07485f0c0 (7 bit ascii even parity)

      the same com object used in .net or asp returns binary value in ascii 7 bit (8bit for popular term)

      i can't have this happen becuase the two systems won't decrypt the same value correctly through the com object.

      some Hex values in ascii 7 bit even parity represent chars differently compared to the Hex representation of the same character in 7 bit ascii

      I need to find a way for perl not to transfer the binary string returned from the com object into 7 bit even parity. this changes the hex values thus cannot be converted correctly by the .net apps that read in the perl stored values.

        The easy was to convert from data+parity to data is to & your input with 0x7F. Note that this destroys any benifit the parity might have (in this case, none).

        If you've got a bunch of data in $data, and want to strip the high bit, try $data = chr(0x7F) x length($data);.

        Note that I suspect your actual problem has little to do with parity vs non-parity, but rather with utf-8 encoding. I know of nowhere in perl that cares about parity.

        Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).

        What is the data from the COM object supposed to look like? Are you certain it is 7-bit ASCII with no bytes with the high bit set? In other words, with no extended characters in it.

        Perl is almost certainly not converting to "7-bit even parity" because it doesn't know about any such thing. The only place I have seen "even parity" used is with modems. Not to mention that the string you presented is not even partity.

        That string is not in UTF-8 but it is still likely an encoding issue. Win32::OLE does have an option to set the code page for translating Unicode strings to Perl strings. You might want to check its value or explicitly set it the code page.

        why was this node voted down???

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://335194]
Approved by arden
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (2)
As of 2018-04-21 08:54 GMT
Find Nodes?
    Voting Booth?