2019-01-05 17:50:09

So try and run this code for me please:

def trashy(message, move):
  message2 = ""
  for i in message:
    x = ord(i)
    message2= message2+chr(x+move)
  print(message2)

numbermove = input("How much do you want to shift your letters by?")
something = input("What is your message?")
trashy(something, int(numbermove))

Does it work for you? It doesn't for me... All it does is asks me 2 questions and then promptly screws off. So why? I ran it from the run  dialog... and pasting it in the console didn't even get it do ask me for input. I have also tried to do the return statement, which looked like this:

def trashy(message, move):
  message2 = ""
  for i in message:
    x = ord(i)
    message2= message2+chr(x+move)
  return message2

numbermove = input("How much do you want to shift your letters by?")
something = input("What is your message?")
something2 = trashy(something, int(numbermove))
print(something2)

It doesn't work for me, it just sits there when I paste it into the prompt, and running it from the command line only asks for input and promptly exits.
I have checked my nvda speech viewer, I have checked my nvda history, but it's like the program crashes before it reaches the print statement.
Thing is, the python prompt doesn't complain when I paste in the code. It just sits there, silently, not even asking me for input.
So what did I break? How can I fix it? More importantly, how can I keep that from happening again? I can't code and not see the results of my program.

2019-01-06 13:33:37

Hi,

well, exchange input against raw_input and it will actually work.

D:\>python run.py
How much do you want to shift your letters by?2
What is your message?hello
jgnnq

Best Regards.
Hijacker

2019-01-06 16:53:16

So here's my code, which is still broken:
def trashy(message, move):
  message2 = ""
  for i in message:
    x = ord(i)
    message2= message2+chr(x+move)
  print(message2)

print("How much do you want to shift your letters by?")
numbermove = int(raw_input())
print("What is your message?")
something = raw_input()
trashy(something, numbermove)

What's wrong with it this time? The raw_input function has been renamed to input in python 3, so why didn't it work earlier?

2019-01-06 23:38:30 (edited by cartertemm 2019-01-06 23:41:08)

OP said he was using python 3 in a previous topic. raw_input is a python 2 thing, replaced with input in any later version.

Original script works fine for me. Never run interactive applications from the run dialog, as the run dialog is not at all meant for displaying output.
Open up cmd, cd documents\python
py -3 shifter.py
How much do you want to shift your letters by?
2
What is your message?
hi
jk

Also as an afterthought, you might want to add support for an Ascii range. It seems as if your wanting to shift letters and letters only, as in the Caesar cipher. right now your performing a rough form of byte rotation, and even that fails to some extent.

2019-01-07 01:32:20

Hi,

@CarterTemm: yeah, didn't know that topic and thus didn't know this Python 3 thingy. I got both versions installed and tried with Python 2, which didn't work, thats why i replaced it and voilla.
Didn't mention the ascii range though, this code looked like some tutorial or class homework thing and I guessed he'll have to cover this topic next. Thanks for clarifying anyway smile.

Best Regards.
Hijacker

2019-01-07 03:28:49 (edited by amerikranian 2019-01-07 03:52:24)

Okay, I was an idiot. I forgot to review the screen. Thanks post 4.
A question: Yes: I was aiming at a Caesar cipher. What do you mean by it failing? Can you show me an example of it failing and give me a tip at how to fix it? Don't give the code, I don't want that. Give a general nudge so I can have a chance of discovering the thing myself, please.
Can you also explain supporting asky and bite rotation? As in what it is and why it's not an actual decryption and a simple rotation of bites, as you called them?

Again, I'm sorry. I wish I'd know more then what I do now, but I think that can be said for all of us, heh.

2019-01-07 06:33:21 (edited by Ethin 2019-01-07 06:39:10)

The ASCII thing can be explained simply with an example, as below:
How much do you want to shift your letters by?
35
What is your message?
hi
‹Œ
There's your problem. The problem with this code is that you don't enforce an ASCII range limit; so someone could, say, shift by 3500 characters and result in a strange, weird UTF8 mess. Even worse, you can shift by negatives:
How much do you want to shift your letters by?
-200
What is your message?
hi
Traceback (most recent call last):
  File "t.py", line 11, in <module>
    trashy(something, numbermove)
  File "t.py", line 5, in trashy
    message2= message2+chr(x+move)
