    # File lib/facets/more/crypt.rb, line 54
      def self.crypt(password, algo = :md5, salt = nil, magic='$1$')

        salt ||= generate_salt(8)

        case algo
          when :md5
            require "digest/md5"
          when :sha1
            require "digest/sha1"
          when :rmd160
            require "digest/rmd160"
          when :sha256, :sha384, :sha512
            require "digest/sha2"
        else
          raise(ArgumentError, "unknown algorithm")
        end
        digest_class = Digest.const_get(algo.to_s.upcase)

        # The password first, since that is what is most unknown. Then our magic string. Then the raw salt.
        m = digest_class.new
        m.update(password + magic + salt)

        # Then just as many characters of the MD5(pw,salt,pw)
        mixin = digest_class.new.update(password + salt + password).digest
        password.length.times do |i|
          m.update(mixin[i % 16].chr)
        end

        # Then something really weird...
        # Also really broken, as far as I can tell.  -m
        i = password.length
        while i != 0
          if (i & 1) != 0
            m.update("\x00")
          else
            m.update(password[0].chr)
          end
          i >>= 1
        end

        final = m.digest

        # and now, just to make sure things don't run too fast
        1000.times do |i|
          m2 = digest_class.new

          if (i & 1) != 0
            m2.update(password)
          else
            m2.update(final)
          end

          if (i % 3) != 0
            m2.update(salt)
          end
          if (i % 7) != 0
            m2.update(password)
          end

          if (i & 1) != 0
            m2.update(final)
          else
            m2.update(password)
          end

          final = m2.digest
        end

        # This is the bit that uses to64() in the original code.

        rearranged = ""

        [ [0, 6, 12], [1, 7, 13], [2, 8, 14], [3, 9, 15], [4, 10, 5] ].each do |a, b, c|

          v = final[a] << 16 | final[b] << 8 | final[c]

          4.times do
            rearranged += ITOA64[v & 0x3f].chr
            v >>= 6
          end
        end

        v = final[11]

        2.times do
          rearranged += ITOA64[v & 0x3f].chr
          v >>= 6
        end

        magic + salt + '$' + rearranged
      end