@@ -144,6 +144,14 @@ class Cloudinary::Utils
144144 LONG_URL_SIGNATURE_LENGTH = 32
145145 SHORT_URL_SIGNATURE_LENGTH = 8
146146
147+ ALGO_SHA1 = :sha1
148+ ALGO_SHA256 = :sha256
149+
150+ ALGORITHM_SIGNATURE = {
151+ ALGO_SHA1 => Digest ::SHA1 ,
152+ ALGO_SHA256 => Digest ::SHA256 ,
153+ }
154+
147155 def self . extract_config_params ( options )
148156 options . select { |k , v | URL_KEYS . include? ( k ) }
149157 end
@@ -433,9 +441,9 @@ def self.api_string_to_sign(params_to_sign)
433441 params_to_sign . map { |k , v | [ k . to_s , v . is_a? ( Array ) ? v . join ( "," ) : v ] } . reject { |k , v | v . nil? || v == "" } . sort_by ( &:first ) . map { |k , v | "#{ k } =#{ v } " } . join ( "&" )
434442 end
435443
436- def self . api_sign_request ( params_to_sign , api_secret )
444+ def self . api_sign_request ( params_to_sign , api_secret , signature_algorithm = nil )
437445 to_sign = api_string_to_sign ( params_to_sign )
438- Digest :: SHA1 . hexdigest ( "#{ to_sign } #{ api_secret } " )
446+ hash ( "#{ to_sign } #{ api_secret } " , signature_algorithm , :hexdigest )
439447 end
440448
441449 # Returns a JSON array as String.
@@ -501,6 +509,7 @@ def self.unsigned_download_url(source, options = {})
501509 use_root_path = config_option_consume ( options , :use_root_path )
502510 auth_token = config_option_consume ( options , :auth_token )
503511 long_url_signature = config_option_consume ( options , :long_url_signature )
512+ signature_algorithm = config_option_consume ( options , :signature_algorithm )
504513 unless auth_token == false
505514 auth_token = Cloudinary ::AuthToken . merge_auth_token ( Cloudinary . config . auth_token , auth_token )
506515 end
@@ -545,7 +554,10 @@ def self.unsigned_download_url(source, options = {})
545554 raise ( CloudinaryException , "Must supply api_secret" ) if ( secret . nil? || secret . empty? )
546555 to_sign = [ transformation , sign_version && version , source_to_sign ] . reject ( &:blank? ) . join ( "/" )
547556 to_sign = fully_unescape ( to_sign )
548- signature = compute_signature ( to_sign , secret , long_url_signature )
557+ signature_algorithm = long_url_signature ? ALGO_SHA256 : signature_algorithm
558+ hash = hash ( "#{ to_sign } #{ secret } " , signature_algorithm )
559+ signature = Base64 . urlsafe_encode64 ( hash )
560+ signature = "s--#{ signature [ 0 , long_url_signature ? LONG_URL_SIGNATURE_LENGTH : SHORT_URL_SIGNATURE_LENGTH ] } --"
549561 end
550562
551563 prefix = unsigned_download_url_prefix ( source , cloud_name , private_cdn , cdn_subdomain , secure_cdn_subdomain , cname , secure , secure_distribution )
@@ -671,8 +683,9 @@ def self.cloudinary_api_url(action = 'upload', options = {})
671683 def self . sign_request ( params , options = { } )
672684 api_key = options [ :api_key ] || Cloudinary . config . api_key || raise ( CloudinaryException , "Must supply api_key" )
673685 api_secret = options [ :api_secret ] || Cloudinary . config . api_secret || raise ( CloudinaryException , "Must supply api_secret" )
686+ signature_algorithm = options [ :signature_algorithm ]
674687 params = params . reject { |k , v | self . safe_blank? ( v ) }
675- params [ :signature ] = Cloudinary :: Utils . api_sign_request ( params , api_secret )
688+ params [ :signature ] = api_sign_request ( params , api_secret , signature_algorithm )
676689 params [ :api_key ] = api_key
677690 params
678691 end
@@ -1163,23 +1176,18 @@ def self.to_usage_api_date_format(date)
11631176 end
11641177 end
11651178
1166- # Computes a short or long signature based on a message and secret
1167- # @param [String] message The string to sign
1168- # @param [String] secret A secret that will be added to the message when signing
1169- # @param [Boolean] long_signature Whether to create a short or long signature
1170- # @return [String] Properly formatted signature
1171- def self . compute_signature ( message , secret , long_url_signature )
1172- combined_message_secret = message + secret
1173-
1174- algo , signature_length =
1175- if long_url_signature
1176- [ Digest ::SHA256 , LONG_URL_SIGNATURE_LENGTH ]
1177- else
1178- [ Digest ::SHA1 , SHORT_URL_SIGNATURE_LENGTH ]
1179- end
1180-
1181- "s--#{ Base64 . urlsafe_encode64 ( algo . digest ( combined_message_secret ) ) [ 0 , signature_length ] } --"
1179+ # Computes hash from input string using specified algorithm.
1180+ #
1181+ # @param [String] input String which to compute hash from
1182+ # @param [String|nil] signature_algorithm Algorithm to use for computing hash
1183+ # @param [Symbol] hash_method Hash method applied to a signature algorithm (:digest or :hexdigest)
1184+ #
1185+ # @return [String] Computed hash value
1186+ def self . hash ( input , signature_algorithm = nil , hash_method = :digest )
1187+ signature_algorithm ||= Cloudinary . config . signature_algorithm || ALGO_SHA1
1188+ algorithm = ALGORITHM_SIGNATURE [ signature_algorithm ] || raise ( "Unsupported algorithm '#{ signature_algorithm } '" )
1189+ algorithm . public_send ( hash_method , input )
11821190 end
11831191
1184- private_class_method :compute_signature
1192+ private_class_method :hash
11851193end
0 commit comments