ruby的DES和RSA

RSA加密数据量小,速度慢,是非对称加密。

DES加密数据量大,速度快,是对称加密。

为了实现非对称大数据量加密,可以结合DES和RSA的方式。加密时,先把数据用DES加密,再用RSA将DES的密钥加密(生成一个小的额外文件)。解密时,先用RSA得出DES的密钥,再把数据用DES解密。

为了方便简洁明了,DES中的IV就用KEY。

具体实现:

require 'openssl'

KEY= 'zycjwdss'
#IV = 'zycjwdss'


PUBLICKEY = '-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAM1w2GKYGcb1UQwLtRxMCbPFK/hadrrOiJRzeImmTHTnVKL1iftcmPfG
0ATk37x4Qdr7jJ93ZW2u5nKlQoy8jyVUxQjN5DU7jKzUce2Mh+bbZ8pYeLrLF3xj
YUpym+fIA/xt+wf26o0Z/rDvs4IKuANc0hGtK/8R62ne3I2ew89tAgMBAAE=
-----END RSA PUBLIC KEY-----'

PRIVATEKEY = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDNcNhimBnG9VEMC7UcTAmzxSv4Wna6zoiUc3iJpkx051Si9Yn7
XJj3xtAE5N+8eEHa+4yfd2VtruZypUKMvI8lVMUIzeQ1O4ys1HHtjIfm22fKWHi6
yxd8Y2FKcpvnyAP8bfsH9uqNGf6w77OCCrgDXNIRrSv/Eetp3tyNnsPPbQIDAQAB
AoGBAJnVcBKT9mlm9KNieOGRhopYkI5Nny5OzTLsLExWfFXlixjjZ8kTE3AmLUoc
3/RO0HFbf3dBfm/dUa5zVRvxbfWbsoKUt++bNLdXDMG28mOb9CZ+zLNrgzpQ8+0T
M6NIJGNbCWZSY15JBaDUSoCOE4UEbOuGfrlrsvxetCv/eL3BAkEA+GQiFMzV45/s
X1UhoA2bYaIMzv5mukY4XvRKqJh2R9jSWAPa5w84n/prAEEO9cUdaAkGFfTN7Cgw
bZsw8i2YWQJBANO75fx8usDe9MqvbnmTekxWRPySKB6uCJlhMEmLotnYCPvzmcxQ
TcQafH23ziEqbblY+3bHA7AQM0nV9XB0zTUCQDBhaJX+k8ajVqn27fa7z8EDjFUh
DidIGCC+mnAeSiOSYt4L2i5ZM6FNaFwDUAOk4iZqY4oRRa6y4UPoD2+MW/kCQAUp
qbv0VqFpTlK64Fi6jdrap6f48F1/JNqIkiLY8smZCO8Ly449zwefFbYDC1WnsTE5
yDfnNmHOo1GDlA5/6pkCQCWj+YUSwE8GgvjDCCEs6URWiikc/CW/zVYNG9FtzjWu
ZefzMEQdOKz6y8q0OXYBpHX0VpIX5OTImz3SgS4pMaM=
-----END RSA PRIVATE KEY-----'


class Mycipher

  #得出一对RSA密钥
  def self.get_rsa_key
    rsa = OpenSSL::PKey::RSA.new(1024)
