What is going wrong here?

Notice the initialization of both classes in each of the examples, if
the instance variable is in initialization or in the called method is
the only thing changing between these examples.

I don't understand why I can't begin both classes with the
initialization
set to what I want it to be, I would think that the initialization value
would be consistent for the objects entire life but it only works for
the first pass, the second time through it doesn't work. The only way to
fix this is to not have the respective instance variable set in
initialization with either of the two classes. What is going wrong here?
I like to set variables during initialization but it clearly doesn't
work how I would hope, I would like to understand what is going wrong
because even though I can get it to work I don't see why it doesn't work
in some cases.

Maybe it has to do with my poor use of instance variables :/, if this is
the case I would still like to know what is going on so I can find a way
to work around it

when I say it doesn't work I mean the output is not correct, it gives me
random looking output the second time even though it should give the
plaintext.

###############This way doesn't work##################

class EncryptionBackend
require 'openssl'

  def initialize
    @cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")
  end

  def encrypt(key, plaintext)
  puts plaintext
    @cipher.encrypt
    @cipher.key = key
    ciphertext = @cipher.update(plaintext)
    ciphertext << @cipher.final
    @cipher.reset
    puts ciphertext
    @ciphertext = ciphertext

  end
end

class EncryptMessage
require 'openssl'

  def initialize
    @crypto = EncryptionBackend.new
  end

  def twice
    @message = "whatever"
    encrypt_message
    encrypt_message

  end

  def encrypt_message
    @sha256 = OpenSSL::Digest::SHA256.new
    key = @sha256.digest("whatever")
    @message = @crypto.encrypt(key, @message)
  end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

###############This way works###################

class EncryptionBackend
require 'openssl'

  def initialize
    @cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")
  end

  def encrypt(key, plaintext)
  puts plaintext
    @cipher.encrypt
    @cipher.key = key
    ciphertext = @cipher.update(plaintext)
    ciphertext << @cipher.final
    @cipher.reset
    puts ciphertext
    @ciphertext = ciphertext

  end
end

class EncryptMessage
require 'openssl'

  def initialize
    #nothing
  end

  def twice
    @message = "whatever"
    encrypt_message
    encrypt_message

  end

  def encrypt_message
    @crypto = EncryptionBackend.new
    @sha256 = OpenSSL::Digest::SHA256.new
    key = @sha256.digest("whatever")
    @message = @crypto.encrypt(key, @message)
  end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

###############this way works though##################

class EncryptionBackend
require 'openssl'

  def initialize
    #nothing
  end

  def encrypt(key, plaintext)
  @cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")
  puts plaintext
    @cipher.encrypt
    @cipher.key = key
    ciphertext = @cipher.update(plaintext)
    ciphertext << @cipher.final
    @cipher.reset
    puts ciphertext
    @ciphertext = ciphertext

  end
end

class EncryptMessage
require 'openssl'

  def initialize
    @crypto = EncryptionBackend.new
  end

  def twice
    @message = "whatever"
    encrypt_message
    encrypt_message

  end

  def encrypt_message
    @sha256 = OpenSSL::Digest::SHA256.new
    key = @sha256.digest("whatever")
    @message = @crypto.encrypt(key, @message)
  end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

################This way also works#######################

class EncryptionBackend
require 'openssl'

  def initialize
    @cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")
  end

  def encrypt(key, plaintext)
  puts plaintext
    @cipher.encrypt
    @cipher.key = key
    ciphertext = @cipher.update(plaintext)
    ciphertext << @cipher.final
    @cipher.reset
    puts ciphertext
    @ciphertext = ciphertext

  end
end

class EncryptMessage
require 'openssl'

  def initialize
    ##nothing
  end

  def twice
    @message = "whatever"
    encrypt_message
    encrypt_message

  end

  def encrypt_message
    @crypto = EncryptionBackend.new
    @sha256 = OpenSSL::Digest::SHA256.new
    key = @sha256.digest("whatever")
    @message = @crypto.encrypt(key, @message)
  end
end

message_encrypt = EncryptMessage.new
message_encrypt.twice

···

--
Posted via http://www.ruby-forum.com/.