ValueError: chr() arg not in range(0x110000)
The above value error is Pythons built-in Unicode enforcement; values converted with chr() must be within the range 0-1114112 (0x0-0x110000). However, that range, for the purposes of this cipher project, is far greater than what you need; a cipher that wraps around after it has reached the end of the ASCII table is fine enough. To solve this problem, determine if the ordinal of the character your scanning (and moving) results in an ordinal either greater than 126 or less than 32 (to avoid control characters.)
As for your other question: a byte rotation (also known as a circular shift) is a (easy to break, but fine for this purpose) algorithm where you have a list of (in this case) bytes (which, in the usual case, is in a tuple, but a string will suffice). In the algorithm, you take all the entries (bytes) in that tuple (string) and rearrange them such that the last entry (byte) in the tuple (string) is moved (rotated or shifted) to the first position and all other entries (bytes) are moved into the next sequential position in the tuple (string). So, take the string "hello". If you perform a circular shift on that string, o is moved (shifted) to the position of h, and h, e, l, and l are moved (shifted) such that they fill the remaining space of the string, thereby creating the string "ohell".
To aid you, I'll leave you with the following nugget of info: a circular shift (byte rotation) is a permutation s of the n bytes in the string such that either the sigma of i is identical to (i+1)%n, for all bytes i=1, n; or the sigma of i is identical to (i-1)%n, for all bytes i=1, n. The algorithm is repetitive, which I'll demonstrate twice below. If your implementation is correct, it should follow the following steps (though obviously this is heavily dependent on the string your passing it), assuming 'abcd' is your string:
* Input: abcd
* abcd becomes dabc
* input: dabc
* dabc becomes cdab
* input: cdab
* cdab becomes bcad
* input: bcad
* bcad becomes abcd (original input)
As such, if this is a homework assignment, and if your teacher uses the string "hello", and repeatedly applies your implementation to the string, something like the following should happen:
* teacher passes in "hello"
* "hello" becomes "ohell"
* "ohell" becomes "lohel"
* "lohel" becomes "llohe"
* "llohe" becomes "elloh"
* "elloh" becomes "hello" (original input)
Hope this helps!

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-07 18:07:10

So is this what you're talking about when it comes to circular shifting? (note: I've also fixed the asky support, I hope...)
def trashy(message, move):
  message2 = ""
  for i in message:
    x = ord(i)
    if x+move <32 or x+move >126:
      print("I'm sorry, the value given is out of range, now exiting...")
      return
    else:
      message2= message2+chr(x+move)
  print("Scrambled version of the message is "+message2)
  rotate(message2)

def rotate(rotated):
  message2 = ""
  x = -1
  while x < len(rotated)-1:
    message2 = message2+rotated[x]
    x +=1
  print("Rotated version of the message: "+message2)

numbermove = input("How much do you want to shift your letters by?")
something = input("What is your message?")
trashy(something, int(numbermove))

2019-01-07 19:41:13

if you never want to care about going out of range, just take the input move number and mod it by 94 and then ad 32. I would just also take x as the new ASCII value stop adding move to it all the time.

x = ord(i) + move
move = (x % 94) + 32

I don’t believe in fighting unnecessarily.  But if something is worth fighting for, then its always a fight worth winning.
check me out on Twitter and on GitHub

2019-01-07 20:20:50 (edited by Ethin 2019-01-07 20:25:02)

@8, exactly. You got it! The solution can be expressed in a much more elegant method, but this also works. As an example, in C you might bit-shift each character to the left by one and OR it with the character bit-shifted to the right by 7 ((c<<1)|(c>>7)). The advantage to that would be that the compiler is able to translate that into a very fast single instruction that does it all for you. The disadvantage is that its hard to read, and the outcome is less clear. (It also works on only one character, so it would require iteration.) In Python, there is a similar shortened method, except it is able to work on entire strings. Again though, the outcome is less clear. But this method works; it requires more instructions (and hence, more cycles), but the overhead is negligible. Great work!

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-07 22:28:55

