module Sprockets::DigestUtils

Internal: Hash functions and digest related utilities. Mixed into Environment.

Constants

DIGEST_SIZES

Internal: Maps digest bytesize to the digest class.

HASH_ALGORITHMS

Internal: Maps digest class to the CSP hash algorithm name.

Public Instance Methods

detect_digest_class(bytes) click to toggle source

Internal: Detect digest class hash algorithm for digest bytes.

While not elegant, all the supported digests have a unique bytesize.

Returns Digest::Base or nil.

# File lib/sprockets/digest_utils.rb, line 33
def detect_digest_class(bytes)
  DIGEST_SIZES[bytes.bytesize]
end
digest(obj) click to toggle source

Internal: Generate a hexdigest for a nested JSON serializable object.

This is used for generating cache keys, so its pretty important its wicked fast. Microbenchmarks away!

obj - A JSON serializable object.

Returns a String digest of the object.

# File lib/sprockets/digest_utils.rb, line 45
def digest(obj)
  digest = digest_class.new
  queue  = [obj]

  while queue.length > 0
    obj = queue.shift
    klass = obj.class

    if klass == String
      digest << obj
    elsif klass == Symbol
      digest << 'Symbol'
      digest << obj.to_s
    elsif klass == Fixnum
      digest << 'Fixnum'
      digest << obj.to_s
    elsif klass == Bignum
      digest << 'Bignum'
      digest << obj.to_s
    elsif klass == TrueClass
      digest << 'TrueClass'
    elsif klass == FalseClass
      digest << 'FalseClass'
    elsif klass == NilClass
      digest << 'NilClass'
    elsif klass == Array
      digest << 'Array'
      queue.concat(obj)
    elsif klass == Hash
      digest << 'Hash'
      queue.concat(obj.sort)
    elsif klass == Set
      digest << 'Set'
      queue.concat(obj.to_a)
    elsif klass == Encoding
      digest << 'Encoding'
      digest << obj.name
    else
      raise TypeError, "couldn't digest #{klass}"
    end
  end

  digest.digest
end
digest_class() click to toggle source

Internal: Default digest class.

Returns a Digest::Base subclass.

# File lib/sprockets/digest_utils.rb, line 15
def digest_class
  Digest::SHA256
end
hexdigest_integrity_uri(hexdigest) click to toggle source

Public: Generate hash for use in the `integrity` attribute of an asset tag as per the subresource integrity specification.

digest - The String hexbyte digest of the asset content.

Returns a String or nil if hash algorithm is incompatible.

# File lib/sprockets/digest_utils.rb, line 164
def hexdigest_integrity_uri(hexdigest)
  integrity_uri(unpack_hexdigest(hexdigest))
end
integrity_uri(digest) click to toggle source

Public: Generate hash for use in the `integrity` attribute of an asset tag as per the subresource integrity specification.

digest - The String byte digest of the asset content.

Returns a String or nil if hash algorithm is incompatible.

# File lib/sprockets/digest_utils.rb, line 142
def integrity_uri(digest)
  case digest
  when Digest::Base
    digest_class = digest.class
    digest = digest.digest
  when String
    digest_class = DIGEST_SIZES[digest.bytesize]
  else
    raise TypeError, "unknown digest: #{digest.inspect}"
  end

  if hash_name = HASH_ALGORITHMS[digest_class]
    "#{hash_name}-#{pack_base64digest(digest)}"
  end
end
pack_base64digest(bin) click to toggle source

Internal: Pack a binary digest to a base64 encoded string.

bin - String bytes

Returns base64 String.

# File lib/sprockets/digest_utils.rb, line 113
def pack_base64digest(bin)
  [bin].pack('m0')
end
pack_hexdigest(bin) click to toggle source

Internal: Pack a binary digest to a hex encoded string.

bin - String bytes

Returns hex String.

# File lib/sprockets/digest_utils.rb, line 95
def pack_hexdigest(bin)
  bin.unpack('H*').first
end
pack_urlsafe_base64digest(bin) click to toggle source

Internal: Pack a binary digest to a urlsafe base64 encoded string.

bin - String bytes

Returns urlsafe base64 String.

# File lib/sprockets/digest_utils.rb, line 122
def pack_urlsafe_base64digest(bin)
  str = pack_base64digest(bin)
  str.tr!('+/'.freeze, '-_'.freeze)
  str.tr!('='.freeze, ''.freeze)
  str
end
unpack_hexdigest(hex) click to toggle source

Internal: Unpack a hex encoded digest string into binary bytes.

hex - String hex

Returns binary String.

# File lib/sprockets/digest_utils.rb, line 104
def unpack_hexdigest(hex)
  [hex].pack('H*')
end