Hi,

What's your Ruby version? If you actually get different output for the
three variants (which you shouldn't), then this might be a bug in the
OpenSSL class.

You should note, however, that your code will do the following: It takes
the string "whatever" as the plaintext, encrypts it, then takes the
encrypted string as the plaintext and encrypts it again.

So your output will be something like

whatever (first plaintext)
ABC (encryped "whatever")
ABC (second plaintext = encrypted "whatever")
XYZ (encrypted ABC)

If that's not what you want, then you have to change your code. This
might be a good idea, anyway. You seem to be confused about when to use
instance variables, because most of them simply don't make any sense.

In the first class, you create the instance variable @ciphertext in the
encrypt method, but you use it nowhere. Then what do you need it for? In
the second class, you have the @sha256 variable, but you overwrite it on
every method call. This makes no sense. A local variable is what you
want.

Use instance variables *only* if you actually want to store a value
persistently inside the object. Do *not* use them to pass values to
methods or whatever.

···

--
Posted via http://www.ruby-forum.com/.

I used an instance variable for @ciphertext because I was getting it
with @crypt.instance_variable_get("@ciphertext") but then I realized I
can do it in a much nicer way.

Yes I can confirm that the way I originally said does not work doesn't
work, I am using ruby ruby 1.9.3p125 on Ubuntu 64 bit

the first way outputs this

whatever
�a�xtT��
�a�xtT��
�G��E

the other two ways both output this

whatever
�a�xtT��
�a�xtT��
whatever

···

--
Posted via http://www.ruby-forum.com/.

okay the problem is that .reset is not actually reseting the ciphers
state as shown here:

require 'openssl'

message = "whatever"
sha256 = OpenSSL::Digest::SHA256.new
cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")

2.times do
key = @sha256.digest("whatever")
@sha256.reset
@cipher.encrypt
@cipher.key = key
ciphertext = @cipher.update(@message)
ciphertext << @cipher.final
@cipher.reset
puts ciphertext
end

#> �a�xtT��
#> 9]K���/

would love if someone can confirm this bug and please get it fixed ASAP
thanks :slight_smile:

···

--
Posted via http://www.ruby-forum.com/.

irb(main):001:0> require 'openssl'
=> true
irb(main):002:0> message = "whatever"
=> "whatever"
irb(main):003:0> @sha256 = OpenSSL::Digest::SHA256.new
=> #<OpenSSL::Digest::SHA256:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855>
irb(main):004:0> @cipher = OpenSSL::Cipher::Cipher.new("AES-256-CTR")
=> #<OpenSSL::Cipher::Cipher:0x00000002467830>
irb(main):005:0> 2.times do
irb(main):006:1* key = @sha256.digest("whatever")
irb(main):007:1> @sha256.reset
irb(main):008:1> @cipher.encrypt
irb(main):009:1> @cipher.key = key
irb(main):010:1> ciphertext = @cipher.update(message)
irb(main):011:1> ciphertext << @cipher.final
irb(main):012:1> @cipher.reset
irb(main):013:1> puts ciphertext
irb(main):014:1> end
�a�xtT��
9]K���/
=> 2

···

--
Posted via http://www.ruby-forum.com/.

roob noob wrote in post #1061072:

use OFB instead of CTR please you need the cutting edge version of
OpenSSL for CTR to work

OFB gives me the right output for all three variants:

whatever
�a�xtT��
�a�xtT��
whatever

the method is *always* dependent on outer variables regardless of if
they are passed with @ or with ().

No, without the instance variables, the method will always return the
same value for the same arguments. Its behaviour doesn't depend on outer
variables.

Compare these two methods:

$z = 10
def add(x, y)
  x + y
end
def add2(x, y)
  x + y + $z
end

The first method doesn't use instance variables. add(1, 1) will always
return 2, no matter how the outer world looks like. But add2(1, 1) may
yield different results, depending on the value of $z.

Another important difference is that "() methods" have a clean
interface: all input comes from the arguments, and all output is in the
return value. There are no "magical" values from the outside involved.
This is much easier to track and test, especially if you haven't written
the code yourself.

I do agree that
.instance_variable_get() is ugly though and I am going through my code
and removing it where possible, making the called methods end on what I
want to get from them. In some cases I need to get multiple instance
variables though, maybe I should split it up into many smaller methods
in these cases? How else am I supposed to get multiple instance
variables from a method in one class to a method in another class?

Methods can also return hashes or arrays. This way you can pass multiple
values.

For example:

# this methods calculates the minimum, maximum and average
# of a list of numbers

def min_max_avg(values)
  {
    min: values.min,
    max: values.max,
    avg: values.reduce(:+).to_f/values.length
  }
end

I can't use () in these cases without greatly decreasing the flexibility
of my code, since () assumes that I have a class/method to send the
resulting variables to and .instance_variable_get() only assumes that I
have the variables to get. What if in some cases I want the resulting
variables to go one place and in other cases I want them to go somewhere
else? "Pulling" from the calling method with .instance_variable_get
makes more sense than "pushing" from the called method with () in these
cases.

I do understand the purpose of this idea, and it may even be technically
efficient. But it's still bad style, because how the methods works is
obscure. Imagine you're a programmer using this code from somebody else.
What do you find easier to use:

"encrypt(message) returns the AES-256 encryption of message"

or

"Set the @message variable in an instance of Encrypt and call the
encrypt() method. After this, get the result from the @ciphertext
variable. Be careful not to change the variables in between."

By the way, you shouldn't use "instance_variable_get" at all. This is
simply the wrong method for your purpose. Define getter methods for the
variables (via attr_reader) and call them.

···

--
Posted via http://www.ruby-forum.com/\.

Honestly I see very little difference between

"
message = "whatever"
encrypt(message) #returns the AES-256 encryption of message
"

and

"
@message
encrypt #returns the AES-256 encryption of @message
"

except that with an instance variable I can pass the value seamlessly to
where it needs to go without sending it down the call chain and keeping
track of a bunch of variables and changes to the variable.

  class AddNumbersAndLetters

    def get_input
      input = gets.chop
      add_numbers(input)
    end

     def add_numbers(input)
       numbers_added = input + "123"
       add_letters(numbers_added)
     end

     def add_letters(input)
        letters_added = input + "abc"
     end
  end

does not look as nice to me as

class AddNumbersAndLetters

    def get_input
      @input = gets.chop
      add_numbers
      add_letters
    end

     def add_numbers
       @input += "123"
     end

     def add_letters
        @input += "abc"
     end
  end

especially if there are a lot more methods involved and I would
otherwise need to keep passing input down the call chain with (),
especially if I want to add numbers and then add letters and then add
numbers again and then add letters again, which just becomes a mess
passing with () but with @ it is as simply as doing this

add_numbers
add_letters
add_numbers
add_letters

However, enough Rubyists have told me to avoid using instance variables
in this way that I will take your advice. I don't personally think it is
the intuitive way to do things or that it makes it easier though.

···

--
Posted via http://www.ruby-forum.com/.

I guess I could do this though, to make it a more fair comparison. Maybe
I just need to learn to use () better.

class AddNumbersAndLetters

    def get_input
      input = gets.chop
      add_numbers(input)
    end

     def add_numbers(input)
       input += "123"
       add_letters(input)
     end

     def add_letters(input)
        input += "abc"
     end
  end

···

--
Posted via http://www.ruby-forum.com/.

sorry for post spam, but would this be the appropriate way to do it? I
still prefer the @ way, but I want to do things right.

class AddNumbersAndLetters

     def add_numbers(input)
       input += "123"
       add_letters(input)
     end

     def add_letters(input)
        input += "abc"
     end
  end

add_stuff = AddNumbersAndLetters.new

input = gets.chop

input = add_stuff.add_numbers(input)
input = add_stuff.add_letters(input)
input = add_stuff.add_letters(input)
input = add_stuff.add_numbers(input)
input = add_stuff.add_letters(input)

···

--
Posted via http://www.ruby-forum.com/.

First let me thank you for all of the help you have been :). It is much
appreciated, I find that the more I learn Ruby and start to get a grasp
on the basics, the more questions I end up having that are not easily
answered by prepackaged guides, ie: I need to start asking people.