Post 9, yeah... I should stop with that, point noted. I'll try and write less repetitive code in the future.

2019-01-10 21:24:58 (edited by amerikranian 2019-01-10 21:34:26)

So back to school we go, and one of the things we're welcomed back to is rot_13. Can anyone give me tips on shortening down code and or tell me if I implemented it correctly?
Code goes below.
def rot_13(message):
message2 = ""
for i in message:
  x = ord(i)
  if x>=65 and x<=122:
   x +=13
   if x>122:
    message2+=chr(65+(x-122))
   else:
    message2+=chr(x)
  else:
   message2+=chr(x)
print(message2)

Very basic, I know, it was easier then the original script this topic started with, but oh well... we start small, I guess.
Oh, and before I forget... Can anyone explain affine cipher? How does it work and such? Try to explain it as simply as possible, please...

2019-01-11 01:17:37 (edited by Ethin 2019-01-11 01:19:31)

The affine cipher is a type of monoalphabetic substitution cipher. The way it works is as follows:
* You pass the cipher a string
* Each letter in an alphabet (i.e. the base64 or base32 alphabet) is mapped to its numeric equivalent
* That numeric equivalent is encrypted with a simple mathematical function
* That (now encrypted numeric equivalent) is then converted back to its alphabetic form
The formula used in the cipher means that each letter than is encrypted maps to one other letter and back again, meaning the cipher is a standard substitution cipher with a rule governing which letter maps to which. That also means that it has the same weaknesses of a substitution cipher. The simple mathematical function used to encipher (encrypt) each letter is (ax + b) mod 26, where b is the magnitude of the shift.
In other words, mainly mathematical:
* The letters of an alphabet of size m are first mapped to the range 0,m-1 (that is, 0 to the size of the alphabet minus one).
* Modular arithmetic is then employed to map each plaintext letters' ordinal to its encrypted equivalent. That function is e(x)=(ax+b)%m, where modulus m is the size of the alphabet (determined in the first step) and a and b are the keys to the cipher. The value a must be chosen such that a and m are coprime (that is, the only positive integer (factor) that divides both of them is 1).
* To decrypt the encrypted plaintext, you first get the encrypted letters ordinal, and employ the mathematical function d(x)=a^-1(x-b)%m, where a^-1 is the modular multiplicative inverse of a modulo m, i.e. it satisfies the equation 1=a(base a)^-1%m.
The Caesar cipher is one such example of an affine cipher with a=1 since the encrypting function reduces to a linear shift.
I know you asked for a simple explanation, but I elaborated on the cipher in case you needed it. If your going to be writing one, you'll need all that I have provided here. As for your other problem, ROT-13 can be implemented in 1 line in Python, 3 if you split it across lines for ease of readability. As a hint, look in the bytes module (automatically imported). I also just ran your code through Python, and the implementation isn't correct. When running the method I'm hinting at and giving it 'Hello world!', I get 'Uryyb jbeyq!'. When I run it through your method though, I get 'UryyC KCFyq!'. So your close, but not quite there.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-11 21:41:02 (edited by amerikranian 2019-01-11 21:47:36)

note: It seems like the forum trims my spaces for indention. I have changed the spaces to > signs, so just replace those with spaces when you run my code.
@Ethin, Thanks for the explanation of the cipher. Looks like it's gonna be a joy to write, not...
I have also seemed to fix the broken rot_13 method. Tell me if it works for you.
Code goes below.
def rot_13(message):
>message2 = ""
>for i in message:
>>x = ord(i)
>>if x>=65 and x<=90:
>>>x +=13
>>>if x >90:
>>>>x = 64+(x-90)
>>elif x >=97 and x <=122:
>>>x +=13
>>>if x>122:
>>>>x = 96+(x-122)
>>message2+=chr(x)
>print(message2)

