# Simple cipher solver, finding all possible key combinations

**URL:** https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807
**Category:** ruby-talk
**Created:** [10 August 2007 14:19 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807 "2007-08-10T14:19:55Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![Aric\_Campbell](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@Aric\_Campbell](https://rubytalk.org/u/Aric_Campbell)
#### Post date: [10 August 2007 14:19 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/1 "2007-08-10T14:19:55Z")

</div>

I am trying to find every possible combination of the letters of the alphabet to create a file by a program to solve simple replacement ciphers. There shouldn't be any repeats of letters in the combination (i.e. a can only occur once in a given combination).

I had thought of using the code below to get every possible combination and, even though it contains duplicate letters in the combinations it generates, I was going to prune those out. The problem is that it would take a very considerable number of years before the program finishes. Anyone know of an algorithm that I could use to generate the possibilities in a more timely manner?

class Value  
&nbsp;&nbsp;def initialize val='a'  
&nbsp;&nbsp;&nbsp;&nbsp;@value = val  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def == rhs  
&nbsp;&nbsp;&nbsp;&nbsp;if rhs.class != self.class  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;rhs.value == self.value  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def next  
&nbsp;&nbsp;&nbsp;&nbsp;if @value == 'z'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.reset  
&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@value = @value.next  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def reset  
&nbsp;&nbsp;&nbsp;&nbsp;@value = 'a'  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def value  
&nbsp;&nbsp;&nbsp;&nbsp;@value  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
end

class Set  
&nbsp;&nbsp;def initialize  
&nbsp;&nbsp;&nbsp;&nbsp;@buffer = []  
&nbsp;&nbsp;&nbsp;&nbsp;26.times {@buffer \<\< Value.new}  
&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def value  
&nbsp;&nbsp;&nbsp;&nbsp;@buffer  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;temp = []  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;@buffer.each{|a| temp \<\< a.value}  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;temp  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def exausted?  
&nbsp;&nbsp;&nbsp;&nbsp;@buffer.each do |a|  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if a.value != 'z'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;return true  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
&nbsp;&nbsp;def next  
&nbsp;&nbsp;&nbsp;&nbsp;cursor = 1  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;while true  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @buffer.last(cursor)[0].value == 'z'  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cursor += 1  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;end  
&nbsp;&nbsp;&nbsp;&nbsp;self.value  
&nbsp;&nbsp;&nbsp;&nbsp;  
&nbsp;&nbsp;end  
&nbsp;&nbsp;  
end

> **···**
>
> #################################################################  
> #################################################################
> 
> s = Set.new  
> f = open "sets.out",'w'
> 
> f \<\< s.value
> 
> while s.exausted? == false  
> &nbsp;&nbsp;f \<\< s.next \<\< "\n"  
> end
> 
> ---------------------------------  
> Be a better Globetrotter. Get better travel answers from someone who knows.  
> Yahoo! Answers - Check it out.

---

<div class="post-metadata">

### Author: ![Jamie\_Lynn\_O\_Marr](https://avatars.discourse-cdn.com/v4/letter/j/0ea827/32.png) [@Jamie\_Lynn\_O\_Marr](https://rubytalk.org/u/Jamie_Lynn_O_Marr)
#### Post date: [10 August 2007 15:27 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/2 "2007-08-10T15:27:27Z")

</div>

This is actually a timely question; I was about to start working on the same  
problem!

I'm a Ruby nuby, and as practice I decided that my first project would be a  
suite of old school cryptography encryption/decryption software. (Later to  
be web-ified with Rails so anyone can use it on the web)

So this isn't exactly an answer to your question, but it is a way to  
optimize your decryption:

Substitution cyphers are easiest to solve with a frequency analysis. (The  
most common letters in the English language are 'E' 'T' and 'A' in that  
order) Of course, the utility of this method increases with the length of  
the cyphertext, so it may not be useful for very short (one word) messages  
but is very useful for longer blocks of text (two or three sentences or  
more).

Rather than computing all possible cyphers every time, you could make each  
calculation dependent on a frequency analysis. So you count the number of  
times each letter appears in the cyphertext, then try substituting the  
letter that corresponds to the frequency. It is possible you may have to  
run through several dozen combinations before you hit on the right one, but  
it should be much faster than just calculating every single possible  
combination. Rather than a random assignment of letter combinations, you  
make the choice of combinations dependent on the frequency analysis. It  
will require user input each time (puts 'Does this make sense? (y/n)') in  
order to determine if the decryption actually worked (unless you're going to  
include a syntax library to check it against, and if you do that, please  
tell me how you do it!). I hope eventually to allow the user to adjust the  
frequency analysis themselves, because the human brain can spot patterns  
that pure statistics can't. . .but that's a little more complicated.

I wish I had some code for you, but like I said, I was just about to start  
working on this myself. On the other hand, if you want some Ruby code for  
substitution ENcryption, I'm putting the finishing touches on that right  
now. Sorry I'm not faster, but I'm learning Ruby in between raising a  
toddler, gestating a new kid, and trying to get into law school 😉

Hit me up on AIM if you want to talk about old school cryptography. I'm not  
much of a Ruby coder yet, but I know a lot about old school cryptography 🙂

Jamie Lynn  
AKA greymaiden  
over.

> **···**
>
> On 8/10/07, Aric Campbell \<ajcampbell0128@yahoo.com\> wrote:
> 
> > I am trying to find every possible combination of the letters of the  
> > alphabet to create a file by a program to solve simple replacement ciphers.  
> > There shouldn't be any repeat of letters in the combination (i.e. a can  
> > only occur once in a given combination).
> > 
> > I had thought of using the code below to get every possible combination  
> > and, even though it contains duplicate letters in the combinations it  
> > generates, I was going to prune those out. The problem is that it would take  
> > a very considerable number of years before the program finishes. Anyone know  
> > of an algorithm that I could use to generate the possibilities in a more  
> > timely manner?
> > 
> > class Value  
> > &nbsp;&nbsp;def initialize val='a'  
> > &nbsp;&nbsp;&nbsp;&nbsp;@value = val  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def == rhs  
> > &nbsp;&nbsp;&nbsp;&nbsp;if rhs.class != self.class  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;rhs.value == self.value  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def next  
> > &nbsp;&nbsp;&nbsp;&nbsp;if @value == 'z'  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;self.reset  
> > &nbsp;&nbsp;&nbsp;&nbsp;else  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@value = @value.next  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def reset  
> > &nbsp;&nbsp;&nbsp;&nbsp;@value = 'a'  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def value  
> > &nbsp;&nbsp;&nbsp;&nbsp;@value  
> > &nbsp;&nbsp;end
> > 
> > end
> > 
> > class Set  
> > &nbsp;&nbsp;def initialize  
> > &nbsp;&nbsp;&nbsp;&nbsp;@buffer =   
> > &nbsp;&nbsp;&nbsp;&nbsp;26.times {@buffer \<\< Value.new}  
> > &nbsp;&nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def value  
> > &nbsp;&nbsp;&nbsp;&nbsp;@buffer
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;temp =
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;@buffer.each{|a| temp \<\< a.value}
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;temp  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def exausted?  
> > &nbsp;&nbsp;&nbsp;&nbsp;@buffer.each do |a|  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if a.value != 'z'  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return false  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;return true  
> > &nbsp;&nbsp;end
> > 
> > &nbsp;&nbsp;def next  
> > &nbsp;&nbsp;&nbsp;&nbsp;cursor = 1
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;while true  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if @buffer.last(cursor)[0].value == 'z'
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cursor += 1  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()
> > 
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@buffer.last(cursor)[0].next()  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break  
> > &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;end  
> > &nbsp;&nbsp;&nbsp;&nbsp;self.value
> > 
> > &nbsp;&nbsp;end
> > 
> > end
> > 
> > #################################################################  
> > #################################################################
> > 
> > s = Set.new  
> > f = open "sets.out",'w'
> > 
> > f \<\< s.value
> > 
> > while s.exausted? == false  
> > &nbsp;&nbsp;f \<\< s.next \<\< "\n"  
> > end
> > 
> > ---------------------------------  
> > Be a better Globetrotter. Get better travel answers from someone who  
> > knows.  
> > Yahoo! Answers - Check it out.

