module Sprockets::DigestUtils
def detect_digest_class(bytes)
While not elegant, all the supported digests have a unique bytesize.
Internal: Detect digest class hash algorithm for digest bytes.
def detect_digest_class(bytes) DIGEST_SIZES[bytes.bytesize] end
def digest(obj)
obj - A JSON serializable object.
wicked fast. Microbenchmarks away!
This is used for generating cache keys, so its pretty important its
Internal: Generate a hexdigest for a nested JSON serializable object.
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'.freeze 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
def digest_class
Internal: Default digest class.
def digest_class Digest::SHA256 end
def hexdigest_integrity_uri(hexdigest)
digest - The String hexbyte digest of the asset content.
as per the subresource integrity specification.
Public: Generate hash for use in the `integrity` attribute of an asset tag
def hexdigest_integrity_uri(hexdigest) integrity_uri(unpack_hexdigest(hexdigest)) end
def integrity_uri(digest)
digest - The String byte digest of the asset content.
as per the subresource integrity specification.
Public: Generate hash for use in the `integrity` attribute of an asset tag
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
def pack_base64digest(bin)
bin - String bytes
Internal: Pack a binary digest to a base64 encoded string.
def pack_base64digest(bin) [bin].pack('m0') end
def pack_hexdigest(bin)
bin - String bytes
Internal: Pack a binary digest to a hex encoded string.
def pack_hexdigest(bin) bin.unpack('H*').first end
def pack_urlsafe_base64digest(bin)
bin - String bytes
Internal: Pack a binary digest to a urlsafe base64 encoded string.
def pack_urlsafe_base64digest(bin) str = pack_base64digest(bin) str.tr!('+/'.freeze, '-_'.freeze) str.tr!('='.freeze, ''.freeze) str end
def unpack_hexdigest(hex)
hex - String hex
Internal: Unpack a hex encoded digest string into binary bytes.
def unpack_hexdigest(hex) [hex].pack('H*') end