The code looks a bit different now, because I got told that rot_13 is only supposed to affect English alphabet and alphabet only. If you pass something like "Hello[] w__o^^rl\\d" to the code in post 12 it will shift the brackets the backslashes and the underscores instead of leaving them alone as it should.
I will look at the bites module, though the point of it was to see if you could implement the logic. It wasn't the difficulty of the script, it was just to see if we learn anything in class. I'll be back with the broken affine cipher some time next week.
I would like to thank you all for actually answering my questions, and I'm sorry to be such a bother. It's not the most fun thing in the world to teach a newbie, trust me, I know.

2019-01-11 22:13:50

Oh, no, I had fun writing all that. No bother, it was fun to see someone interested in learning about programming and cryptography.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-14 21:56:52

Right, I think this is how the affine cipher works.
Code goes below, again, replace the > with spaces.
def affine(a, b, c):
>message2 = ""
>for i in c:
>>x = ord(i)
>>message2+=str((a*x+b)%26)
>return message2

I'm sure it's broken in a way, but oh well.
Now, suppose that I want to get the original string of text back. Here's a problem. I can't. Not because I'm not able to code in the method, I probably can, but because this code will spill out a bunch of numbers, like so.
Input: affine(3, 5, "I am a good boy, right?")
output: 162310202310232001923130472398251512
Cool, right? What a giant hot mess. So, here is my main question:
The way I pictured this working was adding a character that adds itself to the string, so instead of message2+=str((a*x+b)%26), we could have message2+=" "+str((a*x+b)%26). In this case, the special character that would seperate the letters would be space. My issue comes when I would create a loop, the i would equal space and python will convert the thing instead of simply ignoring it.
Don't provide the code, just talk it out with me, please. Could we do a for loop with range and i increasing by 2 instead? Would we simply scrap the for loop and use a while one with it checking for the equality of the 2 string's length? Or is the cipher only meant for single letters, not words, and I am over complicating things again?

2019-01-15 06:57:35

Yeah, you messed up, and I'm honestly not sure where you went wrong with this one. I think, however, that you are over-complicating things. When I run your cipher and add a chr() call, I get back bytes (yes, literal Unicode sequences).
Edit: actually, your quite close. A source I found used a string of characters to hold all the translatable symbols, and did something quite similar to what your doing. They didn't constrain it to the alphabet, either: they constrained it to the characters " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\] ^_`abcdefghijklmnopqrstuvwxyz{|}~". Furthermore, they scanned the keys used, and aborted if either (1) the first key was one, (2) the second key was zero, (3) the first or second keys were less than zero or the second key was greater than the size of the symbol table minus one, or (4) the key and the size of the symbol table were not relatively prime. (All of those are weaknesses and measures should be in place to forbid them.) Furthermore, instead of dividing the key into two separate parameters, the version I'm looking at split the two keys into two separate, distinct entities, then analyzed those halves. During the encryption process, the version looped through the message, determined if it was in the symbol table, and encrypted it. If it wasn't, it did something a bit different. During the decryption process, the version located the mod inverse of the first part of the key and the size of the symbol table, iterated through the enciphered message, and inverted the encryption if and only if the character that was examined was in the symbol table. Finally: as you don't need this method, I'll disclose what the version also did: it allowed you to generate a random, secure key. It did this by (1) infinitely generating key portions between the range 2-length of symbol table, (2) determining if the first key portion and the size of the symbol table were relatively prime, and (3) if they were relatively prime, it returned the first key times the size of the symbol table plus the second keys portion. If they didn't match, it continued generating a key until it returned a relatively prime result. I'm not giving any code like you asked, if you want to implement such a mechanism yourself.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-15 18:03:58 (edited by stewie 2019-01-16 19:53:53)