---

<div class="post-metadata">

### Author: ![Lloyd\_Linklater](https://avatars.discourse-cdn.com/v4/letter/l/919ad9/32.png) [@Lloyd\_Linklater](https://rubytalk.org/u/Lloyd_Linklater)
#### Post date: [10 August 2007 18:04 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/3 "2007-08-10T18:04:23Z")

</div>

Aric Campbell wrote:

> I had thought of using the code below to get every possible combination  
> and, even though it contains duplicate letters in the combinations it  
> generates, I was going to prune those out. The problem is that it would  
> take a very considerable number of years before the program finishes.  
> Anyone know of an algorithm that I could use to generate the  
> possibilities in a more timely manner?

Well, you could try more than just the most common letters strategy.  
What you really want to do is reduce the number of possibilities. There  
are a limited number of legitimate one and two character words. You  
could start with them and see if things add up elsewhere with those  
letters assigned.

Check the recent Ruby puzzle for finding crosswords.  
[Ruby Quiz - Crossword Solver (#132)](http://www.rubyquiz.com/quiz132.html) Interestingly enough, there were a  
good many groovy approaches but the one listed in this link reference a  
widget made by google which is made for finding words like this. It  
seems highly optimized and could help you out.

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

### Author: ![Jamie\_Lynn\_O\_Marr](https://avatars.discourse-cdn.com/v4/letter/j/0ea827/32.png) [@Jamie\_Lynn\_O\_Marr](https://rubytalk.org/u/Jamie_Lynn_O_Marr)
#### Post date: [10 August 2007 15:30 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/4 "2007-08-10T15:30:51Z")

</div>

Right, probably should have told you my AIM name if I asked you to talk to  
me there. I'm LastGreyMaiden on AIM. greymaiden on GoogleChat.

Braaaaaiiiiinsss. . . .sigh.

> **···**
>
> On 8/10/07, Jamie Lynn O'Marr \<greymaiden@gmail.com\> wrote:
> 
> > This is actually a timely question; I was about to start working on the  
> > same problem!
> > 
> > I'm a Ruby nuby, and as practice I decided that my first project would be  
> > a suite of old school cryptography encryption/decryption software. (Later  
> > to be web-ified with Rails so anyone can use it on the web)
> > 
> > So this isn't exactly an answer to your question, but it is a way to  
> > optimize your decryption:
> > 
> > Substitution cyphers are easiest to solve with a frequency analysis. (The  
> > most common letters in the English language are 'E' 'T' and 'A' in that  
> > order) Of course, the utility of this method increases with the length of  
> > the cyphertext, so it may not be useful for very short (one word) messages  
> > but is very useful for longer blocks of text (two or three sentences or  
> > more).
> > 
> > Rather than computing all possible cyphers every time, you could make each  
> > calculation dependent on a frequency analysis. So you count the number of  
> > times each letter appears in the cyphertext, then try substituting the  
> > letter that corresponds to the frequency. It is possible you may have to  
> > run through several dozen combinations before you hit on the right one, but  
> > it should be much faster than just calculating every single possible  
> > combination. Rather than a random assignment of letter combinations, you  
> > make the choice of combinations dependent on the frequency analysis. It  
> > will require user input each time (puts 'Does this make sense? (y/n)') in  
> > order to determine if the decryption actually worked (unless you're going to  
> > include a syntax library to check it against, and if you do that, please  
> > tell me how you do it!). I hope eventually to allow the user to adjust the  
> > frequency analysis themselves, because the human brain can spot patterns  
> > that pure statistics can't. . .but that's a little more complicated.
> > 
> > I wish I had some code for you, but like I said, I was just about to start  
> > working on this myself. On the other hand, if you want some Ruby code for  
> > substitution ENcryption, I'm putting the finishing touches on that right  
> > now. Sorry I'm not faster, but I'm learning Ruby in between raising a  
> > toddler, gestating a new kid, and trying to get into law school 😉
> > 
> > Hit me up on AIM if you want to talk about old school cryptography. I'm  
> > not much of a Ruby coder yet, but I know a lot about old school cryptography  
> > 🙂
> > 
> > Jamie Lynn  
> > AKA greymaiden  
> > over.
> > 
> > On 8/10/07, Aric Campbell \<ajcampbell0128@yahoo.com\> wrote:  
> > \>  
> > \> I am trying to find every possible combination of the letters of the  
> > \> alphabet to create a file by a program to solve simple replacement ciphers.  
> > \> There shouldn't be any repeat of letters in the combination (i.e. a can  
> > \> only occur once in a given combination).  
> > \>  
> > \> I had thought of using the code below to get every possible combination  
> > \> and, even though it contains duplicate letters in the combinations it  
> > \> generates, I was going to prune those out. The problem is that it would take  
> > \> a very considerable number of years before the program finishes. Anyone know  
> > \> of an algorithm that I could use to generate the possibilities in a more  
> > \> timely manner?  
> > \>  
> > \>  
> > \>  
> > \> class Value  
> > \> def initialize val='a'  
> > \> @value = val  
> > \> end  
> > \>  
> > \> def == rhs  
> > \> if rhs.class != self.class  
> > \> return false  
> > \>  
> > \> end  
> > \> rhs.value == self.value  
> > \> end  
> > \>  
> > \> def next  
> > \> if @value == 'z'  
> > \> self.reset  
> > \> else  
> > \> @value = @value.next  
> > \> end  
> > \> end  
> > \>  
> > \> def reset  
> > \> @value = 'a'  
> > \> end  
> > \>  
> > \> def value  
> > \> @value  
> > \> end  
> > \>  
> > \> end  
> > \>  
> > \>  
> > \>  
> > \>  
> > \> class Set  
> > \> def initialize  
> > \> @buffer =   
> > \> 26.times {@buffer \<\< Value.new}  
> > \> end  
> > \>  
> > \> def value  
> > \> @buffer  
> > \>  
> > \> temp =   
> > \>  
> > \> @buffer.each{|a| temp \<\< a.value}  
> > \>  
> > \> temp  
> > \> end  
> > \>  
> > \> def exausted?  
> > \> @buffer.each do |a|  
> > \> if a.value != 'z'  
> > \> return false  
> > \> end  
> > \> end  
> > \> return true  
> > \> end  
> > \>  
> > \> def next  
> > \> cursor = 1  
> > \>  
> > \>  
> > \> while true  
> > \> if @buffer.last(cursor)[0].value == 'z'  
> > \>  
> > \> @buffer.last(cursor)[0].next()  
> > \> cursor += 1  
> > \> @buffer.last(cursor)[0].next()  
> > \>  
> > \> else  
> > \> @buffer.last(cursor)[0].next()  
> > \> break  
> > \> end  
> > \> end  
> > \> self.value  
> > \>  
> > \> end  
> > \>  
> > \> end  
> > \>  
> > \>  
> > \> #################################################################  
> > \> #################################################################  
> > \>  
> > \>  
> > \> s = Set.new  
> > \> f = open "sets.out",'w'  
> > \>  
> > \> f \<\< s.value  
> > \>  
> > \>  
> > \> while s.exausted? == false  
> > \> f \<\< s.next \<\< "\n"  
> > \> end  
> > \>  
> > \>  
> > \>  
> > \>  
> > \> ---------------------------------  
> > \> Be a better Globetrotter. Get better travel answers from someone who  
> > \> knows.  
> > \> Yahoo! Answers - Check it out.  
> > \>

---

<div class="post-metadata">

### Author: ![James\_Edward\_Gray\_II](https://avatars.discourse-cdn.com/v4/letter/j/ea5d25/32.png) [@James\_Edward\_Gray\_II](https://rubytalk.org/u/James_Edward_Gray_II)
#### Post date: [11 August 2007 16:12 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/5 "2007-08-11T16:12:28Z")

</div>

We had an older quiz that was even closer to this problem:

[http://www.rubyquiz.com/quiz13.html](http://www.rubyquiz.com/quiz13.html)

James Edward Gray II

> **···**
>
> On Aug 10, 2007, at 1:04 PM, Lloyd Linklater wrote:
> 
> > Aric Campbell wrote:
> > 
> > > I had thought of using the code below to get every possible combination  
> > > and, even though it contains duplicate letters in the combinations it  
> > > generates, I was going to prune those out. The problem is that it would  
> > > take a very considerable number of years before the program finishes.  
> > > Anyone know of an algorithm that I could use to generate the  
> > > possibilities in a more timely manner?
> > 
> > Well, you could try more than just the most common letters strategy.  
> > What you really want to do is reduce the number of possibilities. There  
> > are a limited number of legitimate one and two character words. You  
> > could start with them and see if things add up elsewhere with those  
> > letters assigned.
> > 
> > Check the recent Ruby puzzle for finding crosswords.  
> > [Ruby Quiz - Crossword Solver (#132)](http://www.rubyquiz.com/quiz132.html)

---

<div class="post-metadata">

### Author: ![Aric\_Campbell](https://avatars.discourse-cdn.com/v4/letter/a/4bbf92/32.png) [@Aric\_Campbell](https://rubytalk.org/u/Aric_Campbell)
#### Post date: [10 August 2007 15:52 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/6 "2007-08-10T15:52:53Z")

</div>

I don't have AIM but I do have GoogleChat.

I will have to look into the frequency analysis angle. It wouldn't be too hard to analyze a few works of fiction form project Gutenberg and then use the results to make suggestions for substitutions. I'm guessing that if spaces are included in the cipher text you could also suggest 'i' and 'a' for single characters and other optimizations like that.

I'm still curious whether there is a way to find all possible combinations. It's more of a "I feel like I'm missing something obvious and want to know what it is" kind of curiosity. I suppose I could ask on a math forum as well. My method simply isn't practical. There would be 6,156,119,580,207,157,310,796,674,288,400,203,776 iterations in my program before I even got to pruning the results.

Jamie Lynn O'Marr \<greymaiden@gmail.com\> wrote: Right, probably should have told you my AIM name if I asked you to talk to  
me there. I'm LastGreyMaiden on AIM. greymaiden on GoogleChat.

Braaaaaiiiiinsss. . . .sigh.

> **···**
>
> On 8/10/07, Jamie Lynn O'Marr wrote:
> 
> > This is actually a timely question; I was about to start working on the  
> > same problem!
> > 
> > I'm a Ruby nuby, and as practice I decided that my first project would be  
> > a suite of old school cryptography encryption/decryption software. (Later  
> > to be web-ified with Rails so anyone can use it on the web)
> > 
> > So this isn't exactly an answer to your question, but it is a way to  
> > optimize your decryption:
> > 
> > Substitution cyphers are easiest to solve with a frequency analysis. (The  
> > most common letters in the English language are 'E' 'T' and 'A' in that  
> > order) Of course, the utility of this method increases with the length of  
> > the cyphertext, so it may not be useful for very short (one word) messages  
> > but is very useful for longer blocks of text (two or three sentences or  
> > more).
> > 
> > Rather than computing all possible cyphers every time, you could make each  
> > calculation dependent on a frequency analysis. So you count the number of  
> > times each letter appears in the cyphertext, then try substituting the  
> > letter that corresponds to the frequency. It is possible you may have to  
> > run through several dozen combinations before you hit on the right one, but  
> > it should be much faster than just calculating every single possible  
> > combination. Rather than a random assignment of letter combinations, you  
> > make the choice of combinations dependent on the frequency analysis. It  
> > will require user input each time (puts 'Does this make sense? (y/n)') in  
> > order to determine if the decryption actually worked (unless you're going to  
> > include a syntax library to check it against, and if you do that, please  
> > tell me how you do it!). I hope eventually to allow the user to adjust the  
> > frequency analysis themselves, because the human brain can spot patterns  
> > that pure statistics can't. . .but that's a little more complicated.
> > 
> > I wish I had some code for you, but like I said, I was just about to start  
> > working on this myself. On the other hand, if you want some Ruby code for  
> > substitution ENcryption, I'm putting the finishing touches on that right  
> > now. Sorry I'm not faster, but I'm learning Ruby in between raising a  
> > toddler, gestating a new kid, and trying to get into law school 😉
> > 
> > Hit me up on AIM if you want to talk about old school cryptography. I'm  
> > not much of a Ruby coder yet, but I know a lot about old school cryptography  
> > 🙂
> > 
> > Jamie Lynn  
> > AKA greymaiden  
> > over.
> > 
> > On 8/10/07, Aric Campbell wrote:  
> > \>  
> > \> I am trying to find every possible combination of the letters of the  
> > \> alphabet to create a file by a program to solve simple replacement ciphers.  
> > \> There shouldn't be any repeat of letters in the combination (i.e. a can  
> > \> only occur once in a given combination).  
> > \>  
> > \> I had thought of using the code below to get every possible combination  
> > \> and, even though it contains duplicate letters in the combinations it  
> > \> generates, I was going to prune those out. The problem is that it would take  
> > \> a very considerable number of years before the program finishes. Anyone know  
> > \> of an algorithm that I could use to generate the possibilities in a more  
> > \> timely manner?  
> > \>  
> > \>  
> > \>  
> > \> class Value  
> > \> def initialize val='a'  
> > \> @value = val  
> > \> end  
> > \>  
> > \> def == rhs  
> > \> if rhs.class != self.class  
> > \> return false  
> > \>  
> > \> end  
> > \> rhs.value == self.value  
> > \> end  
> > \>  
> > \> def next  
> > \> if @value == 'z'  
> > \> self.reset  
> > \> else  
> > \> @value = @value.next  
> > \> end  
> > \> end  
> > \>  
> > \> def reset  
> > \> @value = 'a'  
> > \> end  
> > \>  
> > \> def value  
> > \> @value  
> > \> end  
> > \>  
> > \> end  
> > \>  
> > \>  
> > \>  
> > \>  
> > \> class Set  
> > \> def initialize  
> > \> @buffer =   
> > \> 26.times {@buffer \<\< Value.new}  
> > \> end  
> > \>  
> > \> def value  
> > \> @buffer  
> > \>  
> > \> temp =   
> > \>  
> > \> @buffer.each{|a| temp \<\< a.value}  
> > \>  
> > \> temp  
> > \> end  
> > \>  
> > \> def exausted?  
> > \> @buffer.each do |a|  
> > \> if a.value != 'z'  
> > \> return false  
> > \> end  
> > \> end  
> > \> return true  
> > \> end  
> > \>  
> > \> def next  
> > \> cursor = 1  
> > \>  
> > \>  
> > \> while true  
> > \> if @buffer.last(cursor)[0].value == 'z'  
> > \>  
> > \> @buffer.last(cursor)[0].next()  
> > \> cursor += 1  
> > \> @buffer.last(cursor)[0].next()  
> > \>  
> > \> else  
> > \> @buffer.last(cursor)[0].next()  
> > \> break  
> > \> end  
> > \> end  
> > \> self.value  
> > \>  
> > \> end  
> > \>  
> > \> end  
> > \>  
> > \>  
> > \> #################################################################  
> > \> #################################################################  
> > \>  
> > \>  
> > \> s = Set.new  
> > \> f = open "sets.out",'w'  
> > \>  
> > \> f \<\< s.value  
> > \>  
> > \>  
> > \> while s.exausted? == false  
> > \> f \<\< s.next \<\< "\n"  
> > \> end  
> > \>  
> > \>  
> > \>  
> > \>  
> > \> ---------------------------------  
> > \> Be a better Globetrotter. Get better travel answers from someone who  
> > \> knows.  
> > \> Yahoo! Answers - Check it out.  
> > \>
> 
> ---------------------------------  
> Fussy? Opinionated? Impossible to please? Perfect. Join Yahoo!'s user panel and lay it on us.

---

<div class="post-metadata">

### Author: ![Glen\_Holcomb](https://avatars.discourse-cdn.com/v4/letter/g/ecc23a/32.png) [@Glen\_Holcomb](https://rubytalk.org/u/Glen_Holcomb)
#### Post date: [10 August 2007 17:09 UTC](https://rubytalk.org/t/simple-cipher-solver-finding-all-possible-key-combinations/39807/7 "2007-08-10T17:09:59Z")

</div>

It sounds to me like you are wanting to break Vigenere's Cypher.

There are several ways to do it although it sounds like you are going for  
the most painful. Here is a description of Vigenere:

[http://www.trincoll.edu/depts/cpsc/cryptography/vigenere.html](http://www.trincoll.edu/depts/cpsc/cryptography/vigenere.html)

You really do want to perform a frequency alanysis to break something like  
that:

> **[Letter frequency](https://en.wikipedia.org/wiki/Letter_frequencies)**
>
> Letter frequency is the number of times letters of the alphabet appear on average in written language. Letter frequency analysis dates back to the Arab mathematician Al-Kindi (c. 801–873 AD), who formally developed the method to break ciphers. Letter frequency analysis gained importance in Europe with the development of movable type in 1450 AD, where one must estimate the amount of type required for each letterform. Linguists use letter frequency analysis as a rudimentary technique for language i...

I don't have my crypto book in front of me but their table looks pretty  
good.

> **···**
>
> On 8/10/07, Aric Campbell \<ajcampbell0128@yahoo.com\> wrote:
> 
> > I don't have AIM but I do have GoogleChat.
> > 
> > I will have to look into the frequency analysis angle. It wouldn't be too  
> > hard to analyze a few works of fiction form project Gutenberg and then use  
> > the results to make suggestions for substitutions. I'm guessing that if  
> > spaces are included in the cipher text you could also suggest 'i' and 'a'  
> > for single characters and other optimizations like that.
> > 
> > I'm still curious whether there is a way to find all possible  
> > combinations. It's more of a "I feel like I'm missing something obvious and  
> > want to know what it is" kind of curiosity. I suppose I could ask on a math  
> > forum as well. My method simply isn't practical. There would be  
> > 6,156,119,580,207,157,310,796,674,288,400,203,776 iterations in my program  
> > before I even got to pruning the results.
> > 
> > Jamie Lynn O'Marr \<greymaiden@gmail.com\> wrote: Right, probably should  
> > have told you my AIM name if I asked you to talk to  
> > me there. I'm LastGreyMaiden on AIM. greymaiden on GoogleChat.
> > 
> > Braaaaaiiiiinsss. . . .sigh.
> > 
> > On 8/10/07, Jamie Lynn O'Marr wrote:  
> > \>  
> > \> This is actually a timely question; I was about to start working on the  
> > \> same problem!  
> > \>  
> > \> I'm a Ruby nuby, and as practice I decided that my first project would  
> > be  
> > \> a suite of old school cryptography encryption/decryption  
> > software. (Later  
> > \> to be web-ified with Rails so anyone can use it on the web)  
> > \>  
> > \> So this isn't exactly an answer to your question, but it is a way to  
> > \> optimize your decryption:  
> > \>  
> > \> Substitution cyphers are easiest to solve with a frequency  
> > analysis. (The  
> > \> most common letters in the English language are 'E' 'T' and 'A' in that  
> > \> order) Of course, the utility of this method increases with the length  
> > of  
> > \> the cyphertext, so it may not be useful for very short (one word)  
> > messages  
> > \> but is very useful for longer blocks of text (two or three sentences or  
> > \> more).  
> > \>  
> > \> Rather than computing all possible cyphers every time, you could make  
> > each  
> > \> calculation dependent on a frequency analysis. So you count the number  
> > of  
> > \> times each letter appears in the cyphertext, then try substituting the  
> > \> letter that corresponds to the frequency. It is possible you may have  
> > to  
> > \> run through several dozen combinations before you hit on the right one,  
> > but  
> > \> it should be much faster than just calculating every single possible  
> > \> combination. Rather than a random assignment of letter combinations,  
> > you  
> > \> make the choice of combinations dependent on the frequency analysis. It  
> > \> will require user input each time (puts 'Does this make sense? (y/n)')  
> > in  
> > \> order to determine if the decryption actually worked (unless you're  
> > going to  
> > \> include a syntax library to check it against, and if you do that, please  
> > \> tell me how you do it!). I hope eventually to allow the user to adjust  
> > the  
> > \> frequency analysis themselves, because the human brain can spot patterns  
> > \> that pure statistics can't. . .but that's a little more complicated.  
> > \>  
> > \> I wish I had some code for you, but like I said, I was just about to  
> > start  
> > \> working on this myself. On the other hand, if you want some Ruby code  
> > for  
> > \> substitution ENcryption, I'm putting the finishing touches on that right  
> > \> now. Sorry I'm not faster, but I'm learning Ruby in between raising a  
> > \> toddler, gestating a new kid, and trying to get into law school 😉  
> > \>  
> > \> Hit me up on AIM if you want to talk about old school cryptography. I'm  
> > \> not much of a Ruby coder yet, but I know a lot about old school  
> > cryptography  
> > \> 🙂  
> > \>  
> > \> Jamie Lynn  
> > \> AKA greymaiden  
> > \> over.  
> > \>  
> > \>  
> > \>  
> > \> On 8/10/07, Aric Campbell wrote:  
> > \> \>  
> > \> \> I am trying to find every possible combination of the letters of the  
> > \> \> alphabet to create a file by a program to solve simple replacement  
> > ciphers.  
> > \> \> There shouldn't be any repeat of letters in the combination (i.e. a  
> > can  
> > \> \> only occur once in a given combination).  
> > \> \>  
> > \> \> I had thought of using the code below to get every possible  
> > combination  
> > \> \> and, even though it contains duplicate letters in the combinations it  
> > \> \> generates, I was going to prune those out. The problem is that it  
> > would take  
> > \> \> a very considerable number of years before the program finishes.  
> > Anyone know  
> > \> \> of an algorithm that I could use to generate the possibilities in a  
> > more  
> > \> \> timely manner?  
> > \> \>  
> > \> \>  
> > \> \>  
> > \> \> class Value  
> > \> \> def initialize val='a'  
> > \> \> @value = val  
> > \> \> end  
> > \> \>  
> > \> \> def == rhs  
> > \> \> if rhs.class != self.class  
> > \> \> return false  
> > \> \>  
> > \> \> end  
> > \> \> rhs.value == self.value  
> > \> \> end  
> > \> \>  
> > \> \> def next  
> > \> \> if @value == 'z'  
> > \> \> self.reset  
> > \> \> else  
> > \> \> @value = @value.next  
> > \> \> end  
> > \> \> end  
> > \> \>  
> > \> \> def reset  
> > \> \> @value = 'a'  
> > \> \> end  
> > \> \>  
> > \> \> def value  
> > \> \> @value  
> > \> \> end  
> > \> \>  
> > \> \> end  
> > \> \>  
> > \> \>  
> > \> \>  
> > \> \>  
> > \> \> class Set  
> > \> \> def initialize  
> > \> \> @buffer =   
> > \> \> 26.times {@buffer \<\< Value.new}  
> > \> \> end  
> > \> \>  
> > \> \> def value  
> > \> \> @buffer  
> > \> \>  
> > \> \> temp =   
> > \> \>  
> > \> \> @buffer.each{|a| temp \<\< a.value}  
> > \> \>  
> > \> \> temp  
> > \> \> end  
> > \> \>  
> > \> \> def exausted?  
> > \> \> @buffer.each do |a|  
> > \> \> if a.value != 'z'  
> > \> \> return false  
> > \> \> end  
> > \> \> end  
> > \> \> return true  
> > \> \> end  
> > \> \>  
> > \> \> def next  
> > \> \> cursor = 1  
> > \> \>  
> > \> \>  
> > \> \> while true  
> > \> \> if @buffer.last(cursor)[0].value == 'z'  
> > \> \>  
> > \> \> @buffer.last(cursor)[0].next()  
> > \> \> cursor += 1  
> > \> \> @buffer.last(cursor)[0].next()  
> > \> \>  
> > \> \> else  
> > \> \> @buffer.last(cursor)[0].next()  
> > \> \> break  
> > \> \> end  
> > \> \> end  
> > \> \> self.value  
> > \> \>  
> > \> \> end  
> > \> \>  
> > \> \> end  
> > \> \>  
> > \> \>  
> > \> \> #################################################################  
> > \> \> #################################################################  
> > \> \>  
> > \> \>  
> > \> \> s = Set.new  
> > \> \> f = open "sets.out",'w'  
> > \> \>  
> > \> \> f \<\< s.value  
> > \> \>  
> > \> \>  
> > \> \> while s.exausted? == false  
> > \> \> f \<\< s.next \<\< "\n"  
> > \> \> end  
> > \> \>  
> > \> \>  
> > \> \>  
> > \> \>  
> > \> \> ---------------------------------  
> > \> \> Be a better Globetrotter. Get better travel answers from someone who  
> > \> \> knows.  
> > \> \> Yahoo! Answers - Check it out.  
> > \> \>  
> > \>  
> > \>
> > 
> > ---------------------------------  
> > Fussy? Opinionated? Impossible to please? Perfect. Join Yahoo!'s user  
> > panel and lay it on us.
> 
> --  
> "Hey brother Christian with your high and mighty errand, Your actions speak  
> so loud, I can't hear a word you're saying."
> 
> -Greg Graffin (Bad Religion)
