class TrubyLicense
Constants
- LicenseData
- X500Principal
Public Class Methods
new(password, key)
click to toggle source
Creates an instance able to read and write licenses using the supplied password and key. For writing licenses the key needs to be a private key, otherwise a public key will do.
# File lib/truby_license.rb, line 27 def initialize password, key raise ArgumentError.new("password must be a String") unless password.is_a? String raise ArgumentError.new("key must be an OpenSSL DSA key") unless key.is_a? OpenSSL::PKey::DSA @password = password @key = key # to hold the ciphers used in the crypt method @cipher ||= {} # some extra parameters TrueLicense uses @iterations = 2005 @salt = "\xCE\xFB\xDE\xAC\x05\x02\x19q" end
Public Instance Methods
deserialize_license(license_blob)
click to toggle source
# File lib/truby_license.rb, line 41 def deserialize_license license_blob begin license_data = gunzip(decrypt(license_blob)) rescue OpenSSL::Cipher::CipherError raise InvalidPassword.new "Could not decrypt license blob" rescue Zlib::GzipFile::Error raise InvalidLicense.new "Invalid format of license blob: not gzipped corrrectly" end JavabeanXml.from_xml license_data, :string => lambda { |value, properties| value }, "de.schlichtherle.xml.GenericCertificate" => lambda { |v, properties| sig = b64d(properties[:signature]) license =properties[:encoded] algorithm = properties[:signatureAlgorithm] encoding = properties[:signatureEncoding] unless algorithm == "SHA1withDSA" raise NotImplementedError.new( "signature algorithm %s has not been implemented". % algorithm ) end unless encoding == "US-ASCII/Base64" raise NotImplementedError.new( "signature encoding %s has not been implemented". % encoding ) end unless verify_signature(license, sig) raise InvalidLicense.new("License signature mismatch") end JavabeanXml.from_xml(license, :long => lambda { |value, p| value.to_i }, :string => lambda { |value, p| value }, "java.util.Date" => lambda { |value, p| Time.at(value / 1000) }, "javax.security.auth.x500.X500Principal" => lambda { |value, p| X500Principal.new value }, "de.schlichtherle.license.LicenseContent" => lambda {|value, properties| ld = LicenseData.new ld.members.each do |prop| ld[prop] = properties[prop.to_sym] end ld } ) } end
serialize_license(license_data)
click to toggle source
# File lib/truby_license.rb, line 91 def serialize_license license_data lic_data = license_data.clone # allows us to make changes unless @key.private? raise PrivateKeyNeeded.new("Cannot use a public key to encrypt the license") end # make sure issuer and holder are properly wrapped in X500Principal objects [:issuer, :holder].each do |prop| if lic_data[prop].is_a? String lic_data[prop] = X500Principal.new lic_data[prop] end end lic_data.consumerType = lic_data.consumerType.to_s inner = JavabeanXml.to_xml lic_data, LicenseData => lambda { |value| { :class => "de.schlichtherle.license.LicenseContent", :properties => lic_data.members.inject({}) {|props, prop| props[prop.to_sym] = lic_data[prop] props } } }, X500Principal => lambda { |value| { :class => "javax.security.auth.x500.X500Principal", :value => { :class => :string, :value => value.name } } }, Time => lambda { |value| { :class => "java.util.Date", :value => { :class => :long, :value => value.to_i * 1000 } } }, String => lambda { |value| { :class => :string, :value => value } } outer = JavabeanXml.to_xml( { :class => "de.schlichtherle.xml.GenericCertificate", :properties => { :encoded => inner, :signature => b64e(sign(inner)), :signatureAlgorithm => "SHA1withDSA", :signatureEncoding => "US-ASCII/Base64" } }, String => lambda { |value| { :class => :string, :value => value } } ) encrypt(gzip(outer)) end
Private Instance Methods
b64d(string)
click to toggle source
# File lib/truby_license.rb, line 180 def b64d string Base64.decode64 string end
b64e(data)
click to toggle source
# File lib/truby_license.rb, line 176 def b64e data Base64.encode64 data end
crypt(mode, data)
click to toggle source
# File lib/truby_license.rb, line 192 def crypt mode, data unless @cipher[mode] @cipher[mode] = OpenSSL::Cipher.new "DES" @cipher[mode].send mode @cipher[mode].pkcs5_keyivgen @password, @salt, @iterations end c = @cipher[mode] c.update(data) + c.final end
decrypt(data)
click to toggle source
# File lib/truby_license.rb, line 202 def decrypt data crypt :decrypt, data end
encrypt(data)
click to toggle source
# File lib/truby_license.rb, line 206 def encrypt data crypt :encrypt, data end
gunzip(data)
click to toggle source
# File lib/truby_license.rb, line 168 def gunzip data Zlib::GzipReader.new(StringIO.new(data)).read end
gzip(data)
click to toggle source
# File lib/truby_license.rb, line 160 def gzip data gzipped = "" zf = Zlib::GzipWriter.new(StringIO.new(gzipped)) zf << data zf.close gzipped end
sha1(data)
click to toggle source
# File lib/truby_license.rb, line 172 def sha1 data OpenSSL::Digest::SHA1.digest(data) end
sign(data)
click to toggle source
# File lib/truby_license.rb, line 184 def sign data @key.syssign sha1(data) end
verify_signature(data, signature)
click to toggle source
# File lib/truby_license.rb, line 188 def verify_signature data, signature @key.sysverify(sha1(data), signature) end