require 'pty' require 'expect' require 'fileutils' # # This class encrypts and decrypts a file using GnuPG. # Output file will stay in the same directory as input file. # # Author:: FUJIWARA Teruyoshi # Copyright:: Copyright (c) 2010 FUJIWARA Teruyoshi # License:: Distributes under the same terms as Ruby # Date:: July 3, 2010 # Version:: 1.0 # # == Requirement # * You need GnuPG installed on your box. # # == Note # This script requires 'pty' and 'expect' modules. # So be careful of follwoing issues: # * It won't work on Windows and requires Unix/Cygwin environment. # * Be careful of locale. It changes message from gpg and may cause trouble with 'expect'. # # == See Also # * http://www.gnupg.org # class Crypt @@gpg_cmd_encrypt = "/usr/bin/gpg -c" @@gpg_cmd_decrypt = "/usr/bin/gpg" @@verbose = false # Encriypt a file using GnuPG. # === Arguments # [path] a file to be encrypted. # [password] password # === Return value # [true] succeeded # [false] failed def self.encrypt(path, password) ENV["LC_ALL"] = "C" unless FileTest.file?(path) puts("Error: File not found(#{path}).") return false end if FileTest.file?("#{path}.gpg") FileUtils.mv("#{path}.gpg", "#{path}.gpg.old", {:force => true}) puts("#{path}.gpg already exists. Renamed as #{path}.gpg.old") end cmd = "#{@@gpg_cmd_encrypt} \"#{path}\" ; echo done." puts(cmd) if @@verbose begin PTY.spawn(cmd) do |r, w| w.sync = true puts("enter password...") if @@verbose r.expect(/Enter passphrase:/) { w.puts("#{password}\n") } puts("re-enter password") if @@verbose r.expect(/Repeat passphrase:/) { w.puts("#{password}\n") } puts("waiting finish.") if @@verbose r.expect(/done/) { puts("done.\n") if @@verbose } end rescue PTY::ChildExited => e puts("GPG process finished.\n") if @@verbose end puts("#{path}.gpg") if @@verbose if FileTest.file?("#{path}.gpg") puts("Succeeded to encrypt.\n") if @@verbose return true else puts("Failed to encrypt.\n") if @@verbose return false end end # Decriypt a file Using GnuPG. # === Arguments # [path] a file to be decrypted. Maybe it has a filename like "*.gpg". # [password] password # === Return value # [true] succeeded # [false] failed def self.decrypt(path, password) ENV["LC_ALL"] = "C" unless FileTest.file?(path) puts("Error: File not found(#{path}).") return false end cmd = "#{@@gpg_cmd_decrypt} \"#{path}\" ; echo done." puts(cmd) if @@verbose begin PTY.spawn(cmd) do |r, w| w.sync = true puts("enter password...") if @@verbose r.expect(/Enter passphrase:/) { w.puts("#{password}\n") } puts("waiting finish.") if @@verbose r.expect(/done/) { puts("done.\n") if @@verbose } end rescue PTY::ChildExited => e puts("GPG process finished.\n") if @@verbose end if FileTest.file?(path.gsub(/\.gpg$/, "")) puts("Succeeded to decrypt.\n") if @@verbose return true else puts("Failed to decrypt.\n") if @@verbose return false end end end