Ord takes a character as input and returns the ascii value of that character, which in python is an integer. You are transforming the integer for the cipher, which is fine. You then call str on the result, which just turns the number into a string without actually converting the ascii code back to a character. If you replace the str call with chr (since it's only one character anyway), it should work.

(edit)You call  chr to convert the ascii back to a single character, not ord.(/edit)

Deep in the human unconscious is a pervasive need for a logical universe that makes sense. But the real universe is always one step beyond logic.

2019-01-16 21:47:21 (edited by amerikranian 2019-01-16 21:53:02)

@Ethan, could you explain how to undo the modulus opparator using numbers please? I'm still in algebra, so forgive me for not being able to keep up with you. heh. I also seem to grasp things quicker and or better if you give me an expression with numbers, Rather than a bunch of theory.
As to your post 17, interesting... We'll see if I will need to re-code the entire thing. My hope is not to, but oh well... we all fail time to time.
On another note, what does the ^ operator do? mathematically, I mean?

2019-01-17 01:16:47 (edited by stewie 2019-01-17 01:17:36)

Normally the ^ operator is exponentiation (2^2 = 2 squared, 2^3 = 2 cubed, etc). In python though ^ is the bitwise  xor operation. Python's exponentiation operator is ** (as in, 2**2 or 2**3).

You can't directly reverse the modulus operation unless you know the number you were dividing by (call it  d), the whole number part of the result (call it w), and the remainder (which mod  finds, call it r). Mod returns a single number, so it would be impossible to tell which combination resulted. You could multiply the dividing number by the whole part (d*w) and add the remainder r to get back to the original number.

For example, try 30%7 (30 mod 7). 30 divided by 7 results in 4 remainder 2. To get back to 30 you could do 4*7+2 (4*7 to get to 28, add the remainder of 2 to get to 30). Without having all 3 of those numbers the inversion would have been impossible.

Deep in the human unconscious is a pervasive need for a logical universe that makes sense. But the real universe is always one step beyond logic.

2019-01-24 21:57:41 (edited by amerikranian 2019-01-25 21:43:36)

So while failing at an affine cipher, I decided to take a break. Sometimes it helps, sometimes it doesn't. In short, I coded something else:
Here you go.

def factor(xs, factornum):
 x1 = 1
 x2 = 1
 isfactored = False
 while isfactored==False:
  z = x1*x2
  if z==factornum:
   w = x1+x2
   if w==xs:
    print( str(x1)+" "+str(x2))
    return
  if x2>factornum:
   x2=1
   x1+=1
  if x1>factornum:
   print("Unfactorable expression.")
   return
  x2+=1

def negfactor(xs, factornum):
 x1 = -1
 x2 = -1
 isfactored=False
 while isfactored==False:
  z = x1*x2
  if z==factornum:
   w = x1+x2
   if w==xs:
    print(str(x1)+" "+str(x2))
    return
  if x2<factornum-factornum*2:
   x2=-1
   x1-=1
  if x1<factornum-factornum*2:
   print("Unfactorable expression.")
   return
  x2-=1


def hybrid(xs, factornum):
 x1=-1
 x2=1
 isfactored=False
 while isfactored==False:
  z = x1*x2
  if z==factornum:
   w = x1+x2
   if w==xs:
    print(str(x1)+" "+str(x2))
    return
  if x2>factornum+factornum*-2:
   x2=1
   x1-=1
  if x1<factornum:
   print( "Unfactorable expression.")
   return
  x2+=1

def begin(xs, factornum):
 if xs >0 and factornum>0:
  factor(xs, factornum)
 elif xs <0 and factornum >0:
  negfactor(xs, factornum)
 elif xs >0 and factornum <0:
  hybrid(xs, factornum)
 else:
  print("It appears that you gave an invalid number. Try again.")

Completely useless, I know, but something fun on the side. Also, let me know if you see any potential issues. I know you can crash the script by giving it letters or too big of a number, I'm looking into try statements to fix that problem as I write this.

2019-01-24 22:45:44 (edited by Ethin 2019-01-24 22:46:55)

Have you considered using code tags? Like (replace left and right bracket with the actual chars, the forum provides no way of escaping BBCode):
left bracket code right bracket
def hi():
    return
left bracket /code right bracket

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-25 01:53:41

OK. It’s done. I did it on an iPhone, so I apologize for any indention errors.

2019-01-25 04:25:47

That's OK

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.
My Github

2019-01-25 21:44:08

Right, I believe the indention problems are completely fixed now. Now you can run the thing and it should... work?