How to encrypt and decrypt SketchUp .skp files?

Hello developers,

Is there a way to use something like Openssl to encrypt and decrypt a .skp file?
I tried the following but failed…

require 'openssl'

module RafaelRivera
module SuCrypt
  refine String do
    def encrypt(key)
		cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
		cipher.key = Digest::SHA1.hexdigest key
		s = cipher.update(self) + cipher.final
		s.unpack('H*')[0].upcase
	end #####

	def decrypt(key)
		cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
		cipher.key = Digest::SHA1.hexdigest key
		s = [self].pack("H*").unpack("C*").pack("c*")
		cipher.update(s) + cipher.final
	end ####
  end #### refine ####
end #### module ####
end #### module ####


module RafaelRivera
module SuCrypt
	using RafaelRivera::SuCrypt
	class Main
      
		def initialize
			key = 'secret'
			file = ENV['HOME'] + '/Desktop/sup/test.skp'

			# Encrypt
			file2 = ENV['HOME'] + '/Desktop/sup/test_encrypted.skp'
			plain = File.read(file)
			File.write(file2, plain.encrypt(key))

			# Decrypt
			file3 = ENV['HOME'] + '/Desktop/sup/test_decrypted.skp'
			cipher= File.read(file2)
			File.write(file3, cipher.decrypt(key))
		end ####
	end #### class ####
end #### module ####
end #### module ####

Sketchup.active_model.select_tool RafaelRivera::SuCrypt::Main.new

The code above works well on files with extension .txt but not with .skp files. Any help will be appreciated!

Note: Edited the example code to wrap it inside modules but the working code can be found below.

You shouldn’t extend the String class since it is public and not in your name space. Think about all the SketchUp newbies who see this and will be hit by a truck.

The File.open method has a second argument for the read/write mode. It defaults to text (“t”), so try out to use “b” for binary:

File.open(file, "rb") { |f|
  plain = f.read()
}
File.open(file2, "wb") { |f|
  f.write(plain.encrypt(key))
}
2 Likes

Because text files are text. SKP files are binary files.

You can also use the rubyzip gem library and encrypt the whole archive with a password.

1 Like

It works!

Thank you so much… Here is the final test which proved to be successful…

require 'openssl'

module RafaelRivera
module SuCrypt
  refine String do
    def encrypt(key)
		cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
		cipher.key = Digest::SHA1.hexdigest key
		s = cipher.update(self) + cipher.final
		s.unpack('H*')[0].upcase
	end #####

	def decrypt(key)
		cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').decrypt
		cipher.key = Digest::SHA1.hexdigest key
		s = [self].pack("H*").unpack("C*").pack("c*")
		cipher.update(s) + cipher.final
	end ####
  end #### refine ####
end #### module ####
end #### module ####


module RafaelRivera
module SuCrypt
	using RafaelRivera::SuCrypt
	class Main
      
		def initialize
			key = 'secret'
			@file  = ENV['HOME'] + '/Desktop/sup/test.skp'
			@file2 = ENV['HOME'] + '/Desktop/sup/test_encrypted.skp'
			@file3 = ENV['HOME'] + '/Desktop/sup/test_decrypted.skp'
			## Encrypt
			su_encrypt(key)
			## Decrypt
			su_decrypt(key)
		end ####

		def su_encrypt(key)
			## Plain
			File.open(@file, "rb") { |f|
				@plain = f.read()
			}
			File.open(@file2, "wb") { |f|
				f.write( @plain.encrypt(key) )
			}
		end ####

		def su_decrypt(key)
			## Cipher
			File.open(@file2, "rb") { |f|
				@cipher = f.read()
			}
			File.open(@file3, "wb") { |f|
				f.write(@cipher.decrypt(key))
			}
		end ####

	end #### class ####
end #### module ####
end #### module ####

Sketchup.active_model.select_tool RafaelRivera::SuCrypt::Main.new

Yes, I should have known that :slight_smile:

In my project, I am using Ruby on Rails so I’ll be able to check that rubyzip gem out… Thanks for the suggestion. I’ll check it out later and report back to you guys. Again thanks for the help!

Perfect!

Besides that, it is rather recommended to do no heavy work in the initialize method, only variable initialization, and do the heavy work in a method (run or apply…) that you call on the initialized instance.
Two examples where this will become a problem: Once you design test cases and just need to initialize an object of that type as stub (without running all its code), or when you want to create data objects for serialization.

2 Likes

Yes, I need to keep my initialize space as clean as possible. Thank you so much for the help!

Oooops…I changed the post above to fix a problem.

The new code refines the String class and adds two new methods within my own module namespace. I hope this will not cause any issues with other extensions.

Then by adding ‘using RafaelRivera::SuCrypt’ I can use the new String methods in my code.

Everything seems to be working now…I think!

Anyways, thanks again!

To be sure, make another dummy extension that also refines the String class, and see if things works as you hope.