# public_key only can public_encrypt or public_decrypt no private_encrypt nor private_decrypt
#rsa.public_key.to_pem the class of return value is String
    [rsa.public_key.to_pem, rsa.to_pem]
  end

  #用私钥加密
  def self.rsa_private_encrypt(value, rsakey)
    rsa = OpenSSL::PKey::RSA.new(rsakey)
    rsa.private_encrypt(value)
  end

  #用私钥解密 unused
  def self.rsa_private_decrypt(value, rsakey)
    rsa = OpenSSL::PKey::RSA.new(rsakey)
    rsa.private_decrypt(value)
  end

  #用公钥加密 unused
  def self.rsa_public_encrypt(value, publickey)
    rsa = OpenSSL::PKey::RSA.new(publickey)
    rsa.public_encrypt(value)
  end

  #用公钥解密
  def self.rsa_public_decrypt(value, publickey)
    rsa = OpenSSL::PKey::RSA.new(publickey)
    rsa.public_decrypt(value)
  end

  #DES加密
  def self.des_encrypt(text, key, iv)
    c = OpenSSL::Cipher::Cipher.new('DES-CBC')
    c.encrypt
    c.key = key
    c.iv = iv
    ret = c.update(text)
    ret << c.final
    return ret
  end

  #DES解密
  def self.des_decrypt(encrypt_value, key, iv)
    c = OpenSSL::Cipher::Cipher.new('DES-CBC')
    c.decrypt
    c.key = key
    c.iv = iv
    ret = c.update(encrypt_value)
    ret << c.final
    return ret
  end

  #将文件读为byte型string
  def self.filetostring filepath
    f = File.open filepath, 'rb'
    text = f.read
    f.close
    return text
  end

  #将byte型string转成文件
  def self.stringtofile filepath, string
    f = File.open filepath, 'wb'
    f.print string
    f.close
  end

  #将DES的KEY用RSA私钥加密后转成文件
  def self.keytopefile filepath, key
    pe = rsa_private_encrypt key, PRIVATEKEY
    stringtofile filepath, pe
  end

  #将文件用RSA公钥解密后读出DES的KEY
  def self.pefiletokey filepath
    pe = filetostring filepath
    orikey = rsa_public_decrypt pe, PUBLICKEY
    return orikey
  end

  #加密文件(主要方法)
  def self.encode filepath
    text = filetostring filepath
    en = des_encrypt text, KEY, KEY
    stringtofile filepath, en
    keytopefile filepath + '.pefile', KEY
  end

  #解密文件(主要方法)
  def self.decode filepath
    key = pefiletokey filepath + '.pefile'
    en = filetostring filepath
    text = des_decrypt en, key, key
    stringtofile filepath, text
  end

end

使用时,先生成一对RSA的publickey和privatekey。

加密端只需要DES的KEY(可临时生成),privatekey和encode:

require 'openssl'

KEY= 'zycjwdss'
#IV = 'zycjwdss'

PRIVATEKEY = '-----BEGIN RSA PRIVATE KEY-----
MIICXAIBAAKBgQDNcNhimBnG9VEMC7UcTAmzxSv4Wna6zoiUc3iJpkx051Si9Yn7
XJj3xtAE5N+8eEHa+4yfd2VtruZypUKMvI8lVMUIzeQ1O4ys1HHtjIfm22fKWHi6
yxd8Y2FKcpvnyAP8bfsH9uqNGf6w77OCCrgDXNIRrSv/Eetp3tyNnsPPbQIDAQAB
AoGBAJnVcBKT9mlm9KNieOGRhopYkI5Nny5OzTLsLExWfFXlixjjZ8kTE3AmLUoc
3/RO0HFbf3dBfm/dUa5zVRvxbfWbsoKUt++bNLdXDMG28mOb9CZ+zLNrgzpQ8+0T
M6NIJGNbCWZSY15JBaDUSoCOE4UEbOuGfrlrsvxetCv/eL3BAkEA+GQiFMzV45/s
X1UhoA2bYaIMzv5mukY4XvRKqJh2R9jSWAPa5w84n/prAEEO9cUdaAkGFfTN7Cgw
bZsw8i2YWQJBANO75fx8usDe9MqvbnmTekxWRPySKB6uCJlhMEmLotnYCPvzmcxQ
TcQafH23ziEqbblY+3bHA7AQM0nV9XB0zTUCQDBhaJX+k8ajVqn27fa7z8EDjFUh
DidIGCC+mnAeSiOSYt4L2i5ZM6FNaFwDUAOk4iZqY4oRRa6y4UPoD2+MW/kCQAUp
qbv0VqFpTlK64Fi6jdrap6f48F1/JNqIkiLY8smZCO8Ly449zwefFbYDC1WnsTE5
yDfnNmHOo1GDlA5/6pkCQCWj+YUSwE8GgvjDCCEs6URWiikc/CW/zVYNG9FtzjWu
ZefzMEQdOKz6y8q0OXYBpHX0VpIX5OTImz3SgS4pMaM=
-----END RSA PRIVATE KEY-----'


