Page 2 of 7 FirstFirst 1234 ... LastLast
Results 11 to 20 of 68

Thread: Programming Challenge 9: Vigenère cipher

  1. #11
    Join Date
    Feb 2008
    Location
    UK
    Beans
    24

    Re: Programming Challenge 9: Vigenère cipher

    Its nice to see so many submits already.

    Wybiral your solution works nicely.

    nvteighen yours compiles, but gives me a Segmentation fault after typing in the values which can't be good.

    Zugzwang I would like to see yours, but can't get it to compile. It gives me swing errors. Any suggestions?

    Alasdair im not familiar with lisp would you be able to post a compile/run command.

  2. #12
    Join Date
    Apr 2006
    Location
    Sheffield - England
    Beans
    Hidden!

    Re: Programming Challenge 9: Vigenère cipher

    If you have CLISP installed and you saved the code in /home/your-user-name/cipher.lisp you should be able to load it with the command "clisp -i /home/your-user-name/cipher.lisp". Then just type the following commands:

    (vigenere "ATTACKATDAWN" "LEMON")
    (vigenere "LXFOPVEFRNHR" "LEMON" :decrypt t)

  3. #13
    Join Date
    Feb 2008
    Location
    UK
    Beans
    24

    Re: Programming Challenge 9: Vigenère cipher

    Thanks, worked like a charm.

  4. #14
    Join Date
    Apr 2007
    Location
    Germany
    Beans
    239
    Distro
    Ubuntu 10.04 Lucid Lynx

    Thumbs down Re: Programming Challenge 9: Vigenère cipher

    Some Haskell code:
    Code:
    import Char
    import System
    
    main :: IO ()
    main = do    args <- getArgs
        if length args < 2 then
            putStrLn "I need more arguments!"
            else
                putStrLn $ encrypt (head args) (head $ tail args)
    
    encrypt :: String -> String -> String
    encrypt [] _ = []
    encrypt _ [] = []
    encrypt (x:xs) (y:ys) = (chr $ mod (ord x + ord y) 26 + 65) : encrypt xs ys
    Its 1AM here, lets see if i can add some more functionality this week.

    You will need a Haskell compiler:
    Code:
    sudo apt-get install ghc
    To run the program:
    Code:
    runhaskell vigenere.hs "ATTACKATDAWN" "LEMONLEMONLEPEINS"
    edit: obviously, vigenere.hs is the file name where you saved the code
    Last edited by conehead77; April 29th, 2008 at 12:28 AM.
    NEVER use a command given to you before asking and knowing exactly what it does. Make sure you know what it is that you're telling your system to do before doing it; some commands can be very harmful to your system or leave you vulnerable to attack.

  5. #15
    Join Date
    Jun 2006
    Location
    Gwangju, Korea
    Beans
    3,479
    Here's a library written in Ruby.

    Features:

    • Accepts the text and the key in any format. It automatically converts to uppercase and discards non-alphanumeric characters
    • Can read the text from a string or a file
    • Can generate pseudorandom keys. According to Wikipedia, Vigenère with a truly random key the same length as the plain text that's only used once is an unbreakable encryption form. Alas, the best source of randomness I have available is /dev/random (which is better than most programming languages provide). In addition, there's an option to provide a seed to get repeatable keys. So, for example, you could distribute the key 91_534_256_345_327_534_563_457_908 and (separately) tell the recipient to use that as the seed, then use the 11th generated key. Not terribly secure, but perhaps better than a standard key.
    • Can use non-English alphabets. An example is below using the Greek alphabet. Note that it can only auto-uppercase letters occurring in the English alphabet.
    • Optionally groups output into groups of n letters
    • Exposes a full API

    vigenère.rb:
    PHP Code:
    #!/usr/bin/env ruby

    # This is a library to implement the Vigenère Cipher.

    require 'enumerator'
    $KCODE 'UTF-8'

    # Exception raised if the key is set before the text.
    class NoTextError StandardError
    end

    # This class handles encoding and decoding text using the
    # Vigenère Cipher.
    class Vigenere
      
      
    # For convenience, you can set the options in the constructor. All
      # values are optional (though they need to be specified eventually).
      # 
      # Arguments:
      # key:             The cipher key
      # text:            The text to be encoded or decoded
      # chars_per_group: If non-nil, output will be grouped into groups of
      #                    this many characters.
      # 
      # When setting the text and the key, this class will automatically
      # convert its input to uppercase and strip all non-alphabetic
      # characters.
      
    def initialize(key niltext nilchars_per_group nil)
        @
    letter_set = %w[A B C D E F G H I J K L M N O P Q R S T U V W X Y Z]
        @
    table, @letter_indices make_tabula_recta
        
    @chars_per_group chars_per_group
        self
    .text text unless text.nil?
        
    self.key key unless key.nil?
        @
    seeded nil
      end
      
      
    # Reader methods for various instance variables.
      
    attr_reader :chars_per_group, :cipher_text, :letter_set, :plain_text, :seed, :table
      
      
    # Set the number of characters per output group. It is an error to set
      # this to 0. Set to nil to disable grouping.
      
    def chars_per_group=(n)
        
    raise ArgumentError"Can't have 0 characters per group; set to nil to disable" if == 0
        
    @chars_per_group n
      end
      
      
    # Decode the stored text using the stored key. Of course, both must be
      # set prior to calling this method.
      
    def decode
        transform 
    :decode
      end
      
      
    # Encode the stored text using the stored key. Of course, both must be
      # set prior to calling this method.
      
    def encode
        transform 
    :encode   
      end
      
      
    # Opens the specified file and sets it as the text.
      
    def file=(filename)
        
    File.open(filename) do |f|
          
    self.text f.read
        end
        self
    .text
      end
      
      
    # Provides sensible output on inspect and when running in irb.
      
    def inspect
        
    "<Vigenere: @text=%s, @key=%s, @seed=%s>" % [
          (@
    text) ? @text.inspect 'nil',
          (@
    key)  ? @key.inspect  'nil',
          (@
    seed) ? @seed.inspect 'nil',
        ]
      
    end
      
      
    # Returns the current key.
      
    def key
        add_spaces
    (@keychars_per_group)
      
    end
      
      
    # Sets the key. Raises NoTextError unless the text is set first.
      # Automatically converts the key to uppercase and discards
      # non-alphabetic characters.
      
    def key=(key)
        
    begin
          txt_len 
    = @text.split('').length # A bug in Ruby 1.8 sometimes causes String#length to return an incorrect value
        
    rescue NoMethodError
          raise NoTextError
    "You must set the text before setting a key."
        
    end
        
    @original_key key
        key 
    normalize_text(key).split('')
        
    until key.length >= txt_len
          key 
    += key
        end
        
    @key key[0...txt_len].join('')
        @
    key
      end
      
      
    # Sets the alphabet to use. Takes an array of uppercase (if
      # applicable) letters. Note: normalize_text can only auto-uppercase
      # the letters of the English alphabet. That means that if you use a
      # non-English alphabet, you'll have to manually convert your text and
      # key to uppercase.
      
    def letter_set=(array)
        @
    letter_set = array
        @
    table, @letter_indices make_tabula_recta
      end
      
      
    # Makes the tabula_recta--the cipher table. Returns an array of the
      # table itself and a hash mapping letters to indices.
      
    def make_tabula_recta
        letters 
    = @letter_set.dup
        table 
    = []
        
    letters.length.times do
          
    table.push letters.dup
          letters
    .push letters.shift
        end
        indices 
    = {}
        
    letters letters.each_with_index { |letteriindices[letter] = }
        [
    tableindices]
      
    end
      
      
    # Generates a pseudorandom key the same length as the text. Sets and
      # returns the key.
      # 
      # If a seed has been set via the seed= method, then this method
      # generates a repeatable pseudorandom number based on the seed. If the
      # seed has not been set, or has been explicitly set to nil, then this
      # method generates the most random number possible on the system.
      
    def random_key
        text_length 
    = @text.split('').length # See explanation in method key=.
        
    if @seed
          key 
    = []
          
    text_length.times do
            
    key.push(@table[0][rand(@letter_set.length)])
          
    end
        
    else
          
    cmd "dd if=/dev/random bs=1 count=#{text_length}"
          
    key = `#{cmd} 2>/dev/null`.chomp.unpack("C#{text_length}")
          
    key.collect! { |i| @table[0][% @letter_set.length] }
        
    end
        self
    .key key.join ''
      
    end
      
      
    # To use a seeded random number for a random key (so that the key can
      # be replayed, call this method with an Integer. To use a more random
      # key, call it with nil.
      
    def seed=(value)
        
    srand(value) if value.kind_ofInteger
        
    @seed value
      end
      
      
    # Returns the current text.
      
    def text
        add_spaces
    (@text, @chars_per_group)
      
    end
      
      
    # Sets the text. Automatically converts text to uppercase and discards
      # non-alphabetic characters.
      
    def text=(text)
        @
    text normalize_text text
        self
    .key= @original_key if @original_key
      end
      
      
    # Handles conversion to a string. Returns the text. Text is in
      # whichever state it was last converted to.
      
    def to_s
        text
      end
      
      
    # The following methods are private.
      
    private
      
      
    # Adds spaces to str every chars_per_group characters.
      
    def add_spaces(strchars_per_group nil)
        return 
    str if chars_per_group.nil?
        
    str str.split ''
        
    out = []
        
    str.each_slice(chars_per_group) do |group|
          
    group.push ' '
          
    out.push group.join('')
        
    end
        out
    .join('').strip
      end
      
      
    # Converts text to uppercase and discards non-alphabetic characters.
      
    def normalize_text(text)
        
    letters text.upcase.split ''
        
    letters.delete_if { |x| ! @table[0].include?(x) }
        
    letters.join ''
      
    end
      
      
    # Performs the actual encoding or decoding. The argument direction is
      # one of :encode or :decode.
      
    def transform(direction)
        
    text_letters = @text.split ''
        
    key_letters = @key.split ''
        
    transformed = []
        case 
    direction
          when 
    :encode
            text_letters
    .each_with_index do |letteri|
              
    index1 = @letter_indices.fetch(key_letters.fetch(i))
              
    index2 = @letter_indices.fetch(letter)
              
    transformed.push @table.fetch(index1).fetch(index2)
            
    end
            
    @plain_text = @text
            
    @cipher_text add_spaces(transformed.join(''), @chars_per_group)
            @
    text normalize_text @cipher_text
            
    @cipher_text
          when 
    :decode
            text_letters
    .each_with_index do |letteri|
              
    index = @letter_indices.fetch(letter) - @letter_indices.fetch(key_letters.fetch(i))
              
    transformed.push @table[0].fetch(index)
            
    end
            
    @plain_text add_spaces(transformed.join(''), @chars_per_group)
            @
    cipher_text self.text
            
    @text normalize_text @plain_text
            
    @plain_text
          
    else
            
    raise ArgumentError"direction must be either :encode or :decode"
        
    end
      end
    end

    # Testing code. Only executed if this file is executed directly. If this
    # file is require'd, this code doesn't run.

    # To run the testing code:
    #     ./vigenère.rb text key [chars-per-group]
    if $== __FILE__
      raise 
    "Must supply at least 2 command line arguments" if ARGV.length 2
      a 
    Vigenere.new
      
    a.text ARGV[0]
      
    a.key ARGV[1]
      
    a.chars_per_group ARGV[2].to_i if ARGV.length >= 3
      
      puts 
    "Using supplied key:"
      
    puts "      Plain text : #{a}"
      
    puts "    Supplied key : #{a.key}"
      
    puts "    Encoded text : #{a.encode}"
      
    puts "    Decoded text : #{a.decode}"
      
      
    a.seed 7629384752639857236945827346952837652938752392938742837462598
      a
    .random_key
      
      puts 
    "\nUsing random (seeded) key:"
      
    puts "      Plain text : #{a}"
      
    puts "      Random key : #{a.key}"
      
    puts "    Encoded text : #{a.encode}"
      
    puts "    Decoded text : #{a.decode}"
    end 
    The classes Vigenere and NoTextError are the actual implementation. The rest is a test stub.

    To run the test code:
    Code:
    ~:$ ruby vigenère.rb 'Attack at dawn!' Lemon   ## Which produces:
    Using supplied key:
          Plain text : ATTACKATDAWN
        Supplied key : LEMONLEMONLE
        Encoded text : LXFOPVEFRNHR
        Decoded text : ATTACKATDAWN
    
    Using random (seeded) key:
          Plain text : ATTACKATDAWN
          Random key : MGOCMGYHJJEJ
        Encoded text : MZHCOQYAMJAW
        Decoded text : ATTACKATDAWN
    (Of course, the random key will vary.)

    To test this as a library (the test code doesn't test reading from a file):
    Code:
    ~:$ irb
    >> require 'vigenère'
    => true
    >> Vigenere.new('lemon', 'attack at dawn', 5).encode
    => "LXFOP VEFRN HR"
    >> a = Vigenere.new
    => <Vigenere: @text=nil, @key=nil, @seed=nil>
    >> a.file = 'test.txt'
    => "test.txt"
    >> a.key = 'this is a key'
    => "this is a key"
    >> a
    => <Vigenere: @text="THISISATESTFILE", @key="THISISAKEYTHISI", @seed=nil>
    >> a.encode
    => "MOQKQKADIQMMQDM"
    >> a.decode
    => "THISISATESTFILE"
    >> b = Vigenere.new
    => <Vigenere: @text=nil, @key=nil, @seed=nil>
    >> b.letter_set = %w[Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Φ Ω]
    => ["Α", "Β", "Γ", "Δ", "Ε", "Ζ", "Η", "Θ", "Ι", "Κ", "Λ", "Μ", "Ν", "Ξ", "Ο", "Π", "Ρ", "Σ", "Τ", "Υ", "Φ", "Χ", "Φ", "Ω"]
    >> b.text = "ΑΝΘΡΟΠΟΣ"
    => "ΑΝΘΡΟΠΟΣ"
    >> b.key = "ΑΝΗΡ"
    => "ΑΝΗΡ"
    >> b
    => <Vigenere: @text="ΑΝΘΡΟΠΟΣ", @key="ΑΝΗΡΑΝΗΡ", @seed=nil>
    >> b.encode
    => "ΑΑΞΙΟΔΦΚ"
    >> b.decode
    => "ΑΝΘΡΟΠΡΣ"
    >> b.seed = 1337
    => 1337
    >> b
    => <Vigenere: @text="ΑΝΘΡΟΠΟΣ", @key="ΑΝΗΡΑΝΗΡ", @seed=1337>
    >> b.random_key
    => "ΩΙΘΘΤΤΦΙ"
    >> b.random_key
    => "ΚΗΦΩΒΗΦΤ"
    >> b.random_key
    => "ΓΚΙΜΒΩΥΟ"
    >> b.seed = 1337
    => 1337
    >> b.random_key
    => "ΩΙΘΘΤΤΦΙ"
    >> b.random_key
    => "ΚΗΦΩΒΗΦΤ"
    >> b.random_key
    => "ΓΚΙΜΒΩΥΟ"
    >> b
    => <Vigenere: @text="ΑΝΘΡΟΠΟΣ", @key="ΓΚΙΜΒΩΥΟ", @seed=1337>
    >> b.encode
    => "ΓΧΠΔΠΟΚΘ"
    >> b.decode
    => "ΑΝΘΡΟΠΟΣ"
    >> exit
    Last edited by mssever; May 1st, 2008 at 07:50 AM. Reason: Added random keys and support for multiple character sets

  6. #16
    Join Date
    Oct 2007
    Beans
    1,914
    Distro
    Lubuntu 12.10 Quantal Quetzal

    Re: Programming Challenge 9: Vigenère cipher

    Quote Originally Posted by bobdob20 View Post
    Zugzwang I would like to see yours, but can't get it to compile. It gives me swing errors. Any suggestions?
    Please paste the full output of the compiler run here since I can only guess what's wrong otherwise. Did you configure your system to use the Sun-JDK? What's the output of "javac -version" and "java -version"?

  7. #17
    Join Date
    Feb 2008
    Location
    UK
    Beans
    24

    Re: Programming Challenge 9: Vigenère cipher

    From javac GUI.java:
    Code:
    GUI.java:23: warning: The serializable class GUI does not declare a static final serialVersionUID field of type long
    	public class GUI extends javax.swing.JFrame {
    	             ^^^
    GUI.java:34: warning: The serializable class IllegalCodeException does not declare a static final serialVersionUID field of type long
    	public class IllegalCodeException extends Exception {};
    	             ^^^^^^^^^^^^^^^^^^^^
    GUI.java:177: error: javax.swing.GroupLayout cannot be resolved to a type
    	javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    	^^^^^^^^^^^^^^^^^^^^^^^
    GUI.java:177: error: javax.swing.GroupLayout cannot be resolved to a type
    	javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    	                                            ^^^^^^^^^^^^^^^^^^^^^^^
    GUI.java:180: error: javax.swing.GroupLayout cannot be resolved
    	jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    	                                  ^^^^^^^^^^^^^^^^^^^^^^^
    GUI.java:184: error: javax.swing.GroupLayout cannot be resolved
    	jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
    	                                  ^^^^^^^^^^^^^^^^^^^^^^^
    GUI.java:273: warning: The parameter evt is never read
    	private void jButtonSaveActionPerformed(java.awt.event.ActionEvent evt) {                                            
    	                                                                   ^^^
    GUI.java:308: warning: The parameter evt is never read
    	private void jButtonLoadActionPerformed(java.awt.event.ActionEvent evt) {                                            
    	                                                                   ^^^
    GUI.java:321: warning: The parameter evt is never read
    	private void jButtonActionActionPerformed(java.awt.event.ActionEvent evt) {                                              
    	                                                                     ^^^
    9 problems (4 errors, 5 warnings)
    javac -version
    Code:
    gcj-4.2 (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu6)
    Copyright (C) 2007 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    java -version
    Code:
    java version "1.6.0"
    OpenJDK Runtime Environment (build 1.6.0-b09)
    OpenJDK 64-Bit Server VM (build 1.6.0-b09, mixed mode)java-1.5.0-sun
    Even after changing the default java version to java-1.5.0-sun i still get the same errors. Also 'gcj GUI.java' gives the same errors, just less warnings.

  8. #18
    Join Date
    Aug 2006
    Beans
    278

    Re: Programming Challenge 9: Vigenère cipher

    Quote Originally Posted by mssever View Post
    Vigenère with a truly random key the same length as the plain text that's only used once is an unbreakable encryption form. Alas, the best source of randomness I have available is /dev/random (which is better than most programming languages provide
    The problem is that the recipient needs to know the key, else you just did a random-number-generator
    Since you`d either need to agree on a key before or transmit the random key to the recipient alongside the encrypted message this aint a viable approach (instead of securely transmitting a message you now need to securely transmitt a key of the same length). You need a deterministic pseudo-random-number generator, like a Linear Feedback Shift Register, then you can generate long keys from seed-values
    Last edited by Npl; April 29th, 2008 at 01:22 PM.

  9. #19
    Join Date
    Oct 2007
    Beans
    1,914
    Distro
    Lubuntu 12.10 Quantal Quetzal

    Re: Programming Challenge 9: Vigenère cipher

    It looks quite suspicious to me that "javac" refers to "gcj" on your computer.

    However, I've removed the need for the GroupLayout class (didn't know that that was the new default layout for the GUI builder in later versions of Netbeans although this only works for Java6 and above), it might work now.

    Eventually, you might need to perform a "sudo update-alternatives --config javac" as well to use Sun's compiler.

  10. #20
    Join Date
    Apr 2007
    Location
    (X,Y,Z) = (0,0,0)
    Beans
    3,715

    Re: Programming Challenge 9: Vigenère cipher

    I'm proud to tell you I got my original Vigenère code to work! This reads data from file, not from user's input as the previous.

    Sorry for malloc & friends.

    UPDATE: Improved some things.
    1) Now it ignores non-alphabetic data leaving it untouched, instead of deleting it. That solves a little bug regarding file-length.
    2) Noticed that I forgot to initialize malloc'ed arrays... (in simple words: my code could have lead to "undefined behaivor")

    PHP Code:
    /*Vigenère Cipher Implementation in C*/

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>

    void Init(char *toinitint n)
    {
        
    int i;
        for(
    0ni++)
            
    toinit[i] = 0;


    void CallArgError(char *appname)
    {
        
    printf("Usage: %s FILE KEY-FILE MODE\n\n"appname);
        
    puts("FILE: Input file to be encrypted/decrypted.");
        
    puts("KEY-FILE: File to be used as key.");
        
    puts("MODE: e = encrypt/d = decrypt");
        exit(
    1);
    }

    int ReadFile(FILE **SourceFilechar **OutputStreamchar *path)
    {
        *
    SourceFile fopen(path"r+");
        if(*
    SourceFile == NULL)
        {
            
    puts("Error reading file");
            exit(
    2);
        }

        
    int length 0;
        
    fseek(*SourceFile0SEEK_END);
        
    length ftell(*SourceFile) - 1;
        
    rewind(*SourceFile);
        *
    OutputStream malloc(length sizeof(*OutputStream));
        if(*
    OutputStream == NULL)
        {
            
    puts("Internal error! Exiting");
            exit(
    2);
        }
        
    Init(*OutputStreamlength);

        
    char c 0;
        
    int i 0;
        while(!
    feof(*SourceFile))
        {
                
    fscanf(*SourceFile"%c", &c);
                if(
    isalpha(c))
                    (*
    OutputStream)[i] = toupper(c);
                else
                    (*
    OutputStream)[i] = c;
                
    i++;
        }

        return 
    length;
    }

    void EnDecrypt(FILE *SourceFilechar *PlainText,
                    
    int PlainTextLengthchar *Key,
                    
    int KeyLengthchar option)
    {
        
    rewind(SourceFile);
        
    int i0;
        
    char buf 0;
        for(
    0PlainTextLengthi++)
        {
            if(
    isalpha(PlainText[i]) && isalpha(Key[a]))
            {
                if(
    option == 'e')
                    
    buf = ((PlainText[i] - 65) + (Key[a] - 65)) % 26;
                else if(
    option == 'd')
                {
                    
    buf = ((PlainText[i] - 65) - (Key[a] - 65)) % 26;
                    if(
    buf 0)
                        
    buf += 26;
                }
        
                
    buf += 65;
            }
            else
                
    buf PlainText[i];
            
            
    fprintf(SourceFile"%c"buf);

            
    a++;
            if(
    >= KeyLength)
                
    0;
        }
    }

    int main(int argcchar **argv)
    {
        if(
    argc != 4)
            
    CallArgError(argv[0]);

        
    FILE *SourceFile NULL;
        
    char *PlainText NULL;
        
    int PlainTextLength ReadFile(&SourceFile, &PlainTextargv[1]);

        
    FILE *KeyFile NULL;
        
    char *Key NULL;
        
    int KeyLength ReadFile(&KeyFile, &Keyargv[2]);
        
    fclose(KeyFile);
        
    KeyFile NULL;

        if((
    strcmp("e"argv[3]) == 0) || (strcmp("d"argv[3]) == 0))
            
    EnDecrypt(SourceFilePlainTextPlainTextLengthKeyKeyLengthargv[3][0]);
        else
            
    CallArgError(argv[0]);

        
    fclose(SourceFile);
        
    SourceFile NULL;
        
    free(Key);
        
    Key NULL;
        
    free(PlainText);
        
    PlainText NULL;
        return 
    0;

    Last edited by nvteighen; May 2nd, 2008 at 06:54 PM. Reason: Improved code

Page 2 of 7 FirstFirst 1234 ... LastLast

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •