lib/encrypted_strings/extensions/string.rb in encrypted_strings-0.2.1 vs lib/encrypted_strings/extensions/string.rb in encrypted_strings-0.3.0
- old
+ new
@@ -1,210 +1,208 @@
require 'openssl'
require 'base64'
-module PluginAWeek #:nodoc:
- module EncryptedStrings
- module Extensions #:nodoc:
- # Adds support for in-place encryption/decryption of strings
- module String
- def self.included(base) #:nodoc:
- base.class_eval do
- attr_accessor :cipher
-
- alias_method :equals_without_encryption, :==
- alias_method :==, :equals_with_encryption
- end
- end
-
- # Encrypts the current string using the specified cipher. The default
- # cipher is sha.
- #
- # Configuration options are cipher-specific. See each individual cipher
- # class to find out the options available.
- #
- # == Example
- #
- # The following uses an SHA cipher to encrypt the string:
- #
- # password = 'shhhh'
- # password.encrypt # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- #
- # == Custom encryption mode
- #
- # The following uses Symmetric cipher (with a default password) to
- # encrypt the string:
- #
- # PluginAWeek::EncryptedStrings::SymmetricCipher.default_password = 'secret'
- # password = 'shhhh'
- # password.encrypt(:symmetric) # => "jDACXI5hMPI=\n"
- #
- # == Custom encryption options
- #
- # Some encryption modes also support additional configuration options
- # that determine how to encrypt the string. For example, SHA supports
- # a salt which seeds the algorithm:
- #
- # password = 'shhhh'
- # password.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
- def encrypt(*args)
- cipher = cipher_from_args(*args)
- encrypted_string = cipher.encrypt(self)
- encrypted_string.cipher = cipher
+module EncryptedStrings
+ module Extensions #:nodoc:
+ # Adds support for in-place encryption/decryption of strings
+ module String
+ def self.included(base) #:nodoc:
+ base.class_eval do
+ attr_accessor :cipher
- encrypted_string
+ alias_method :equals_without_encryption, :==
+ alias_method :==, :equals_with_encryption
end
+ end
+
+ # Encrypts the current string using the specified cipher. The default
+ # cipher is sha.
+ #
+ # Configuration options are cipher-specific. See each individual cipher
+ # class to find out the options available.
+ #
+ # == Example
+ #
+ # The following uses an SHA cipher to encrypt the string:
+ #
+ # password = 'shhhh'
+ # password.encrypt # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ #
+ # == Custom encryption mode
+ #
+ # The following uses Symmetric cipher (with a default password) to
+ # encrypt the string:
+ #
+ # EncryptedStrings::SymmetricCipher.default_password = 'secret'
+ # password = 'shhhh'
+ # password.encrypt(:symmetric) # => "jDACXI5hMPI=\n"
+ #
+ # == Custom encryption options
+ #
+ # Some encryption modes also support additional configuration options
+ # that determine how to encrypt the string. For example, SHA supports
+ # a salt which seeds the algorithm:
+ #
+ # password = 'shhhh'
+ # password.encrypt(:sha, :salt => 'secret') # => "3b22cbe4acde873c3efc82681096f3ae69aff828"
+ def encrypt(*args)
+ cipher = cipher_from_args(*args)
+ encrypted_string = cipher.encrypt(self)
+ encrypted_string.cipher = cipher
- # Encrypts this string and replaces it with the encrypted value. This
- # takes the same parameters as #encrypt, but returns the same string
- # instead of a different one.
- #
- # == Example
- #
- # password = 'shhhh'
- # password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
- # password # => "qSg8vOo6QfU=\n"
- def encrypt!(*args)
- encrypted_string = encrypt(*args)
- self.cipher = encrypted_string.cipher
-
- replace(encrypted_string)
- end
+ encrypted_string
+ end
+
+ # Encrypts this string and replaces it with the encrypted value. This
+ # takes the same parameters as #encrypt, but returns the same string
+ # instead of a different one.
+ #
+ # == Example
+ #
+ # password = 'shhhh'
+ # password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
+ # password # => "qSg8vOo6QfU=\n"
+ def encrypt!(*args)
+ encrypted_string = encrypt(*args)
+ self.cipher = encrypted_string.cipher
- # Is this string encrypted? This will return true if the string is the
- # result of a call to #encrypt or #encrypt!.
- #
- # == Example
- #
- # password = 'shhhh'
- # password.encrypted? # => false
- # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password.encrypted? # => true
- def encrypted?
- !cipher.nil?
- end
+ replace(encrypted_string)
+ end
+
+ # Is this string encrypted? This will return true if the string is the
+ # result of a call to #encrypt or #encrypt!.
+ #
+ # == Example
+ #
+ # password = 'shhhh'
+ # password.encrypted? # => false
+ # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password.encrypted? # => true
+ def encrypted?
+ !cipher.nil?
+ end
+
+ # Decrypts this string. If this is not a string that was previously
+ # encrypted, the cipher must be specified in the same way that it is
+ # when encrypting a string.
+ #
+ # == Example
+ #
+ # Without being previously encrypted:
+ #
+ # password = "qSg8vOo6QfU=\n"
+ # password.decrypt(:symmetric, :password => 'secret') # => "shhhh"
+ #
+ # After being previously encrypted:
+ #
+ # password = 'shhhh'
+ # password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
+ # password.decrypt # => "shhhh"
+ def decrypt(*args)
+ raise ArgumentError, 'Cipher cannot be inferred: must specify it as an argument' if args.empty? && !encrypted?
- # Decrypts this string. If this is not a string that was previously
- # encrypted, the cipher must be specified in the same way that it is
- # when encrypting a string.
- #
- # == Example
- #
- # Without being previously encrypted:
- #
- # password = "qSg8vOo6QfU=\n"
- # password.decrypt(:symmetric, :password => 'secret') # => "shhhh"
- #
- # After being previously encrypted:
- #
- # password = 'shhhh'
- # password.encrypt!(:symmetric, :password => 'secret') # => "qSg8vOo6QfU=\n"
- # password.decrypt # => "shhhh"
- def decrypt(*args)
- raise ArgumentError, 'Cipher cannot be inferred: must specify it as an argument' if args.empty? && !encrypted?
-
- cipher = args.empty? && self.cipher || cipher_from_args(*args)
- encrypted_string = cipher.decrypt(self)
- encrypted_string.cipher = nil
-
- encrypted_string
- end
+ cipher = args.empty? && self.cipher || cipher_from_args(*args)
+ encrypted_string = cipher.decrypt(self)
+ encrypted_string.cipher = nil
- # Decrypts this string and replaces it with the decrypted value This
- # takes the same parameters as #decrypt, but returns the same string
- # instead of a different one.
- #
- # For example,
- #
- # password = "qSg8vOo6QfU=\n"
- # password.decrypt!(:symmetric, :password => 'secret') # => "shhhh"
- # password # => "shhhh"
- def decrypt!(*args)
- value = replace(decrypt(*args))
- self.cipher = nil
- value
- end
-
- # Can this string be decrypted? Strings can only be decrypted if they
- # have previously been decrypted *and* the cipher supports decryption.
- # To determine whether or not the cipher supports decryption, see the
- # api for the cipher.
- def can_decrypt?
- encrypted? && cipher.can_decrypt?
- end
-
- # Tests whether the other object is equal to this one. Encrypted strings
- # will be tested not only on their encrypted strings, but also by
- # decrypting them and running tests against the decrypted value.
- #
- # == Equality with strings
- #
- # password = 'shhhh'
- # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password == "shhhh" # => true
- #
- # == Equality with encrypted strings
- #
- # password = 'shhhh'
- # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password == 'shhhh' # => true
- #
- # another_password = 'shhhh'
- # another_password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
- # password == another_password # => true
- def equals_with_encryption(other)
- if !(is_equal = equals_without_encryption(other)) && String === other
- if encrypted?
- if other.encrypted?
- # We're both encrypted, so check if:
- # (1) The other string is the encrypted value of this string
- # (2) This string is the encrypted value of the other string
- # (3) The other string is the encrypted value of this string, decrypted
- # (4) This string is the encrypted value of the other string, decrypted
- is_string_equal?(self, other) || is_string_equal?(other, self) || self.can_decrypt? && is_string_equal?(self.decrypt, other) || other.can_decrypt? && is_string_equal?(other.decrypt, self)
- else
- # Only we're encrypted
- is_string_equal?(other, self)
- end
+ encrypted_string
+ end
+
+ # Decrypts this string and replaces it with the decrypted value This
+ # takes the same parameters as #decrypt, but returns the same string
+ # instead of a different one.
+ #
+ # For example,
+ #
+ # password = "qSg8vOo6QfU=\n"
+ # password.decrypt!(:symmetric, :password => 'secret') # => "shhhh"
+ # password # => "shhhh"
+ def decrypt!(*args)
+ value = replace(decrypt(*args))
+ self.cipher = nil
+ value
+ end
+
+ # Can this string be decrypted? Strings can only be decrypted if they
+ # have previously been decrypted *and* the cipher supports decryption.
+ # To determine whether or not the cipher supports decryption, see the
+ # api for the cipher.
+ def can_decrypt?
+ encrypted? && cipher.can_decrypt?
+ end
+
+ # Tests whether the other object is equal to this one. Encrypted strings
+ # will be tested not only on their encrypted strings, but also by
+ # decrypting them and running tests against the decrypted value.
+ #
+ # == Equality with strings
+ #
+ # password = 'shhhh'
+ # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password == "shhhh" # => true
+ #
+ # == Equality with encrypted strings
+ #
+ # password = 'shhhh'
+ # password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password == 'shhhh' # => true
+ #
+ # another_password = 'shhhh'
+ # another_password.encrypt! # => "66c85d26dadde7e1db27e15a0776c921e27143bd"
+ # password == another_password # => true
+ def equals_with_encryption(other)
+ if !(is_equal = equals_without_encryption(other)) && String === other
+ if encrypted?
+ if other.encrypted?
+ # We're both encrypted, so check if:
+ # (1) The other string is the encrypted value of this string
+ # (2) This string is the encrypted value of the other string
+ # (3) The other string is the encrypted value of this string, decrypted
+ # (4) This string is the encrypted value of the other string, decrypted
+ is_string_equal?(self, other) || is_string_equal?(other, self) || self.can_decrypt? && is_string_equal?(self.decrypt, other) || other.can_decrypt? && is_string_equal?(other.decrypt, self)
else
- if other.encrypted?
- # Only the other string is encrypted
- is_string_equal?(self, other)
- else
- # Neither are encrypted and equality test didn't work before, so
- # they can't be equal
- false
- end
+ # Only we're encrypted
+ is_string_equal?(other, self)
end
else
- # The other value wasn't a string, so we can't check encryption equality
- is_equal
- end
- end
-
- private
- def is_string_equal?(value, encrypted_value) #:nodoc:
- # If the encrypted value can be decrypted, then test against the decrypted value
- if encrypted_value.can_decrypt?
- encrypted_value.decrypt.equals_without_encryption(value)
+ if other.encrypted?
+ # Only the other string is encrypted
+ is_string_equal?(self, other)
else
- # Otherwise encrypt this value based on the cipher used on the encrypted value
- # and test the equality of those strings
- encrypted_value.equals_without_encryption(encrypted_value.cipher.encrypt(value))
+ # Neither are encrypted and equality test didn't work before, so
+ # they can't be equal
+ false
end
end
-
- # Builds the cipher to use from the given arguments
- def cipher_from_args(*args) #:nodoc:
- options = args.last.is_a?(Hash) ? args.pop : {}
- name = (args.first || :sha).to_s.gsub(/(?:^|_)(.)/) {$1.upcase}
- PluginAWeek::EncryptedStrings.const_get("#{name}Cipher").new(options)
- end
+ else
+ # The other value wasn't a string, so we can't check encryption equality
+ is_equal
+ end
end
+
+ private
+ def is_string_equal?(value, encrypted_value) #:nodoc:
+ # If the encrypted value can be decrypted, then test against the decrypted value
+ if encrypted_value.can_decrypt?
+ encrypted_value.decrypt.equals_without_encryption(value)
+ else
+ # Otherwise encrypt this value based on the cipher used on the encrypted value
+ # and test the equality of those strings
+ encrypted_value.equals_without_encryption(encrypted_value.cipher.encrypt(value))
+ end
+ end
+
+ # Builds the cipher to use from the given arguments
+ def cipher_from_args(*args) #:nodoc:
+ options = args.last.is_a?(Hash) ? args.pop : {}
+ name = (args.first || :sha).to_s.gsub(/(?:^|_)(.)/) {$1.upcase}
+ EncryptedStrings.const_get("#{name}Cipher").new(options)
+ end
end
end
end
::String.class_eval do
- include PluginAWeek::EncryptedStrings::Extensions::String
+ include EncryptedStrings::Extensions::String
end