class Mycipher

  def self.rsa_private_encrypt(value, rsakey)
    rsa = OpenSSL::PKey::RSA.new(rsakey)
    rsa.private_encrypt(value)
  end

  def self.des_encrypt(text, key, iv)
    c = OpenSSL::Cipher::Cipher.new('DES-CBC')
    c.encrypt
    c.key = key
    c.iv = iv
    ret = c.update(text)
    ret << c.final
    return ret
  end

  def self.filetostring filepath
    f = File.open filepath, 'rb'
    text = f.read
    f.close
    return text
  end

  def self.stringtofile filepath, string
    f = File.open filepath, 'wb'
    f.print string
    f.close
  end
  
  def self.keytopefile filepath, key
    pe = rsa_private_encrypt key, PRIVATEKEY
    stringtofile filepath, pe
  end

  def self.encode filepath
    text = filetostring filepath
    en = des_encrypt text, KEY, KEY
    stringtofile filepath, en
    keytopefile filepath + '.pefile', KEY
  end

end

解密端只需要publickey和decode:

require 'openssl'


PUBLICKEY = '-----BEGIN RSA PUBLIC KEY-----
MIGJAoGBAM1w2GKYGcb1UQwLtRxMCbPFK/hadrrOiJRzeImmTHTnVKL1iftcmPfG
0ATk37x4Qdr7jJ93ZW2u5nKlQoy8jyVUxQjN5DU7jKzUce2Mh+bbZ8pYeLrLF3xj
YUpym+fIA/xt+wf26o0Z/rDvs4IKuANc0hGtK/8R62ne3I2ew89tAgMBAAE=
-----END RSA PUBLIC KEY-----'

 

class Mycipher

  def self.rsa_public_decrypt(value, publickey)
    rsa = OpenSSL::PKey::RSA.new(publickey)
    rsa.public_decrypt(value)
  end

  def self.des_decrypt(encrypt_value, key, iv)
    c = OpenSSL::Cipher::Cipher.new('DES-CBC')
    c.decrypt
    c.key = key
    c.iv = iv
    ret = c.update(encrypt_value)
    ret << c.final
    return ret
  end

  def self.filetostring filepath
    f = File.open filepath, 'rb'
    text = f.read
    f.close
    return text
  end

  def self.stringtofile filepath, string
    f = File.open filepath, 'wb'
    f.print string
    f.close
  end

  def self.pefiletokey filepath
    pe = filetostring filepath
    orikey = rsa_public_decrypt pe, PUBLICKEY
    return orikey
  end

  def self.decode filepath
    key = pefiletokey filepath + '.pefile'
    en = filetostring filepath
    text = des_decrypt en, key, key
    stringtofile filepath, text
  end

end

经测试

Mycipher.encode 'D:\\code.doc'

Mycipher.decode 'D:\\code.doc'

结果正确。

在lib中新建文件夹cipher,把以上文件放进去。

在lib中新建文件mycipherext.rb

#Input next line in application.rb
#include Mycipherext
#And input next line in class which you want to use Mycipher
#require_mycipher_ext
#
#Input next line to encode a file, with generate a .pefile file(Notice:This will change the original file)
#Mycipher.encode 'D:\\code.doc'
#Input next line to decode a file, by using a .pefile file(Notice:This will change the original file)
#Mycipher.decode 'D:\\code.doc'
#
#Author: zzqwdss


module Mycipherext
  def require_mycipher_ext
    Dir["#{RAILS_ROOT}/lib/cipher/*.rb"].each do |f|
      require_dependency f
    end
  end
end
Object.instance_eval { include Mycipherext }

mycipher.rar

原文地址:https://www.cnblogs.com/zycjwdss/p/1848929.html