How to convert bytes to numbers into a string of characters? (symbolic representation of a number)

How easy it is to convert a number, for example. 0x616263, equivalent 6382179in base 10, to a string by dividing the number by consecutive bytes? So, the above example should convert to 'abc'.

I experimented with Array.pack , but can't figure out how to get it to convert more than one byte to a number, for example. [0x616263].pack("C*")returns 'c'. I also tried 0x616263.to_s(256), but this throws an ArgumentError: invalid value. I think he needs some kind of coding information?

(Note. The other data types in the type packet Nwork with the above example, but only because it fits within 4 bytes, therefore, for example, [0x616263646566].pack("N")gives cdef, not abcdef)

This question is vaguely similar to this , but not really. Also, I kind of figured out how to get the hexadecimal representation string from a character string using "abcde".unpack("c*").map{|c| c.to_s(16)}.join(""), which gives '6162636465'. I basically want to go back.

I do not think this is an XY problem , but in case this is the case - I am trying to convert the number I "ve decoded from RSA to a string of characters.

Thanks for any help. I'm not too experienced with Ruby. I would also be interested in a Python solution (for fun), but I don't know if there is a right to add tags for two separate programming languages ​​to this question.

+4
source share
3 answers

To convert a single number 0x00616263in the 3 characters, what you really need to do is to divide them into three numbers: 0x00000061, 0x00000062and 0x00000063.

For the last number, zero zero digits are already in the right place. But for the other two you need to do a bit-break using >> 16and >> 8respectively.

Then use bitwise and to get rid of other numbers:

num1 = (0x616263 >> 16) & 0xFF
num2 = (0x616263 >> 8) & 0xFF
num3 = 0x616263 & 0xFF

:

char1 = ((0x616263 >> 16) & 0xFF).chr
char2 = ((0x616263 >> 8) & 0xFF).chr
char3 = (0x616263 & 0xFF).chr

, Ruby-esque. , Ruby , .

+4

64-

2 ** 64 (8 ), :

  • " " 8

[0x616263].pack('Q>').sub(/\x00+/,'')
# "abc"
[0x616263646566].pack('Q>').sub(/\x00+/,'')
# "abcdef"

Python 2 3

Python pack , . decode() to

:
import struct
import re
print(re.sub('\x00', '', struct.pack(">Q", 0x616263646566).decode()))
# abcdef
print(re.sub('\x00', '', struct.pack(">Q", 0x616263).decode()))
# abc

gsub

8 , . , 10 (, "\ t" ):

def decode(int)
  if int < 2**64
    [int].pack('Q>').sub(/\x00+/, '')
  else
    nhex = int.to_s(16)
    nhex = '0' + nhex if nhex.size.odd?
    nhex.gsub(/../) { |hh| hh.to_i(16).chr }
  end
end

puts decode(0x616263) == 'abc'
# true
puts decode(0x616263646566) == 'abcdef'
# true
puts decode(0x0961) == "\ta"
# true
puts decode(0x546869732073656e74656e63652069732077617920746f6f206c6f6e6720666f7220616e20496e743634)
# This sentence is way too long for an Int64

, :

def encode(str)
  str.reverse.each_byte.with_index.map { |b, i| b * 256**i }.inject(:+)
end

, RSA .

. @Nathan, :

def decode(int)
  a = []
  while int>0
    a << (int & 0xFF)
    int >>= 8
  end
  a.reverse.pack('C*')
end

fruity, , gsub.

+3

Now I'm skating with this:

n = 0x616263

nhex = n.to_s(16)
nhexarr = nhex.scan(/.{1,2}/)
nhexarr = nhexarr.map {|e| e.to_i(16)}

out = nhexarr.pack("C*")

But he was hoping for a concise / inline way to do this, so I will leave this answer unacceptable for now.

+2
source

Source: https://habr.com/ru/post/1673088/


All Articles