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.
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/
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
Dwolla permits an app to solicit and store a user's PIN as a form of pre-authorization, but requires that it be encrypted. From the TOS:
PIN(s) must be encrypted in transit and at rest (this includes any and
all backup mediums) using FIPS 140-2 standards (at a minimum)
Normally, I'd use Bcrypt to encrypt (actually, make a secure hash. Neil Slater, thanks for the correction) something (using bcrypt-ruby gem), such as a password. But if I encrypt with Bcrypt, then I'd have to transmit the hash, and of course that won't match what Dwolla is expecting and the PIN will be rejected.
How do you encrypt the PIN and unencrypt it for secure transmittal?
UPDATE:
One of the answers in the question that Andrew links to below referenced OpenSSL:Cipher, and using that I can encrypt the PIN with the below code. But remaining questions then are:
How should I store the key, iv (initialization vector), and cipher? Is it secure to save as environment variables, or would it be better to put in a database table in a secure hash?
Does the below code make sense as a way to encrypt the PIN?
Since I don't have a public key from Dwolla, what's the best way to transmit it?
pin = "1111" # this is what needs to be encrypted
#encryption:
cipher = OpenSSL::Cipher.new('AES-128-CBC') #=> #<OpenSSL::Cipher:0x00000100ef09d8>
cipher.encrypt
key = cipher.random_key #=> odd characters...
iv = cipher.random_iv #=> odd characters...
encrypted = cipher.update(pin) + cipher.final #=> odd characters...
#dcryption:
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
decipher.decrypt
decipher.key = key
decipher.iv = iv
plain = decipher.update(encrypted) + decipher.final
puts plain == pin #=> true
So this is what I've found out. In Rails, generate the key just once and store as an environment variable (and when you deploy encrypt it). Generate a new iv (initialization vector) for each pin. Store the iv and the encrypted pin in the database.
You may want to convert the encrypted PIN and the IV to UTF8 in order to successfully save without changing how you set up your database. (Be default, they'll be generated as ASCII 8-bit).
Here is one way to do it inside your User model, but you may want to refactor since these are large methods:
def dwolla_pin # => this is to decrypt the PIN in order to use it
unless encrypted_dwolla_pin.nil?
decipher = OpenSSL::Cipher::AES.new(128, :CBC)
decipher.decrypt
decipher.key = ENV["ENCRYPT_KEY"]
# Convert IV from UTF8 (as stored) back to ASCII-8bit (for OpenSSL)
utf8_iv = self.iv_for_pin
decipher.iv = Base64.decode64(utf8_iv.encode('ascii-8bit'))
# Convert PIN from UTF8 (as stored) back to ASCII-8bit (for OpenSSL)
utf8_pin = self.encrypted_dwolla_pin
ascii_pin = Base64.decode64(utf8_pin.encode('ascii-8bit'))
dwolla_pin ||= decipher.update(ascii_pin) + decipher.final
end
end
def dwolla_pin=(new_pin) # => this is to encrypt the PIN in order to store it
return false unless valid_pin?(new_pin)
cipher = OpenSSL::Cipher.new('AES-128-CBC')
cipher.encrypt
cipher.key = ENV["ENCRYPT_KEY"]
# Create IV and convert to UTF-8 for storage in database
iv = cipher.random_iv
utf8_iv = Base64.encode64(iv).encode('utf-8')
self.update_attribute(:iv_for_pin, utf8_iv)
# Encrypt PIN and convert to UTF-8 for storage in database
encrypted_pin = cipher.update(new_pin) + cipher.final
utf8_pin = Base64.encode64(encrypted_pin).encode('utf-8')
self.update_attribute(:encrypted_dwolla_pin, utf8_pin)
end
def valid_pin?(pin) # => Here I'm just checking to make sure the PIN is basically in the right format
pin.match(/^\d{4}/) && pin.length == 4
end
"Secure transit" means SSL for usage and SSH for deployment. If deploying to Heroku then already using SSH, but for SSL you will need to buy from your DNS host wildcard cert and the ssl endpoint on Heroku.
Does anyone have anything to add to this?
I'd use public/private key encryption in a case like this. Not an expert on Ruby, but this link might help:
Ruby: file encryption/decryption with private/public keys
If your pin is being sent externally then you'd need the end-users public key to encrypt. If this isn't possible then you could use a mixture of asynmmetric (public/private) and symmetric algorithms - basically what SSH does.
http://en.wikipedia.org/wiki/Secure_Shell
I am trying to parse og meta tags using the HTTParty gem using this code:
link = http://www.usatoday.com/story/gameon/2013/01/08/nfl-jets-tony-sparano-fired/1817037/
# link = http://news.yahoo.com/chicago-lottery-winners-death-ruled-homicide-181627271.html
resp = HTTParty.get(link)
ret_body = resp.body
# title
og_title = ret_body.match(/\<[Mm][Ee][Tt][Aa] property\=\"og:title\"\ content\=\"(.*?)\"\/\>/)
og_title = og_title[1].to_s
The problem is that it worked on some sites (yahoo!) but not others (usa today)
Don't parse HTML with regular expressions, because they're too fragile for anything but the simplest problems. A tiny change to the HTML can break the pattern, causing you to begin a slow battle of maintaining an ever expanding pattern. It's a war you won't win.
Instead, use a HTML parser. Ruby has Nokogiri, which is excellent. Here's how I'd do what you want:
require 'nokogiri'
require 'httparty'
%w[
http://www.usatoday.com/story/gameon/2013/01/08/nfl-jets-tony-sparano-fired/1817037/
http://news.yahoo.com/chicago-lottery-winners-death-ruled-homicide-181627271.html
].each do |link|
resp = HTTParty.get(link)
doc = Nokogiri::HTML(resp.body)
puts doc.at('meta[property="og:title"]')['content']
end
Which outputs:
Jets fire offensive coordinator Tony Sparano
Chicago lottery winner's death ruled a homicide
Perhaps I can offer an easier solution? Check out the OpenGraph gem.
It's a simple library for parsing Open Graph protocol information from web sites and should solve your problem.
Solution:
og_title = ret_body.match(/\<[Mm][Ee][Tt][Aa] property\=\"og:title\"\ content\=\"(.*?)\"[\s\/\>|\/\>]/)
og_title = og_title[1].to_s
Trailing whitespace messed up the parsing so make sure to check for that. I added an OR clause to the regex to allow for both trailing and non trailing whitespace.
I know as a programmer that is rare for someone to do, but I actually need it and can not at all so someone needs to convert this small function cryptography python for delphi.
function: `
from Crypto.Cipher import Blowfish
class Blowfish(object):
cipher = None
def __init__(self, key, mode = Blowfish.MODE_ECB):
self.cipher = Blowfish.new(key, mode)
def encrypt(self, texto):
encriptar = self.cipher.encrypt(texto)
return encriptar `
-
one example
key = 123key
text = hi man
result = ìûÕ]–•¢
I people much times because I tried to do in Delphi and always shows me different results then do better and ask for someone who understands python / delphi
thank so much!
For the comment on DCPcrypt, maybe your python library results the raw encrypted bytes, and the result of DCPcrypt (or other delphi library like Turbo Lockbox) gives you the result encoded in something like UU64 o MIME (this is done to easily transfer o store the result)
If you just want to implement Blowfish algorithm in Delphi, try DCPcrypt.
#Mili, you can't translate this code to delphi because does not exist a RTL library (or function) in delphi with blowfish support, dou you need use a third party component for this. i recommend you the
Delphi Encryption Compedium Part I v.5.2. you can try out this link for more components.
You can also try TurboPower LockBox 3.1.0 at http://lockbox.seanbdurkin.id.au/ .
This library also implements Blowfish.