Second, how does this look? These are snippets from a class that
estimates password entropy. Before I was using instance variables for
@entropy_bits and calling methods like in my previous examples, now I am
trying to use inject I think I at least come close to doing it right. My
program does work anyway.

def estimate_password_entropy(password)

    evaluate_entropy = [
    contains_dictionary_word?(password),
    contains_special_character?(password),
    contains_upcase_character?(password),
    contains_lowcase_character?(password),
    contains_number?(password),
    length_estimated_entropy(password)
    ]
    puts evaluate_entropy.to_s
    entropy_bits = evaluate_entropy.inject(:+)
  end

def contains_dictionary_word?(password)
  entropy_bits = 0
  passed_dictionary_test = true
  File.open("#{RELATIVEPATH}/data/dictionary") do |dictionary|
    while line = dictionary.gets
      passed_dictionary_test = false and break if
password.include?(line.chop)
    end
    entropy_bits = 6 if passed_dictionary_test and password.length > 4
    end
    return entropy_bits
  end

#all other tests fit the following pattern

  def contains_special_character?(password)
    entropy_bits = 0
    special_characters = %w{ ~ ! @ # $ % ^ & * ( ) _ - + = \{ [ ] | \ :
; " ' < , > . ? / \} }
    special_characters.each do |special_character|
    if password.include?(special_character) then entropy_bits = 1.5 and
break
     end
    end
    return entropy_bits
  end

···

--
Posted via http://www.ruby-forum.com/.

This looks good. :slight_smile:

Since you already said that the character tests follow the same pattern,
you might wanna think about writing only one generalized method. For
example, you could put the character sets and the corresponding "scores"
in an array and then let a method iterate over it. You don't even have
to write the actual characters down but use regular expressions instead:

/\p{Lower}/

This regular expression matches any string with a lower case letter (of
any language) in it. If you only want the latin letters from a to z, you
can instead use the pattern

/[a-z]/

This narrows the test down to one line: password =~ pattern

As a complete example:

···

#------------------------------------------
class Entropy

  # the scores are just made up
  CHARACTER_SCORES = {
    # special characters
    # = printable ASCII characters which are not alphanumeric
    /[\p{ASCII}&&\p{Graph}&&\p{^Alnum}]/ => 11,
    # uppercase letters
    /[A-Z]/ => 22,
    # lowercase letter
    /[a-z]/ => 33,
    # digits
    /[0-9]/ => 44
  }

  def test_characters password
    CHARACTER_SCORES.inject 0 do |sum, (pattern, score)|
      password =~ pattern ? sum + score : sum
    end
  end

end
#------------------------------------------

By the way, most of the time you don't need lowlevel structures like the
while statement. Ruby has a lot of iterators which do the same thing in
a lot less lines.

For example, you could rewrite the dictionary method to this:

#------------------------------------------
def contains_dictionary_word?(password)
  entropy_bits = 0
  passed_dictionary_test =
    File.foreach("#{RELATIVEPATH}/data/dictionary").any? do |line|
      password.include? line.chop
    end
  entropy_bits = 6 if passed_dictionary_test and password.length > 4
  return entropy_bits
end
#------------------------------------------

The "while gets" is replaced with "File.foreach". And the "break false"
is replaced with the "any?" iterator.

On last thing: You should be careful with method names. A method called
"contains_dictionary_word?" looks all like it returns either true or
false. It it returns a score instead, this may lead to confusion. So I'd
rather call it "test_dictionary" or so.

--
Posted via http://www.ruby-forum.com/.

How do I iterate through a Class so that I can perform some action on each object? For example...

MyClass.each do {|obj| DO SOME STUFF}

It looks like I have to create the .each method in my class. I tried something like what's mentioned here...

...but haven't gotten it to work.

Matt

roob noob wrote in post #1061056:

I used an instance variable for @ciphertext because I was getting it
with @crypt.instance_variable_get("@ciphertext") but then I realized I
can do it in a much nicer way.

The method should simply return the encrypted string and do nothing
else. Like I said earlier: Don't misuse instance variables to pass
values around. This is not only ugly and cumbersome but also prone to
error, because the method then becomes dependend on some outer
variables. What if the value is accidently changed by another method?
This will break your code, and you'll have a hard time finding the
reason.

We've already discussed this in an earlier thread:

I don't know how you've come to adept this programming style, but you
should get rid of it right away. This also applies to the
"instance_variable_get". While this does work, it's very bad style and
more of a hack. Outer objects are supposed to use the getters and
setters and not fumble with the actual variables inside the object.

can you please confirm that each version works correctly for you on your
version of ruby, simply by copy pasting it ? Particularly interested in
the version I have listed as not working.

Sorry, I can't help you with that, because I can't get the CTR mode
working.

edit: also in my full program I set @sha256 in initialize and then reset
it through a lot of methods, but in this case a local variable would
certainly be best

Well, a local variable is not only "better" in this case. It's the only
right way to do this. Using an instance variable doesn't make any sense,
because you don't want the SHA256 object to be a property of the object.

···

--
Posted via http://www.ruby-forum.com/\.

roob noob wrote in post #1061170:

Honestly I see very little difference between

"
message = "whatever"
encrypt(message) #returns the AES-256 encryption of message
"

and

"
@message
encrypt #returns the AES-256 encryption of @message
"

The difference is that the first method works on its own. You don't need
a certain context or specific preparations, you simply pass a string and
get the encrypted string.

On the other hand, the second method is completely dependend on the
outer world. You cannot even call it without having set the @message
variable before. And you have to make sure the value isn't changed in
the meantime (which makes the whole program rather "unstable" and
completely unsuitable for threaded applications).

The worst thing is that these dependencies aren't even obvious from the
code. You'd have to write a comment and explain which steps have to be
taken. Otherwise, there will be strange errors like "nil doesn't have a
+ method".

Well, if you only write small programs for yourself and don't plan to
publish them, this all might be acceptable. But I wouldn't even start to
adept this programming style, because it will get in your way as soon as
your applications become bigger or you share the code with others.

This is a bit like arguing about if you can use a hammer to put a screw
in. Well, if you only got a few screws and the result doesn't really
matter, then you *can* do it. It does work. But it's the wrong way and
it isn't suitable as a general approach.

By the way: Your programming style wouldn't even work in most other
languages. It relies on the fact that Ruby is rather sloppy with
instance variables and allows them to be created on the fly by any
method. In more strict programming languages, every variable has to be
declared first, which would make the whole approach rather tedious.

roob noob wrote in post #1061186:

sorry for post spam, but would this be the appropriate way to do it? I
still prefer the @ way, but I want to do things right.

class AddNumbersAndLetters

     def get_input
       input = gets.chop
       input = add_numbers(input)
       input = add_letters(input)
       input = add_letters(input)
       input = add_numbers(input)
       input = add_letters(input)
     end

     def add_numbers(input)
       input += "123"
     end

     def add_letters(input)
        input += "abc"
     end
  end

Yes, this makes a lot more sense. A more advanced approach would be to
only write a "rule" how the string should be built and then let the
program do the actual method chaining on its own:

input = gets.chop
transform_input = [
  :add_numbers,
  :add_letters,
  :add_letters,
  :add_numbers,
  :add_letters
]
transform_input.inject input do |result, method|
  send method, result
end

See

on how the inject method works.

By the way, you should replace the "+=" with a simple "+". You don't
want to reassign the input parameter but simply get the result of adding
"123" to input.

···

--
Posted via http://www.ruby-forum.com/\.

Two notes:

1. By common ruby convention, methods ending with a ? return a
boolean, not an int

2. This does not do what you think it does:

  passed_dictionary_test = false and break if password.include?(line.chop)

it parses as

(passed_dictionary_test = false) and (break if password.include?(line.chop))

then (passed_dictionary_test = false) is an expression, which returns
its rhs, which is false, so the bit after the "and" is never
evaluated. The following code is illustrative - guess what it does,
then run it and see:

x = 0
passed = true
while x < 10
  passed = false and break if x == 5
  puts "x = #{x}, passed = #{passed}"
  x += 1
end

This form of your original code works:

    if password.include?(line.chop)
        passed_dictionary_test = false
        break
    end

martin

···

On Thu, May 17, 2012 at 6:38 PM, roob noob <lists@ruby-forum.com> wrote:

def contains_dictionary_word?(password)
entropy_bits = 0
passed_dictionary_test = true
File.open("#{RELATIVEPATH}/data/dictionary") do |dictionary|
while line = dictionary.gets
passed_dictionary_test = false and break if
password.include?(line.chop)
end
entropy_bits = 6 if passed_dictionary_test and password.length > 4
end
return entropy_bits
end

do you want to find all objects that belong to that class? you need to
use ObjectSpace for that:

ObjectSpace.each_object(classname) {|obj| do something}

the .each method in your class is for individual objects to provide
internal iterators (e.g. if you're implementing a collection class)

martin

···

On Wed, May 16, 2012 at 2:16 PM, Matt Mencel <MR-Mencel@wiu.edu> wrote:

How do I iterate through a Class so that I can perform some action on each object? For example...

MyClass.each do {|obj| DO SOME STUFF}

It looks like I have to create the .each method in my class. I tried something like what's mentioned here...
How do I add 'each' method to Ruby object (or should I extend Array)? - Stack Overflow

...but haven't gotten it to work.

Matt

Matt Mencel wrote in post #1061049:

How do I iterate through a Class so that I can perform some action on
each object? For example...

Please create your own thread. This has nothing to do with this topic.

···

--
Posted via http://www.ruby-forum.com/\.

Martin DeMello wrote in post #1061234:

2. This does not do what you think it does:

  passed_dictionary_test = false and break if
password.include?(line.chop)

it parses as

(passed_dictionary_test = false) and (break if
password.include?(line.chop))

That's not true (at least not in Ruby 1.9). The "if" modifier has lower
precedence then the "and", so the expression is parsed as expected:

(passed_dictionary_test = false and break) if ...

However, you're right about the "and": Since the left operand is always
false, the "break" will never be executed.

So you shouldn't read the "and" as "do this and then that". It rather
means "do this, and if you were successful, do that".

then (passed_dictionary_test = false) is an expression, which returns
its rhs, which is false, so the bit after the "and" is never
evaluated. The following code is illustrative - guess what it does,
then run it and see:

x = 0
passed = true
while x < 10
  passed = false and break if x == 5
  puts "x = #{x}, passed = #{passed}"
  x += 1
end

Have to tested it yourself? If you were right, then "passed" would
always be false. But it's only after x has become 5.

···

--
Posted via http://www.ruby-forum.com/\.

Yup that worked....

Thanks,
Matt

···

----- Original Message -----
From: "Martin DeMello" <martindemello@gmail.com>
To: "ruby-talk ML" <ruby-talk@ruby-lang.org>
Sent: Wednesday, May 16, 2012 4:25:08 PM
Subject: Re: How to Iterate Through a Class

do you want to find all objects that belong to that class? you need to
use ObjectSpace for that:

ObjectSpace.each_object(classname) {|obj| do something}

the .each method in your class is for individual objects to provide
internal iterators (e.g. if you're implementing a collection class)

martin

On Wed, May 16, 2012 at 2:16 PM, Matt Mencel <MR-Mencel@wiu.edu> wrote:

How do I iterate through a Class so that I can perform some action on each object? For example...

MyClass.each do {|obj| DO SOME STUFF}

It looks like I have to create the .each method in my class. I tried something like what's mentioned here...
How do I add 'each' method to Ruby object (or should I extend Array)? - Stack Overflow

...but haven't gotten it to work.

Matt

Oops, yes, you're right, I should have tested it. Ignore my mail.

martin

···

On Thu, May 17, 2012 at 8:39 PM, Jan E. <lists@ruby-forum.com> wrote:

it parses as

(passed_dictionary_test = false) and (break if
password.include?(line.chop))

That's not true (at least not in Ruby 1.9). The "if" modifier has lower
precedence then the "and", so the expression is parsed as expected:

(passed_dictionary_test = false and break) if ...

However, you're right about the "and": Since the left operand is always
false, the "break" will never be executed.