Brand new Rails application.
Rails version 5.0.0.1, Ruby version 2.4.0preview2.
Create application "demo", run a simple scaffold generate Product, and get an error when trying to view the scaffold's overview page (base index file still loads the Welcome to Rails screen fine):
ArgumentError in ProductsController#index
key must be 32 bytes:
cipher = new_cipher
cipher.encrypt
cipher.key = #secret
# Rely on OpenSSL for the initialization vector
iv = cipher.random_iv
The problem line is apparently cipher.key = #secret.
I've seen various mentions on the github repo for Rails mentioning this issue, but all implied it was now resolved in Rails 5.0.0.1
Ok, there was a slight misunderstanding on my part, looks like the fix is coming in 5.0.1 not 5.0.0.1
https://github.com/rails/rails/issues/26694
Please use Digest::MD5 to achive 32 bytes
require 'openssl'
require 'digest'
require 'base64'
data = "encrypt me"
secret_key = "asd3dssdf34HDas"
c = OpenSSL::Cipher.new("aes-256-cbc")
c.encrypt
c.key = Digest::MD5.hexdigest(secret_key) # this will convert key length into 32
encrypted_data = c.update(data.to_s) + c.final
encrypted_data = Base64.urlsafe_encode64(encrypted_data, padding: false) #padding: false will remove '/', '+' from encrypted data
encrypted_data.gsub! "\n",""
Or Simply use secret key of length 32 bytes
data = "encrypt me"
secret_key = "Aswertyuioasdfghjkqwertyuiqwerty"
c = OpenSSL::Cipher.new("aes-256-cbc")
c.encrypt
c.key = secret_key
encrypted_data = c.update(data.to_s) + c.final
Finally found problem! It was from a bugfix... https://bugs.ruby-lang.org/issues/12561
If you are using cipher e.g. 'aes-256-cfb', the key_len is 32, found by:
require 'openssl'
cipher = OpenSSL::Cipher.new('aes-256-cfb')
cipher.key_len # => 32
We had mistakenly thought we needed to send a 256 character nonce, but actually you are supposed to send a 32 character nonce - or
use cipher.random_key (which internally uses the key_len). It never used to be a problem because openssl truncated the nonce... but now you need to send the right lengthed nonce.
We got this error upgrading ruby from 2.3.4 to 2.4.2.
This issue turns out to be connected to the key you are using. Without changing your key you can use the code below to transform your key to 32 bytes:
attr_encrypted :attribute, key: ENV['MY_KEY'].bytes[0..31].pack( "c" * 32 )
try this:
rake db:create
rake db:migrate
then, the most important thing:
bundle update
This works for me.
Use random_key so it always fit.
key = cipher.random_key
cipher.key = key
reference http://ruby-doc.org/stdlib-2.0.0/libdoc/openssl/rdoc/OpenSSL/Cipher.html
Solution:
Edit your Gemfile
Add the following line: gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
bundle install
Optional: I am using ruby2-4.1 . (rvm install ruby-2.4.1)
Rational: The rails version prior to 5.0.0 seems to have a bug that causes this issue. The bug has been resolved in the latest version of Rails. If you hare following the Rails Installation Guide (http://railsapps.github.io/installrubyonrails-mac.html) you will probably encounter this problem as of this posting date.
This fix does work, and is verified by
I was having this problem too and fixed it by running
bundle update
Make sure that you have the latest version of rails installed.
Had the same error:
Running bundle update should do the trick
Related
I have the following header:
From: =?iso-8859-1?Q?Marta_Falc=E3o?= <marta.falcao#example.com.br>
I can easily split out the stuff before the <, which leaves me with
"=?iso-8859-1?Q?Marta_Falc=E3o?="
What can I use to turn this into "Marta Falcão"?
Using the newer Mail gem:
Mail::Encodings.value_decode(str) or
Mail::Encodings.unquote_and_convert_to(str, to_encoding)
Thanks to Roland Illig for his comment, which led me to two options:
install rfc2047-ruby and call Rfc2047.decode(header)
install TMail and call TMail::Unquoter.unquote_and_convert_to(header, 'utf-8') or better yet TMail::Address.parse(header).friendly, the latter of which strips out the <email address> part
Use Ruby to implement RFC 2047 isn't hard:
module Rfc2047
TOKEN = /[\041\043-\047\052\053\055\060-\071\101-\132\134\136\137\141-\176]+/.freeze
ENCODED_TEXT = /[\041-\076\100-\176]+/.freeze
ENCODED_WORD = /=\?(?<charset>#{TOKEN})\?(?<encoding>[QB])\?(?<encoded_text>#{ENCODED_TEXT})\?=/i.freeze
class << self
def encode(input)
"=?#{input.encoding}?B?#{[input].pack('m0')}?="
end
def decode(input)
match_data = ENCODED_WORD.match(input)
raise ArgumentError if match_data.nil?
charset, encoding, encoded_text = match_data.captures
decoded =
case encoding
when 'Q', 'q' then encoded_text.unpack1('M')
when 'B', 'b' then encoded_text.unpack1('m')
end
decoded.force_encoding(charset)
end
end
end
Rfc2047.decode '=?iso-8859-1?Q?Marta_Falc=E3o?=' # => Marta_Falcão
Update
mikel/mail is currently having an encoding issue which might not decode the string correctly.
If that really bothers you, you can try new_rfc_2047:
$ gem install new_rfc_2047
$ ruby -rrfc_2047 -e 'puts Rfc2047.decode "From: =?iso-8859-1?Q?Marta_Falc=E3o?= <marta.falcao#example.com.br>"'
From: Marta Falcão <marta.falcao#example.com.br>
Since the source code of mikel/mail is a little too complicated for me to do the modification, I just made my own gem for this.
Gem source is here: https://github.com/tonytonyjan/rfc_2047/
Running this example
https://cloud.google.com/vision/docs/face-tutorial?hl=zh-tw
by rails on 'google-cloud-vision', '~> 0.31.0'
got the error
uninitialized constant Google::Cloud::Vision::ImageAnnotator
here's the code
require "google/cloud/vision"
project_id = 'xxxxxx'
vision = Google::Cloud::Vision.new project: project_id
image_annotator = Google::Cloud::Vision::ImageAnnotator.new
Did you added google-cloud-ruby gem in your Gemfile and other google related authentication details into your ruby project.
It turns out that the error was caused because I haven't use the latest version of gcloud-vision(0.32.x)
the way to do what I wanna do in gcloud-vision(0.31.0) is
image = vision.image "path/to/face.jpg"
face = image.face
instead of using class
Google::Cloud::Vision::ImageAnnotator
Not sure how to fix Rubocop's Lint/UriEscapeUnescape warning
Tried replacing URI with CGI thinking that was the "drop in" replacement but that blew up the test suite.
Here's the error followed by the line of code where URI is being used:
app/models/media_file.rb:76:5: W: Lint/UriEscapeUnescape: URI.escape method is obsolete and should not be used. Instead, use CGI.escape, URI.encode_www_form or URI.encode_www_form_component depending on your specific use case.
URI ...
^^^
# app/models/media_file.rb
...
def cdn_url(format: nil)
if format.nil?
"#{s3_config.cloudfront_endpoint}/#{escape_url(key)}"
elsif converted_urls.with_indifferent_access[format.to_s]
filename = converted_urls.with_indifferent_access[format.to_s]
if URI.parse(escape_url(filename)).host
filename
else
"#{s3_config.cloudfront_endpoint}/#{escape_url(filename)}"
end
else
converted(url)
end
end
...
private
def escape_url(url)
URI
.escape(url)
.gsub(/\(/, '%28')
.gsub(/\)/, '%29')
.gsub(/\[/, '%5B')
.gsub(/\]/, '%5D')
end
EDIT: Adding sample output of strings escaped with URI and CGI:
url: images/medium/test-image.jpg
URI.escape(url): images/medium/test-image.jpg
CGI.escape(url): images%2Fmedium%2Ftest-image.jpg
url: images/medium/test-image.jpg
URI.escape(url): images/medium/test-image.jpg
CGI.escape(url): images%2Fmedium%2Ftest-image.jpg
It would appear CGI is not a drop in replacement for URI as the listing error might have you believe. Thoughts?
Encounter with the same problem, got it fixed by using addressable lib.
escaped_query = URI.escape(search,
Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
#W: Lint/UriEscapeUnescape: URI.escape method is obsolete and should not be used. Instead, use CGI.escape, URI.encode_www_form or URI.encode_www_form_component depending on your specific use case.
Solved by:
gem addressable gem in gemspec or Gemfile.
gem 'addressable', '~> 2.7'
require addressable/uri
Add appropriate.
escaped_query = Addressable::URI.encode_component(search, Addressable::URI::CharacterClasses::QUERY)
The following function works perfect in PHP. How can it be translated in Ruby on Rails.
Please note that both privateKey and iv are 32 characters long.
mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $privateKey, base64_decode($enc), MCRYPT_MODE_CBC, $iv)
Thanking you very much in anticipation
Try ruby-mcrypt gem.
require 'rubygems'
require 'mcrypt'
crypto = Mcrypt.new(:twofish, :cbc, MY_KEY, MY_IV, :pkcs)
# encryption and decryption in one step
ciphertext = crypto.encrypt(plaintext)
plaintext = crypto.decrypt(ciphertext)
Use only the specific classes that have those functions.
I'm new to rails, and looking to set up a site that uses Amazon's product API. I'm used to using the API in PHP but keen to move to Ruby if at all possible.
I've been trying the various Amazon product API gems, Ruby/AWS, Amazon-ECS, and now Vacuum. However a problem I am sticking at is how to actually use the code they suggest in their readme files.
For example, Vacuum:
https://github.com/hakanensari/vacuum/
It mentions the following code:
req = Vacuum.new :product_advertising
req.configure do |config|
config.key 'key'
config.secret 'secret'
config.tag 'tag'
end
req.build operation: 'ItemSearch',
search_index: 'Books',
keywords: 'Deleuze'
res = req.get
res.valid? or raise res.code
p res.body
Unsure where to put this code, I set up a controller for the test app and put it there. However it fails on the first line, saying that Vacuum is not defined (it's installed as a gem within the gemfile, and I've run bundle install).
I'm probably doing something stupid yet simple to fix, and would really appreciate any suggestions.
D
Edit:
Thanks to x1a4, the following code should be replace the configure block above:
req.configure do |config|
config.key = 'key'
config.secret = 'secret'
config.tag = 'tag'
end
Thanks to x1a4, the following code should be replace the configure block above:
req.configure do |config|
config.key = 'key'
config.secret = 'secret'
config.tag = 'tag'
end