numpy randint() to generate bytes

I have to make a stream cipher that takes in input a byte generator (randint function by default). I tried to implement it in this way but I don’t want to have at the output the str() representation, I want the bytes one, so b'x.......').

I read that bytes() with a list of integers gives the str representation, so if I return crypted in the crypting_fn, with a for cycle to pass to the bytes() only one int at a time, will I solve my “problem”? If not, can you please explain to me how can I do that?

import numpy as np
import numpy.random


class SC(object):

    def __init__(self, key, prng=None, **kwargs):

        if prng is None:
            seed=None
            rs = np.random.RandomState(seed)
            def gen(seed):
                rs = np.random.RandomState(seed)
                while True:

                    yield rs.randint(0,255)

            self.prng = rs.randint(0, 255)

        else:
            self.prng = prng(key, **kwargs)


    def encrypt(self, plaintext):
        return self.crypting_fn(plaintext)

    def decrypt(self, ciphertext):
        return self.crypting_fn(ciphertext)

    def crypting_fn(self, text):

            crypted=bytes([b^s for b, s in zip(text, range(self.prng))])
            return crypted


message = 'hello world!'
key = 0x012345678

a = SC(key)
b = SC(key)

plaintextA = message.encode('utf-8')
ciphertext = a.encrypt(plaintextA)
plaintextB = b.decrypt(ciphertext)

print(plaintextA)
print(ciphertext)
print(plaintextB)

The output Is:

b'hello world!'
b'hdnok%qhzen*'
b'hello world!'

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Your use of the PRNG is borked; instead of generating a stream of bytes, you generate a single byte and your keystream is just 0, 1, 2, 3… up until you hit the random byte (so when the byte is small, you don’t even have enough to encrypt the entire input).

Fix your code to make self.prng a keystream generator, not a single random byte, and use it as such, and you’ll get something that looks like what you want:

import numpy as np
import numpy.random


class SC(object):
    def __init__(self, key, prng=None, **kwargs):
        if prng is None:
            def gen(seed):
                rs = np.random.RandomState(seed)
                while True:
                    yield rs.randint(0, 255)

            self.prng = gen(key)  # Seed with provided "key", not None (which seeds from system random)
        else:
            # Without knowing what prng should be, I can't be sure this line is correct
            # This is what you'd want if calling prng produced an iterator using the keystream
            self.prng = prng(key, **kwargs)

    def encrypt(self, plaintext):
        return self.crypting_fn(plaintext)

    def decrypt(self, ciphertext):
        return self.crypting_fn(ciphertext)

    def crypting_fn(self, text):
        crypted=bytes([b^s for b, s in zip(text, self.prng)])
        return crypted

message = 'hello world!'
key = 0x012345678


a = SC(key)
b = SC(key)

plaintextA = message.encode('utf-8')
ciphertext = a.encrypt(plaintextA)
plaintextB = b.decrypt(ciphertext)

print(plaintextA)
print(ciphertext)
print(plaintextB)

which outputs:

b'hello world!'
b'+x9fxc8xecxd4\xacxf6xaexbax9cxeb'
b'hello world!'

Try it online!


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x