[
  {
    "path": ".document",
    "content": "README.md\nCOPYING\n/lib/**/*.rb\n"
  },
  {
    "path": ".github/workflows/ruby.yml",
    "content": "# This workflow uses actions that are not certified by GitHub.\n# They are provided by a third-party and are governed by\n# separate terms of service, privacy policy, and support\n# documentation.\n# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake\n# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby\n\nname: Ruby\n\non:\n  push:\n    branches: [ \"master\" ]\n  pull_request:\n    branches: [ \"master\" ]\n\npermissions:\n  contents: read\n\njobs:\n  test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      matrix:\n        # Testing on Ubuntu for the time being to avoid potential cost issues with macOS runners\n        os: [ubuntu-latest]\n        ruby-version: ['2.3', '2.4', '2.5', '2.6', ' 2.7', '3.0', '3.1', '3.2', '3.3', '3.4', head, jruby, jruby-head, truffleruby, truffleruby-head]\n\n    steps:\n    - uses: actions/checkout@v4\n    - name: Set up Ruby\n      uses: ruby/setup-ruby@v1\n      with:\n        ruby-version: ${{ matrix.ruby-version }}\n        bundler-cache: true\n    - name: Run tests\n      run: bundle exec rake\n"
  },
  {
    "path": ".gitignore",
    "content": "\n# Created by https://www.gitignore.io/api/c,ruby,macos,rubymine,visualstudiocode\n# Edit at https://www.gitignore.io/?templates=c,ruby,macos,rubymine,visualstudiocode\n\n### C ###\n# Prerequisites\n*.d\n\n# Object files\n*.o\n*.ko\n*.obj\n*.elf\n\n# Linker output\n*.ilk\n*.map\n*.exp\n\n# Precompiled Headers\n*.gch\n*.pch\n\n# Libraries\n*.lib\n*.a\n*.la\n*.lo\n\n# Shared objects (inc. Windows DLLs)\n*.dll\n*.so\n*.so.*\n*.dylib\n\n# Executables\n*.exe\n*.out\n*.app\n*.i*86\n*.x86_64\n*.hex\n\n# Debug files\n*.dSYM/\n*.su\n*.idb\n*.pdb\n\n# Kernel Module Compile Results\n*.mod*\n*.cmd\n.tmp_versions/\nmodules.order\nModule.symvers\nMkfile.old\ndkms.conf\n\n### macOS ###\n# General\n.DS_Store\n.AppleDouble\n.LSOverride\n\n# Icon must end with two \\r\nIcon\n\n# Thumbnails\n._*\n\n# Files that might appear in the root of a volume\n.DocumentRevisions-V100\n.fseventsd\n.Spotlight-V100\n.TemporaryItems\n.Trashes\n.VolumeIcon.icns\n.com.apple.timemachine.donotpresent\n\n# Directories potentially created on remote AFP share\n.AppleDB\n.AppleDesktop\nNetwork Trash Folder\nTemporary Items\n.apdisk\n\n### Ruby ###\n*.gem\n*.rbc\n/.config\n/coverage/\n/InstalledFiles\n/pkg/\n/spec/reports/\n/spec/examples.txt\n/test/tmp/\n/test/version_tmp/\n/tmp/\n\n# Used by dotenv library to load environment variables.\n# .env\n\n# Ignore Byebug command history file.\n.byebug_history\n\n## Specific to RubyMotion:\n.dat*\n.repl_history\nbuild/\n*.bridgesupport\nbuild-iPhoneOS/\nbuild-iPhoneSimulator/\n\n## Specific to RubyMotion (use of CocoaPods):\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control\n# vendor/Pods/\n\n## Documentation cache and generated files:\n/.yardoc/\n/_yardoc/\n/doc/\n/rdoc/\n\n## Environment normalization:\n/.bundle/\n/vendor/bundle\n/lib/bundler/man/\n\n# for a library or gem, you might want to ignore these files since the code is\n# intended to run in multiple environments; otherwise, check them in:\nGemfile.lock\n# .ruby-version\n# .ruby-gemset\n\n# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:\n.rvmrc\n\n### RubyMine ###\n# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm\n# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839\n\n# User-specific stuff\n.idea/**/workspace.xml\n.idea/**/tasks.xml\n.idea/**/usage.statistics.xml\n.idea/**/dictionaries\n.idea/**/shelf\n\n# Generated files\n.idea/**/contentModel.xml\n\n# Sensitive or high-churn files\n.idea/**/dataSources/\n.idea/**/dataSources.ids\n.idea/**/dataSources.local.xml\n.idea/**/sqlDataSources.xml\n.idea/**/dynamic.xml\n.idea/**/uiDesigner.xml\n.idea/**/dbnavigator.xml\n\n# Gradle\n.idea/**/gradle.xml\n.idea/**/libraries\n\n# Gradle and Maven with auto-import\n# When using Gradle or Maven with auto-import, you should exclude module files,\n# since they will be recreated, and may cause churn.  Uncomment if using\n# auto-import.\n# .idea/modules.xml\n# .idea/*.iml\n# .idea/modules\n# *.iml\n# *.ipr\n\n# CMake\ncmake-build-*/\n\n# Mongo Explorer plugin\n.idea/**/mongoSettings.xml\n\n# File-based project format\n*.iws\n\n# IntelliJ\nout/\n\n# mpeltonen/sbt-idea plugin\n.idea_modules/\n\n# JIRA plugin\natlassian-ide-plugin.xml\n\n# Cursive Clojure plugin\n.idea/replstate.xml\n\n# Crashlytics plugin (for Android Studio and IntelliJ)\ncom_crashlytics_export_strings.xml\ncrashlytics.properties\ncrashlytics-build.properties\nfabric.properties\n\n# Editor-based Rest Client\n.idea/httpRequests\n\n# Android studio 3.1+ serialized cache file\n.idea/caches/build_file_checksums.ser\n\n### RubyMine Patch ###\n# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721\n\n# *.iml\n# modules.xml\n# .idea/misc.xml\n# *.ipr\n\n# Sonarlint plugin\n.idea/**/sonarlint/\n\n# SonarQube Plugin\n.idea/**/sonarIssues.xml\n\n# Markdown Navigator plugin\n.idea/**/markdown-navigator.xml\n.idea/**/markdown-navigator/\n\n### VisualStudioCode ###\n.vscode/*\n# !.vscode/settings.json\n# !.vscode/tasks.json\n# !.vscode/launch.json\n# !.vscode/extensions.json\n\n### VisualStudioCode Patch ###\n# Ignore all local history of files\n.history\n\n# End of https://www.gitignore.io/api/c,ruby,macos,rubymine,visualstudiocode\n\n*.bundle\n/.idea\n"
  },
  {
    "path": ".rdoc_options",
    "content": "---\nmain_page: README.md\ntitle: SCrypt Ruby Documentation\n\ncharset: UTF-8\nencoding: UTF-8\nforce_update: true\nline_numbers: true\nmarkup: rdoc\nop_dir: html\nvisibility: :private\n"
  },
  {
    "path": ".rspec",
    "content": "--require spec_helper\n--color\n--format documentation\n"
  },
  {
    "path": ".rubocop.yml",
    "content": "\n# require: rubocop-rspec\n\nplugins:\n  - rubocop-performance\n  - rubocop-rake\n  - rubocop-rspec\n\nAllCops:\n  Include:\n    - Rakefile\n    - ext/**/Rakefile\n    - lib/**/*.{rb,rake}\n    - spec/**/*.rb\n\n  NewCops: enable\n  TargetRubyVersion: 2.3\n\nLayout/LineLength:\n  Max: 120\n\nNaming/VariableNumber:\n  EnforcedStyle: snake_case\n"
  },
  {
    "path": ".ruby-gemset",
    "content": "scrypt"
  },
  {
    "path": ".ruby-version",
    "content": "ruby-3.4.5\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "3.0.7\n-----\n\nChanges:\n\n* Replaced `scanf` usage to avoid the need for a runtime dependency with the upcoming Ruby 2.7.\n* **Development:** Added Rubocop and rules to the project.\n* Refactored:\n    * Extracted (organized) `Engine`, `Errors` and `Password` class/modules into dedicated files in `scrypt` sub-directory.\n    * Logic and syntax cleanup and formatting.\n\n3.0.6\n-----\nFixed:\n\n* Expanded complication flags in support of macOS Mojave.\n\n3.0.5\n-----\n\nChanges:\n\n* Make `rake` development dependency not runtime\n\n3.0.4\n-----\n\nFixed:\n\n* Compilation on Archlinux\n\n3.0.3\n-----\n\nFixed:\n\n* ~Compilation on Archlinux~\n\n\n3.0.2\n-----\n\nFixed:\n\n* ~~Compilation on Archlinux~~\n\n\n3.0.1\n-----\n\nFixed:\n\n* Windows support was broken in 3.0.0\n\n\n3.0.0\n-----\n\nBreaking Changes:\n\n* None\n\nAdded:\n\n* Updated of core scrypt ext code: https://github.com/pbhogan/scrypt/pull/53\n* Support for platforms other than x86 such as ARM\n\n2.1.1\n-----\n\nChanges:\n\n* Uses more secure defaults: Increased max_mem from 1MB to 16MB, and salt_len from 8 to 32 bytes.\n* See discussion at https://github.com/pbhogan/scrypt/issues/25\n\n2.0.1\n-----\n\nChanges:\n* Adds a `:cost` option for specifying a cost string (e.g. `'400$8$19$'`) from the `calibrate` method\n  (https://github.com/pbhogan/scrypt/commit/95ce6e3e37f4b2e8681a544713bfe783d2d69466)\n\n2.0.0\n-----\n\nBreaking Changes:\n\n* `SCrypt::Password#hash` has been renamed to `#checksum`\n  (https://github.com/pbhogan/scrypt/commit/a1a60e06ec9d863c3156ac06fda32ce82cddd759)\n\n"
  },
  {
    "path": "COPYING",
    "content": "Copyright 2010 Patrick Hogan <pbhogan@gmail.com>\n\nOriginal implementation of scrypt by Colin Percival.\nThis product includes software developed by Coda Hale.\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n3. The name of the author may not be used to endorse or promote products\n   derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Gemfile",
    "content": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\ngemspec\n\ngroup :development, :test do\n  gem 'irb'\n  gem 'rdoc', '~> 6'\n\n  gem 'rake', '~> 13'\n  gem 'rspec', '~> 3'\n\n  if RUBY_VERSION >= '3.0.0'\n    gem 'rubocop', '~> 1'\n    gem 'rubocop-performance', '~> 1'\n    gem 'rubocop-rake', '~> 0.7'\n    gem 'rubocop-rspec', '~> 3'\n  end\nend\n"
  },
  {
    "path": "README.md",
    "content": "# scrypt\n\nA Ruby library providing a secure password hashing solution using the scrypt key derivation function.\n\n[![Gem Version](https://badge.fury.io/rb/scrypt.svg)](https://badge.fury.io/rb/scrypt) [![Ruby](https://github.com/pbhogan/scrypt/actions/workflows/ruby.yml/badge.svg)](https://github.com/pbhogan/scrypt/actions/workflows/ruby.yml)\n\n## About scrypt\n\nThe scrypt key derivation function is designed to be far more secure against hardware brute-force attacks than alternative functions such as PBKDF2 or bcrypt. It accomplishes this by being deliberately memory-intensive, making it expensive to implement in hardware.\n\n**Key Features:**\n- Memory-hard function that resists ASIC and FPGA attacks\n- Configurable computational cost, memory usage, and parallelization\n- Drop-in replacement for bcrypt in most applications\n- Production-ready and battle-tested\n\n**Resources:**\n- [Original scrypt paper](http://www.tarsnap.com/scrypt.html)\n- [GitHub repository](http://github.com/pbhogan/scrypt)\n\n## Why you should use scrypt\n\n![KDF comparison](https://github.com/tarcieri/scrypt/raw/modern-readme/kdf-comparison.png)\n\nThe designers of scrypt estimate that on modern (2009) hardware, if 5 seconds are spent computing a derived key, the cost of a hardware brute-force attack against scrypt is roughly 4,000 times greater than the cost of a similar attack against bcrypt (to find the same password), and 20,000 times greater than a similar attack against PBKDF2.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'scrypt'\n```\n\nAnd then execute:\n\n```bash\nbundle install\n```\n\nOr install it yourself as:\n\n```bash\ngem install scrypt\n```\n\n## Basic Usage\n\nThe scrypt gem works similarly to ruby-bcrypt with a few minor differences, especially regarding the cost factor configuration.\n\n```ruby\nrequire \"scrypt\"\n\n# Hash a user's password\npassword = SCrypt::Password.create(\"my grand secret\")\n# => \"400$8$36$78f4ae6983f76119$37ec6ce55a2b928dc56ff9a7d0cdafbd7dbde49d9282c38a40b1434e88f24cf5\"\n\n# Compare passwords\npassword == \"my grand secret\" # => true\npassword == \"a paltry guess\"  # => false\n```\n\n### Configuration Options\n\n`Password.create` accepts several options to customize the key length, salt size, and computational cost limits:\n\n* **`:key_len`** - Length in bytes of the generated key. Default: 32 bytes (256 bits). Range: 16-512 bytes.\n* **`:salt_size`** - Size in bytes of the random salt. Default: 32 bytes (256 bits). Range: 8-32 bytes.\n* **`:max_time`** - Maximum computation time in seconds. Default: 0.2 seconds.\n* **`:max_mem`** - Maximum memory usage in bytes. Default: 16 MB. Set to 0 for no limit (minimum 1 MB).\n* **`:max_memfrac`** - Maximum memory as a fraction of available resources. Default: 0.5. Range: 0-0.5.\n* **`:cost`** - Explicit cost string from `calibrate` method (e.g., `'400$8$19$'`). When provided, `max_*` options are ignored.\n\n**Note:** Default options result in approximately 200ms computation time with 16 MB memory usage.\n\n## Advanced Usage\n\n### Engine Methods\n\nThe scrypt gem provides low-level access to the scrypt algorithm through the `SCrypt::Engine` class:\n\n```ruby\nrequire \"scrypt\"\n\n# Calibrate scrypt parameters for your system\nSCrypt::Engine.calibrate\n# => \"400$8$25$\"\n\n# Generate a salt with default parameters\nsalt = SCrypt::Engine.generate_salt\n# => \"400$8$26$b62e0f787a5fc373\"\n\n# Hash a secret with a specific salt\nSCrypt::Engine.hash_secret(\"my grand secret\", salt)\n# => \"400$8$26$b62e0f787a5fc373$0399ccd4fa26642d92741b17c366b7f6bd12ccea5214987af445d2bed97bc6a2\"\n\n# Calibrate with custom memory limits and save for future use\nSCrypt::Engine.calibrate!(max_mem: 16 * 1024 * 1024)\n# => \"4000$8$4$\"\n\n# Subsequent salt generation will use the calibrated parameters\nSCrypt::Engine.generate_salt\n# => \"4000$8$4$c6d101522d3cb045\"\n```\n\n### Password Creation with Custom Options\n\n```ruby\n# Create password with custom parameters\npassword = SCrypt::Password.create(\"my secret\", {\n  key_len: 64,\n  salt_size: 16,\n  max_time: 0.5,\n  max_mem: 32 * 1024 * 1024\n})\n\n# Create password with pre-calibrated cost\ncost = SCrypt::Engine.calibrate(max_time: 0.1)\npassword = SCrypt::Password.create(\"my secret\", cost: cost)\n```\n\n## Usage in Rails (and the like)\n\n```ruby\n## Usage in Rails (and similar frameworks)\n\n# Store password safely in the user model\nuser.update_attribute(:password, SCrypt::Password.create(\"my grand secret\"))\n\n# Read it back later\nuser.reload!\npassword = SCrypt::Password.new(user.password)\npassword == \"my grand secret\" # => true\n```\n\n## Security Considerations\n\n* **Memory Safety**: The scrypt algorithm requires significant memory, making it resistant to hardware-based attacks\n* **Time-Memory Trade-off**: Higher memory requirements make it expensive to parallelize attacks\n* **Parameter Selection**: Use `calibrate` to find optimal parameters for your system's performance requirements\n* **Salt Generation**: Always use cryptographically secure random salts (handled automatically)\n\n## Performance Tuning\n\nThe scrypt parameters can be tuned based on your security and performance requirements:\n\n```ruby\n# For high-security applications (slower)\npassword = SCrypt::Password.create(\"secret\", max_time: 1.0, max_mem: 64 * 1024 * 1024)\n\n# For faster authentication (less secure)\npassword = SCrypt::Password.create(\"secret\", max_time: 0.1, max_mem: 8 * 1024 * 1024)\n\n# Calibrate once and reuse parameters\nSCrypt::Engine.calibrate!(max_time: 0.5)\n# All subsequent Password.create calls will use these parameters\n```\n\n## Error Handling\n\nThe library raises specific exceptions for different error conditions:\n\n```ruby\nbegin\n  SCrypt::Password.new(\"invalid_hash_format\")\nrescue SCrypt::Errors::InvalidHash => e\n  puts \"Invalid hash format: #{e.message}\"\nend\n\nbegin\n  SCrypt::Engine.hash_secret(nil, \"salt\")\nrescue SCrypt::Errors::InvalidSecret => e\n  puts \"Invalid secret: #{e.message}\"\nend\n```\n\n## Contributing\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n## Acknowledgments\n\n### Original scrypt Algorithm\n- **Colin Percival** and **Tarsnap** for creating the scrypt key derivation function and providing the reference implementation\n- The original scrypt paper: [Stronger Key Derivation via Sequential Memory-Hard Functions](http://www.tarsnap.com/scrypt.html)\n\n### Core Collaborators\n\n- **Patrick Hogan** ([@pbhogan](https://github.com/pbhogan))\n- **Stephen von Takach** ([@stakach](https://github.com/stakach))\n- **Rene van Paassen** ([@repagh](https://github.com/repagh))\n- **Johanns Gregorian** ([@johanns](https://github.com/johanns))\n\n### Special Thanks\n- The Ruby community for testing and feedback\n- Contributors who have submitted bug reports, feature requests, and patches\n- The cryptography community for security reviews and recommendations\n\n## License\n\nThis project is licensed under the BSD-3-Clause License - see the [COPYING](COPYING) file for details.\n"
  },
  {
    "path": "Rakefile",
    "content": "# frozen_string_literal: true\n\nrequire 'bundler/setup'\nrequire 'bundler/gem_tasks'\nrequire 'digest/sha2'\n\nrequire 'ffi'\nrequire 'ffi-compiler/compile_task'\n\nrequire 'fileutils'\nrequire 'rake'\nrequire 'rake/clean'\nrequire 'rdoc/task'\n\nrequire 'rspec/core/rake_task'\n\nrequire 'rubygems'\nrequire 'rubygems/package_task'\n\nrequire './lib/scrypt/version'\n\ntask default: %i[clean compile_ffi spec]\n\ndesc 'Run all specs'\nRSpec::Core::RakeTask.new(:spec) do |t|\n  t.rspec_opts = ['--color', '--backtrace', '--format', 'documentation']\nend\n\ndesc 'Generate checksum for built gem'\ntask :checksum do\n  built_gem_path = \"pkg/scrypt-#{SCrypt::VERSION}.gem\"\n\n  unless File.exist?(built_gem_path)\n    puts \"Gem file not found: #{built_gem_path}\"\n    puts \"Run 'rake build' first to create the gem.\"\n    exit 1\n  end\n\n  checksum = Digest::SHA512.new.hexdigest(File.read(built_gem_path))\n  checksum_path = \"checksum/scrypt-#{SCrypt::VERSION}.gem.sha512\"\n\n  # Ensure checksum directory exists\n  FileUtils.mkdir_p(File.dirname(checksum_path))\n\n  File.write(checksum_path, checksum)\n  puts \"Checksum written to: #{checksum_path}\"\nend\n\ndesc 'Compile FFI extension'\nnamespace :ffi_compiler do\n  FFI::Compiler::CompileTask.new('ext/scrypt/scrypt_ext') do |t|\n    target_cpu = RbConfig::CONFIG['target_cpu']\n\n    t.cflags << '-Wall -std=c99'\n    t.cflags << '-msse -msse2' if t.platform.arch.include?('86')\n    t.cflags << '-D_GNU_SOURCE=1' if RbConfig::CONFIG['host_os'].downcase =~ /mingw/\n    t.cflags << '-D_POSIX_C_SOURCE=200809L' if RbConfig::CONFIG['host_os'].downcase =~ /linux/\n\n    if 1.size == 4 && target_cpu =~ /i386|x86_32/ && t.platform.mac?\n      t.cflags << '-arch i386'\n      t.ldflags << '-arch i386'\n    elsif 1.size == 8 && target_cpu =~ /i686|x86_64/ && t.platform.mac?\n      t.cflags << '-arch x86_64'\n      t.ldflags << '-arch x86_64'\n    end\n\n    t.add_define 'WINDOWS_OS' if FFI::Platform.windows?\n  end\nend\ntask compile_ffi: ['ffi_compiler:default']\n\nCLEAN.include('ext/scrypt/*{.o,.log,.so,.bundle}')\nCLEAN.include('lib/**/*{.o,.log,.so,.bundle}')\n\ndesc 'Generate RDoc documentation'\nRDoc::Task.new(:rdoc) do |rdoc|\n  rdoc.rdoc_dir = 'doc/rdoc'\n  rdoc.options << '--force-update'\n  rdoc.options << '-V'\n\n  rdoc.template = ENV['TEMPLATE'] if ENV['TEMPLATE']\nend\n\ndesc 'Run all specs'\nRSpec::Core::RakeTask.new do |_t|\n  # Task automatically runs specs based on RSpec defaults\nend\n\ndef gem_spec\n  @gem_spec ||= Gem::Specification.load('scrypt.gemspec')\nend\n\nGem::PackageTask.new(gem_spec) do |pkg|\n  pkg.need_zip = true\n  pkg.need_tar = true\n  pkg.package_dir = 'pkg'\nend\n"
  },
  {
    "path": "certs/pbhogan.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MRAwDgYDVQQDDAdwYmhv\nZ2FuMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w\nHhcNMjUwNzIyMTM1NDMxWhcNMjYwNzIyMTM1NDMxWjA+MRAwDgYDVQQDDAdwYmhv\nZ2FuMRUwEwYKCZImiZPyLGQBGRYFZ21haWwxEzARBgoJkiaJk/IsZAEZFgNjb20w\nggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQCSWjGKTBcJNoRa0QeIh0Au\n6uAZ2daA43tu9Kst/DTB3OdsDfZnnJu9NftgmNTw7di9ZTQFH4+BrQg2/HodvZdP\n+HvZecC3ZxXu/US8f+ryz70BrFz1ve+xW11bKNDlw+KkCVmlZobqYQMUuCXjU6wD\ns5lGHGXiiK5tDK9US1rFqK5aV35gibpPaNRBRlEdmGKABmhhdNQw6fVDzfIWxIvE\nIgeTVTvnSAmVfO8F1pH73fRL3zGWXirK8gg09i118POoT7FLtvgU6QzZu46DPhph\nYMgLRK+RM+aAvVa0IH/cD94SrgHXrK82SXKgrccnYTUajiO+BemUWY82dRWWQnW6\n5SSs1KYlNqo2OE5Fx6cSmcCdXermtidRj9SVVK6cp3Z+V4dNCMwe5d0PkmhbcLqH\nxxIb9GFU0Tl7qVnyzuTAHkEbhGM6vTlOnggQzmDQJGT/urpUnYXkPqYiOFB58UWR\nzoUJzGbzGkoyt+8IK2Wi4T0FM+iIjM+nWKfHyx1BKA8CAwEAAaN1MHMwCQYDVR0T\nBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEF+cJzNMLtyKh6xGnlyx97tiHCl\nMBwGA1UdEQQVMBOBEXBiaG9nYW5AZ21haWwuY29tMBwGA1UdEgQVMBOBEXBiaG9n\nYW5AZ21haWwuY29tMA0GCSqGSIb3DQEBCwUAA4IBgQAsiXgPScyfZqqrUkaykumD\nXtahlA0BcS9fchzkf21qd8w34L5I8gyz3fvAJXPAvSqZPSWEn6ud/TOxhXmG6+K/\nrZ7J1iKbGpk3/yMmmkyTLsItloc4xABTRjyJ4Cy1wuJ4kdwgIW/kHTwWG0PFA1YF\nZoqZijAXbTQ4Z+wTcRiUjVpbizB4MtmaQb+Mrr+zxeEmRv/B8iZdkRCZ02C1u+T+\nbwvmftjB0xuKvPmHP1KpSnFh3I4uvlykDMVSNwE0pKlGsVrzkJFf68R2YZJgDwiH\nGmXe0sAsp14rX0I+JyC6a35TPrC7o1PH1zWLSJn2hBIbA/fObf8CAwNRIVHUTTUt\nkr/2/0UpZZ6O3j7S8lovBRVi6Cv+P6avNYOiQpOH0kJyaSw2LMLl87D7t3JYQ0+8\nrTgQJuEZY0TADK4NMJujsMEok9mO6Qfj4d+dVYdpFfuFgYf/LVnpT4sZ8bKVn0PQ\nKtQ2gCSB20nUFBsuf/VRbsMWL+MxzesANGDEIrEXNS0=\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "certs/stakach.pem",
    "content": "-----BEGIN CERTIFICATE-----\nMIIEfDCCAuSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBCMQ4wDAYDVQQDDAVzdGV2\nZTEbMBkGCgmSJomT8ixkARkWC2FjYXByb2plY3RzMRMwEQYKCZImiZPyLGQBGRYD\nY29tMB4XDTE5MTExMzIzMDMwMFoXDTIwMTExMjIzMDMwMFowQjEOMAwGA1UEAwwF\nc3RldmUxGzAZBgoJkiaJk/IsZAEZFgthY2Fwcm9qZWN0czETMBEGCgmSJomT8ixk\nARkWA2NvbTCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALtarCg2Ux+m\nXjcGQ6XVxRbVwwVUxGWIBfpKXzq23WOXk0NkRooyYLuxSfkA/PFVd5OLZTMP+ULr\nKgM9w7+xR/Xhs/qxib/84u54H8rqHTCozYmldR5QpYTwsB4BeG0HpSbD0PGL+4N+\noa50wRyvwVBAZMG4F4QYUGnQlwBpLSm4Fhm6xhKqD9DDhbS5jgIg/S3Cr4dqghUG\nkqsIGjKd6X9wIOIqF1IWLZkXiwN1IcKCJ9FO2iTBEo7UidJXROO5xs5D0Vr3iyiw\nF3tmhpq1C7KkXkv0AxAxRK3SmdpIiagRukvdNFEAcpkgX6qUg62G8KMRGc3dP9lx\ntBP8IonLEcpLktQakuqsV4YETQaKQb5F4WADxh1tvIPcYJUxHsw3sdHZeDywT3De\nLPCNTbuBseIF33hj2qiZ77XMusgVxiqG1eaCD0X58zeVTd7ZDZUFuVKlgAudhyOi\nO30rMiCHNIchQqwVNLah0Tu4KAF7PGAwJhu01qMXOEl9WCEtApOS6wIDAQABo30w\nezAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUjrc6E0haseLehiw2\nJME0lZzbYKMwIAYDVR0RBBkwF4EVc3RldmVAYWNhcHJvamVjdHMuY29tMCAGA1Ud\nEgQZMBeBFXN0ZXZlQGFjYXByb2plY3RzLmNvbTANBgkqhkiG9w0BAQsFAAOCAYEA\nfpmwkaIoCUA8A5IDHTcGWDX5gFYwhrRLMPwvdbU3r9RUeo7slWjek1OCAH4gyLUM\nK+OeWIYyQjOzeRHllNapY3AnOWbwXX7rVrYa0OxFd8JgXgVS/XJR4elzNJ0lb8En\nszSDkj4xl2Yn7FDZBsT+Oq19zMKFZNSF3SYumTuLMq3AdJa3vO2Gg4I1r8oSfZBB\n5V81o2GU9YTGCNrl57dmq+Iop1qVU9jF60wEXyiOz/Fkhvk+kdz2PveH8nhlpBiw\nt3kOzg645P903giemoqlYZJ1XTmBqHLhflfTSxNie6my4izqFQgB9UxtUeesRtaJ\n5y48Vz2twr2OQfw+1lM//SY/H9rPJkaOPDM7AlPodnZvYrr1hAlwXUebgmOq+Mvm\n13PWwCGItI0lMBPfAfadtZKJQNvzl4K4Iq76ksQy3tobcrYw1r4cKTyqvrrrKhWn\n93B950TkkA8h64SLwNEzV3ayjvGKTI95l0cz0B1STPIwvQecQI2j1y8/DzyztNXO\n-----END CERTIFICATE-----\n"
  },
  {
    "path": "checksum/scrypt-3.0.6.gem.sha512",
    "content": "fb1b89bddfd5fa440994aad7f3edc6cce588c41018bf60ba82eab927863e243025c2e25094be2dfefdbe21a022dec62bdd072284ff83e472071791ff69bcb949"
  },
  {
    "path": "ext/alt-impl/crypto_scrypt-nosse.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include \"scrypt_platform.h\"\n\n#include <sys/types.h>\n#ifndef __MINGW32__\n#include <sys/mman.h>\n#endif\n\n#include <errno.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"sha256.h\"\n#include \"sysendian.h\"\n\n#include \"crypto_scrypt.h\"\n\nstatic void blkcpy(void *, void *, size_t);\nstatic void blkxor(void *, void *, size_t);\nstatic void salsa20_8(uint32_t[16]);\nstatic void blockmix_salsa8(uint32_t *, uint32_t *, uint32_t *, size_t);\nstatic uint64_t integerify(void *, size_t);\nstatic void smix(uint8_t *, size_t, uint64_t, uint32_t *, uint32_t *);\n\nstatic void\nblkcpy(void * dest, void * src, size_t len)\n{\n\tsize_t * D = dest;\n\tsize_t * S = src;\n\tsize_t L = len / sizeof(size_t);\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] = S[i];\n}\n\nstatic void\nblkxor(void * dest, void * src, size_t len)\n{\n\tsize_t * D = dest;\n\tsize_t * S = src;\n\tsize_t L = len / sizeof(size_t);\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] ^= S[i];\n}\n\n/**\n * salsa20_8(B):\n * Apply the salsa20/8 core to the provided block.\n */\nstatic void\nsalsa20_8(uint32_t B[16])\n{\n\tuint32_t x[16];\n\tsize_t i;\n\n\tblkcpy(x, B, 64);\n\tfor (i = 0; i < 8; i += 2) {\n#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))\n\t\t/* Operate on columns. */\n\t\tx[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9);\n\t\tx[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18);\n\n\t\tx[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9);\n\t\tx[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18);\n\n\t\tx[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9);\n\t\tx[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18);\n\n\t\tx[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9);\n\t\tx[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18);\n\n\t\t/* Operate on rows. */\n\t\tx[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9);\n\t\tx[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18);\n\n\t\tx[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9);\n\t\tx[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18);\n\n\t\tx[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9);\n\t\tx[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18);\n\n\t\tx[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9);\n\t\tx[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18);\n#undef R\n\t}\n\tfor (i = 0; i < 16; i++)\n\t\tB[i] += x[i];\n}\n\n/**\n * blockmix_salsa8(Bin, Bout, X, r):\n * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r\n * bytes in length; the output Bout must also be the same size.  The\n * temporary space X must be 64 bytes.\n */\nstatic void\nblockmix_salsa8(uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)\n{\n\tsize_t i;\n\n\t/* 1: X <-- B_{2r - 1} */\n\tblkcpy(X, &Bin[(2 * r - 1) * 16], 64);\n\n\t/* 2: for i = 0 to 2r - 1 do */\n\tfor (i = 0; i < 2 * r; i += 2) {\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 16], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[i * 8], X, 64);\n\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 16 + 16], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[i * 8 + r * 16], X, 64);\n\t}\n}\n\n/**\n * integerify(B, r):\n * Return the result of parsing B_{2r-1} as a little-endian integer.\n */\nstatic uint64_t\nintegerify(void * B, size_t r)\n{\n\tuint32_t * X = (void *)((uintptr_t)(B) + (2 * r - 1) * 64);\n\n\treturn (((uint64_t)(X[1]) << 32) + X[0]);\n}\n\n/**\n * smix(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;\n * the temporary storage V must be 128rN bytes in length; the temporary\n * storage XY must be 256r + 64 bytes in length.  The value N must be a\n * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a\n * multiple of 64 bytes.\n */\nstatic void\nsmix(uint8_t * B, size_t r, uint64_t N, uint32_t * V, uint32_t * XY)\n{\n\tuint32_t * X = XY;\n\tuint32_t * Y = &XY[32 * r];\n\tuint32_t * Z = &XY[64 * r];\n\tuint64_t i;\n\tuint64_t j;\n\tsize_t k;\n\n\t/* 1: X <-- B */\n\tfor (k = 0; k < 32 * r; k++)\n\t\tX[k] = le32dec(&B[4 * k]);\n\n\t/* 2: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy(&V[i * (32 * r)], X, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 6: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(X, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(X, &V[j * (32 * r)], 128 * r);\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(Y, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(Y, &V[j * (32 * r)], 128 * r);\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 10: B' <-- X */\n\tfor (k = 0; k < 32 * r; k++)\n\t\tle32enc(&B[4 * k], X[k]);\n}\n\n/**\n * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):\n * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,\n * p, buflen) and write the result into buf.  The parameters r, p, and buflen\n * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N\n * must be a power of 2 greater than 1.\n *\n * Return 0 on success; or -1 on error.\n */\nint\ncrypto_scrypt(const uint8_t * passwd, size_t passwdlen,\n    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,\n    uint8_t * buf, size_t buflen)\n{\n\tvoid * B0, * V0, * XY0;\n\tuint8_t * B;\n\tuint32_t * V;\n\tuint32_t * XY;\n\tsize_t r = _r, p = _p;\n\tuint32_t i;\n\n\t/* Sanity-check parameters. */\n#if SIZE_MAX > UINT32_MAX\n\tif (buflen > (((uint64_t)(1) << 32) - 1) * 32) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n#endif\n\tif ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n\tif (((N & (N - 1)) != 0) || (N < 2)) {\n\t\terrno = EINVAL;\n\t\tgoto err0;\n\t}\n\tif ((r > SIZE_MAX / 128 / p) ||\n#if SIZE_MAX / 256 <= UINT32_MAX\n\t    (r > SIZE_MAX / 256) ||\n#endif\n\t    (N > SIZE_MAX / 128 / r)) {\n\t\terrno = ENOMEM;\n\t\tgoto err0;\n\t}\n\n\t/* Allocate memory. */\n#ifdef HAVE_POSIX_MEMALIGN\n\tif ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)\n\t\tgoto err0;\n\tB = (uint8_t *)(B0);\n\tif ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)\n\t\tgoto err1;\n\tXY = (uint32_t *)(XY0);\n#ifndef MAP_ANON\n\tif ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)\n\t\tgoto err2;\n\tV = (uint32_t *)(V0);\n#endif\n#else\n\tif ((B0 = malloc(128 * r * p + 63)) == NULL)\n\t\tgoto err0;\n\tB = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));\n\tif ((XY0 = malloc(256 * r + 64 + 63)) == NULL)\n\t\tgoto err1;\n\tXY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));\n#ifndef MAP_ANON\n\tif ((V0 = malloc(128 * r * N + 63)) == NULL)\n\t\tgoto err2;\n\tV = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));\n#endif\n#endif\n#ifdef MAP_ANON\n\tif ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,\n#ifdef MAP_NOCORE\n\t    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,\n#else\n\t    MAP_ANON | MAP_PRIVATE,\n#endif\n\t    -1, 0)) == MAP_FAILED)\n\t\tgoto err2;\n\tV = (uint32_t *)(V0);\n#endif\n\n\t/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */\n\tPBKDF2_scrypt_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);\n\n\t/* 2: for i = 0 to p - 1 do */\n\tfor (i = 0; i < p; i++) {\n\t\t/* 3: B_i <-- MF(B_i, N) */\n\t\tsmix(&B[i * 128 * r], r, N, V, XY);\n\t}\n\n\t/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */\n\tPBKDF2_scrypt_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);\n\n\t/* Free memory. */\n#ifdef MAP_ANON\n\tif (munmap(V0, 128 * r * N))\n\t\tgoto err2;\n#else\n\tfree(V0);\n#endif\n\tfree(XY0);\n\tfree(B0);\n\n\t/* Success! */\n\treturn (0);\n\nerr2:\n\tfree(XY0);\nerr1:\n\tfree(B0);\nerr0:\n\t/* Failure! */\n\treturn (-1);\n}\n"
  },
  {
    "path": "ext/alt-impl/crypto_scrypt-ref.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include \"scrypt_platform.h\"\n\n#include <errno.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"sha256.h\"\n#include \"sysendian.h\"\n\n#include \"crypto_scrypt.h\"\n\nstatic void blkcpy(uint8_t *, uint8_t *, size_t);\nstatic void blkxor(uint8_t *, uint8_t *, size_t);\nstatic void salsa20_8(uint8_t[64]);\nstatic void blockmix_salsa8(uint8_t *, uint8_t *, size_t);\nstatic uint64_t integerify(uint8_t *, size_t);\nstatic void smix(uint8_t *, size_t, uint64_t, uint8_t *, uint8_t *);\n\nstatic void\nblkcpy(uint8_t * dest, uint8_t * src, size_t len)\n{\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++)\n\t\tdest[i] = src[i];\n}\n\nstatic void\nblkxor(uint8_t * dest, uint8_t * src, size_t len)\n{\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++)\n\t\tdest[i] ^= src[i];\n}\n\n/**\n * salsa20_8(B):\n * Apply the salsa20/8 core to the provided block.\n */\nstatic void\nsalsa20_8(uint8_t B[64])\n{\n\tuint32_t B32[16];\n\tuint32_t x[16];\n\tsize_t i;\n\n\t/* Convert little-endian values in. */\n\tfor (i = 0; i < 16; i++)\n\t\tB32[i] = le32dec(&B[i * 4]);\n\n\t/* Compute x = doubleround^4(B32). */\n\tfor (i = 0; i < 16; i++)\n\t\tx[i] = B32[i];\n\tfor (i = 0; i < 8; i += 2) {\n#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))\n\t\t/* Operate on columns. */\n\t\tx[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9);\n\t\tx[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18);\n\n\t\tx[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9);\n\t\tx[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18);\n\n\t\tx[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9);\n\t\tx[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18);\n\n\t\tx[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9);\n\t\tx[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18);\n\n\t\t/* Operate on rows. */\n\t\tx[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9);\n\t\tx[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18);\n\n\t\tx[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9);\n\t\tx[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18);\n\n\t\tx[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9);\n\t\tx[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18);\n\n\t\tx[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9);\n\t\tx[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18);\n#undef R\n\t}\n\n\t/* Compute B32 = B32 + x. */\n\tfor (i = 0; i < 16; i++)\n\t\tB32[i] += x[i];\n\n\t/* Convert little-endian values out. */\n\tfor (i = 0; i < 16; i++)\n\t\tle32enc(&B[4 * i], B32[i]);\n}\n\n/**\n * blockmix_salsa8(B, Y, r):\n * Compute B = BlockMix_{salsa20/8, r}(B).  The input B must be 128r bytes in\n * length; the temporary space Y must also be the same size.\n */\nstatic void\nblockmix_salsa8(uint8_t * B, uint8_t * Y, size_t r)\n{\n\tuint8_t X[64];\n\tsize_t i;\n\n\t/* 1: X <-- B_{2r - 1} */\n\tblkcpy(X, &B[(2 * r - 1) * 64], 64);\n\n\t/* 2: for i = 0 to 2r - 1 do */\n\tfor (i = 0; i < 2 * r; i++) {\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &B[i * 64], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\tblkcpy(&Y[i * 64], X, 64);\n\t}\n\n\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\tfor (i = 0; i < r; i++)\n\t\tblkcpy(&B[i * 64], &Y[(i * 2) * 64], 64);\n\tfor (i = 0; i < r; i++)\n\t\tblkcpy(&B[(i + r) * 64], &Y[(i * 2 + 1) * 64], 64);\n}\n\n/**\n * integerify(B, r):\n * Return the result of parsing B_{2r-1} as a little-endian integer.\n */\nstatic uint64_t\nintegerify(uint8_t * B, size_t r)\n{\n\tuint8_t * X = &B[(2 * r - 1) * 64];\n\n\treturn (le64dec(X));\n}\n\n/**\n * smix(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length; the\n * temporary storage V must be 128rN bytes in length; the temporary storage\n * XY must be 256r bytes in length.  The value N must be a power of 2.\n */\nstatic void\nsmix(uint8_t * B, size_t r, uint64_t N, uint8_t * V, uint8_t * XY)\n{\n\tuint8_t * X = XY;\n\tuint8_t * Y = &XY[128 * r];\n\tuint64_t i;\n\tuint64_t j;\n\n\t/* 1: X <-- B */\n\tblkcpy(X, B, 128 * r);\n\n\t/* 2: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i++) {\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy(&V[i * (128 * r)], X, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(X, Y, r);\n\t}\n\n\t/* 6: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i++) {\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(X, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(X, &V[j * (128 * r)], 128 * r);\n\t\tblockmix_salsa8(X, Y, r);\n\t}\n\n\t/* 10: B' <-- X */\n\tblkcpy(B, X, 128 * r);\n}\n\n/**\n * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):\n * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,\n * p, buflen) and write the result into buf.  The parameters r, p, and buflen\n * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N\n * must be a power of 2.\n *\n * Return 0 on success; or -1 on error.\n */\nint\ncrypto_scrypt(const uint8_t * passwd, size_t passwdlen,\n    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,\n    uint8_t * buf, size_t buflen)\n{\n\tuint8_t * B;\n\tuint8_t * V;\n\tuint8_t * XY;\n\tsize_t r = _r, p = _p;\n\tuint32_t i;\n\n\t/* Sanity-check parameters. */\n#if SIZE_MAX > UINT32_MAX\n\tif (buflen > (((uint64_t)(1) << 32) - 1) * 32) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n#endif\n\tif ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n\tif (((N & (N - 1)) != 0) || (N == 0)) {\n\t\terrno = EINVAL;\n\t\tgoto err0;\n\t}\n\tif ((r > SIZE_MAX / 128 / p) ||\n#if SIZE_MAX / 256 <= UINT32_MAX\n\t    (r > SIZE_MAX / 256) ||\n#endif\n\t    (N > SIZE_MAX / 128 / r)) {\n\t\terrno = ENOMEM;\n\t\tgoto err0;\n\t}\n\n\t/* Allocate memory. */\n\tif ((B = malloc(128 * r * p)) == NULL)\n\t\tgoto err0;\n\tif ((XY = malloc(256 * r)) == NULL)\n\t\tgoto err1;\n\tif ((V = malloc(128 * r * N)) == NULL)\n\t\tgoto err2;\n\n\t/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */\n\tPBKDF2_scrypt_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);\n\n\t/* 2: for i = 0 to p - 1 do */\n\tfor (i = 0; i < p; i++) {\n\t\t/* 3: B_i <-- MF(B_i, N) */\n\t\tsmix(&B[i * 128 * r], r, N, V, XY);\n\t}\n\n\t/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */\n\tPBKDF2_scrypt_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);\n\n\t/* Free memory. */\n\tfree(V);\n\tfree(XY);\n\tfree(B);\n\n\t/* Success! */\n\treturn (0);\n\nerr2:\n\tfree(XY);\nerr1:\n\tfree(B);\nerr0:\n\t/* Failure! */\n\treturn (-1);\n}\n"
  },
  {
    "path": "ext/scrypt/Rakefile",
    "content": "require 'ffi-compiler/compile_task'\n\ntarget_cpu = RbConfig::CONFIG['target_cpu']\n\nFFI::Compiler::CompileTask.new('scrypt_ext') do |t|\n  t.cflags << '-Wall -std=c99'\n  t.cflags << '-msse -msse2' if t.platform.arch.include? '86'\n  t.cflags << '-D_GNU_SOURCE=1' if RbConfig::CONFIG['host_os'].downcase =~ /mingw/\n  t.cflags << '-D_POSIX_C_SOURCE=200809L' if RbConfig::CONFIG['host_os'].downcase =~ /linux/\n\n  if 1.size == 4 && target_cpu =~ /i386|x86_32/ && t.platform.mac?\n    t.cflags << '-arch i386'\n    t.ldflags << '-arch i386'\n  elsif 1.size == 8 && target_cpu =~ /i686|x86_64/ && t.platform.mac?\n    t.cflags << '-arch x86_64'\n    t.ldflags << '-arch x86_64'\n  end\n\n  t.export '../../lib/scrypt/scrypt_ext.rb'\n\n  t.add_define 'WINDOWS_OS' if FFI::Platform.windows?\nend\n"
  },
  {
    "path": "ext/scrypt/cpusupport.h",
    "content": "#ifndef _CPUSUPPORT_H_\n#define _CPUSUPPORT_H_\n\n/*\n * To enable support for non-portable CPU features at compile time, one or\n * more CPUSUPPORT_ARCH_FEATURE macros should be defined.  This can be done\n * directly on the compiler command line via -D CPUSUPPORT_ARCH_FEATURE or\n * -D CPUSUPPORT_ARCH_FEATURE=1; or a file can be created with the\n * necessary #define lines and then -D CPUSUPPORT_CONFIG_FILE=cpuconfig.h\n * (or similar) can be provided to include that file here.\n */\n#ifdef CPUSUPPORT_CONFIG_FILE\n#include CPUSUPPORT_CONFIG_FILE\n#endif\n\n/**\n * The CPUSUPPORT_FEATURE macro declares the necessary variables and\n * functions for detecting CPU feature support at run time.  The function\n * defined in the macro acts to cache the result of the ..._detect function\n * using the ..._present and ..._init variables.  The _detect function and the\n * _present and _init variables are turn defined by CPUSUPPORT_FEATURE_DECL in\n * appropriate cpusupport_foo_bar.c file.\n *\n * In order to allow CPUSUPPORT_FEATURE to be used for features which do not\n * have corresponding CPUSUPPORT_FEATURE_DECL blocks in another source file,\n * we abuse the C preprocessor: If CPUSUPPORT_${enabler} is defined to 1, then\n * we access _present_1, _init_1, and _detect_1; but if it is not defined, we\n * access _present_CPUSUPPORT_${enabler} etc., which we define as static, thus\n * preventing the compiler from emitting a reference to an external symbol.\n *\n * In this way, it becomes possible to issue CPUSUPPORT_FEATURE invocations\n * for nonexistent features without running afoul of the requirement that\n * \"If an identifier declared with external linkage is used... in the entire\n * program there shall be exactly one external definition\" (C99 standard, 6.9\n * paragraph 5).  In practice, this means that users of the cpusupport code\n * can omit build and runtime detection files without changing the framework\n * code.\n */\n#define CPUSUPPORT_FEATURE__(arch_feature, enabler, enabled)\t\t\t\t\t\\\n\tstatic int cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler;\t\t\\\n\tstatic int cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler;\t\t\\\n\tstatic inline int cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler(void) { return (0); }\t\\\n\textern int cpusupport_ ## arch_feature ## _present_ ## enabled;\t\t\t\t\\\n\textern int cpusupport_ ## arch_feature ## _init_ ## enabled;\t\t\t\t\\\n\tint cpusupport_ ## arch_feature ## _detect_ ## enabled(void);\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic inline int\t\t\t\t\t\t\t\t\t\\\n\tcpusupport_ ## arch_feature(void)\t\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\tif (cpusupport_ ## arch_feature ## _present_ ## enabled)\t\t\t\\\n\t\t\treturn (1);\t\t\t\t\t\t\t\t\\\n\t\telse if (cpusupport_ ## arch_feature ## _init_ ## enabled)\t\t\t\\\n\t\t\treturn (0);\t\t\t\t\t\t\t\t\\\n\t\tcpusupport_ ## arch_feature ## _present_ ## enabled = \t\t\t\t\\\n\t\t    cpusupport_ ## arch_feature ## _detect_ ## enabled();\t\t\t\\\n\t\tcpusupport_ ## arch_feature ## _init_ ## enabled = 1;\t\t\t\t\\\n\t\treturn (cpusupport_ ## arch_feature ## _present_ ## enabled); \t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic void (* cpusupport_ ## arch_feature ## _dummyptr)(void);\t\t\t\t\\\n\tstatic inline void\t\t\t\t\t\t\t\t\t\\\n\tcpusupport_ ## arch_feature ## _dummyfunc(void)\t\t\t\t\t\t\\\n\t{\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t\t\t\t\t\t\t\t\t\t\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _present ## _CPUSUPPORT_ ## enabler;\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _init ## _CPUSUPPORT_ ## enabler;\t\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _detect ## _CPUSUPPORT_ ## enabler;\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _present_ ## enabled;\t\t\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _init_ ## enabled;\t\t\t\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _detect_ ## enabled;\t\t\t\\\n\t\t(void)cpusupport_ ## arch_feature ## _dummyptr;\t\t\t\t\t\\\n\t}\t\t\t\t\t\t\t\t\t\t\t\\\n\tstatic void (* cpusupport_ ## arch_feature ## _dummyptr)(void) = cpusupport_ ## arch_feature ## _dummyfunc;\t\\\n\tstruct cpusupport_ ## arch_feature ## _dummy\n#define CPUSUPPORT_FEATURE_(arch_feature, enabler, enabled)\t\\\n\tCPUSUPPORT_FEATURE__(arch_feature, enabler, enabled)\n#define CPUSUPPORT_FEATURE(arch, feature, enabler)\t\t\t\t\\\n\tCPUSUPPORT_FEATURE_(arch ## _ ## feature, enabler, CPUSUPPORT_ ## enabler)\n\n/*\n * CPUSUPPORT_FEATURE_DECL(arch, feature):\n * Macro which defines variables and provides a function declaration for\n * detecting the presence of \"feature\" on the \"arch\" architecture.  The\n * function body following this macro expansion must return nonzero if the\n * feature is present, or zero if the feature is not present or the detection\n * fails for any reason.\n */\n#define CPUSUPPORT_FEATURE_DECL(arch, feature)\t\t\t\t\\\n\tint cpusupport_ ## arch ## _ ## feature ## _present_1 = 0;\t\\\n\tint cpusupport_ ## arch ## _ ## feature ## _init_1 = 0;\t\t\\\n\tint\t\t\t\t\t\t\t\t\\\n\tcpusupport_ ## arch ## _ ## feature ## _detect_1(void)\n\n/*\n * List of features.  If a feature here is not enabled by the appropriate\n * CPUSUPPORT_ARCH_FEATURE macro being defined, it has no effect; but if the\n * relevant macro may be defined (e.g., by Build/cpusupport.sh successfully\n * compiling Build/cpusupport-ARCH-FEATURE.c) then the C file containing the\n * corresponding run-time detection code (cpusupport_arch_feature.c) must be\n * compiled and linked in.\n */\nCPUSUPPORT_FEATURE(x86, aesni, X86_AESNI);\nCPUSUPPORT_FEATURE(x86, sse2, X86_SSE2);\n\n#endif /* !_CPUSUPPORT_H_ */\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n/* #include \"bsdtar_platform.h\" */\n\n#include <sys/types.h>\n#if !defined(WINDOWS_OS)\n \t#include <sys/mman.h>\n \t#ifndef HAVE_MMAP\n\t\t#define HAVE_MMAP 1\n \t#endif\n#endif\n#include <errno.h>\n#include <stdint.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"cpusupport.h\"\n#include \"sha256.h\"\n//#include \"warnp.h\"\n\n#include \"crypto_scrypt_smix.h\"\n#include \"crypto_scrypt_smix_sse2.h\"\n\n#include \"crypto_scrypt.h\"\n#include \"warnp.h\"\n\nstatic void (*smix_func)(uint8_t *, size_t, uint64_t, void *, void *) = NULL;\n\n/**\n * _crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen, smix):\n * Perform the requested scrypt computation, using ${smix} as the smix routine.\n */\nstatic int\n_crypto_scrypt(const uint8_t * passwd, size_t passwdlen,\n    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,\n    uint8_t * buf, size_t buflen,\n    void (*smix)(uint8_t *, size_t, uint64_t, void *, void *))\n{\n\tvoid * B0, * V0, * XY0;\n\tuint8_t * B;\n\tuint32_t * V;\n\tuint32_t * XY;\n\tsize_t r = _r, p = _p;\n\tuint32_t i;\n\n\t/* Sanity-check parameters. */\n#if SIZE_MAX > UINT32_MAX\n\tif (buflen > (((uint64_t)(1) << 32) - 1) * 32) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n#endif\n\tif ((uint64_t)(r) * (uint64_t)(p) >= (1 << 30)) {\n\t\terrno = EFBIG;\n\t\tgoto err0;\n\t}\n\tif (((N & (N - 1)) != 0) || (N < 2)) {\n\t\terrno = EINVAL;\n\t\tgoto err0;\n\t}\n\tif ((r > SIZE_MAX / 128 / p) ||\n#if SIZE_MAX / 256 <= UINT32_MAX\n\t    (r > (SIZE_MAX - 64) / 256) ||\n#endif\n\t    (N > SIZE_MAX / 128 / r)) {\n\t\terrno = ENOMEM;\n\t\tgoto err0;\n\t}\n\n\t/* Allocate memory. */\n#ifdef HAVE_POSIX_MEMALIGN\n\tif ((errno = posix_memalign(&B0, 64, 128 * r * p)) != 0)\n\t\tgoto err0;\n\tB = (uint8_t *)(B0);\n\tif ((errno = posix_memalign(&XY0, 64, 256 * r + 64)) != 0)\n\t\tgoto err1;\n\tXY = (uint32_t *)(XY0);\n#if !defined(MAP_ANON) || !defined(HAVE_MMAP)\n\tif ((errno = posix_memalign(&V0, 64, 128 * r * N)) != 0)\n\t\tgoto err2;\n\tV = (uint32_t *)(V0);\n#endif\n#else\n\tif ((B0 = malloc(128 * r * p + 63)) == NULL)\n\t\tgoto err0;\n\tB = (uint8_t *)(((uintptr_t)(B0) + 63) & ~ (uintptr_t)(63));\n\tif ((XY0 = malloc(256 * r + 64 + 63)) == NULL)\n\t\tgoto err1;\n\tXY = (uint32_t *)(((uintptr_t)(XY0) + 63) & ~ (uintptr_t)(63));\n#if !defined(MAP_ANON) || !defined(HAVE_MMAP)\n\tif ((V0 = malloc(128 * r * N + 63)) == NULL)\n\t\tgoto err2;\n\tV = (uint32_t *)(((uintptr_t)(V0) + 63) & ~ (uintptr_t)(63));\n#endif\n#endif\n#if defined(MAP_ANON) && defined(HAVE_MMAP)\n\tif ((V0 = mmap(NULL, 128 * r * N, PROT_READ | PROT_WRITE,\n#ifdef MAP_NOCORE\n\t    MAP_ANON | MAP_PRIVATE | MAP_NOCORE,\n#else\n\t    MAP_ANON | MAP_PRIVATE,\n#endif\n\t    -1, 0)) == MAP_FAILED)\n\t\tgoto err2;\n\tV = (uint32_t *)(V0);\n#endif\n\n\t/* 1: (B_0 ... B_{p-1}) <-- PBKDF2(P, S, 1, p * MFLen) */\n\tPBKDF2_SHA256(passwd, passwdlen, salt, saltlen, 1, B, p * 128 * r);\n\n\t/* 2: for i = 0 to p - 1 do */\n\tfor (i = 0; i < p; i++) {\n\t\t/* 3: B_i <-- MF(B_i, N) */\n\t\t(smix)(&B[i * 128 * r], r, N, V, XY);\n\t}\n\n\t/* 5: DK <-- PBKDF2(P, B, 1, dkLen) */\n\tPBKDF2_SHA256(passwd, passwdlen, B, p * 128 * r, 1, buf, buflen);\n\n\t/* Free memory. */\n#if defined(MAP_ANON) && defined(HAVE_MMAP)\n\tif (munmap(V0, 128 * r * N))\n\t\tgoto err2;\n#else\n\tfree(V0);\n#endif\n\tfree(XY0);\n\tfree(B0);\n\n\t/* Success! */\n\treturn (0);\n\nerr2:\n\tfree(XY0);\nerr1:\n\tfree(B0);\nerr0:\n\t/* Failure! */\n\treturn (-1);\n}\n\n#define TESTLEN 64\nstatic struct scrypt_test {\n\tconst char * passwd;\n\tconst char * salt;\n\tuint64_t N;\n\tuint32_t r;\n\tuint32_t p;\n\tuint8_t result[TESTLEN];\n} testcase = {\n\t.passwd = \"pleaseletmein\",\n\t.salt = \"SodiumChloride\",\n\t.N = 16,\n\t.r = 8,\n\t.p = 1,\n\t.result = {\n\t\t0x25, 0xa9, 0xfa, 0x20, 0x7f, 0x87, 0xca, 0x09,\n\t\t0xa4, 0xef, 0x8b, 0x9f, 0x77, 0x7a, 0xca, 0x16,\n\t\t0xbe, 0xb7, 0x84, 0xae, 0x18, 0x30, 0xbf, 0xbf,\n\t\t0xd3, 0x83, 0x25, 0xaa, 0xbb, 0x93, 0x77, 0xdf,\n\t\t0x1b, 0xa7, 0x84, 0xd7, 0x46, 0xea, 0x27, 0x3b,\n\t\t0xf5, 0x16, 0xa4, 0x6f, 0xbf, 0xac, 0xf5, 0x11,\n\t\t0xc5, 0xbe, 0xba, 0x4c, 0x4a, 0xb3, 0xac, 0xc7,\n\t\t0xfa, 0x6f, 0x46, 0x0b, 0x6c, 0x0f, 0x47, 0x7b,\n\t}\n};\n\nstatic int\ntestsmix(void (*smix)(uint8_t *, size_t, uint64_t, void *, void *))\n{\n\tuint8_t hbuf[TESTLEN];\n\n\t/* Perform the computation. */\n\tif (_crypto_scrypt(\n\t    (const uint8_t *)testcase.passwd, strlen(testcase.passwd),\n\t    (const uint8_t *)testcase.salt, strlen(testcase.salt),\n\t    testcase.N, testcase.r, testcase.p, hbuf, TESTLEN, smix))\n\t\treturn (-1);\n\n\t/* Does it match? */\n\treturn (memcmp(testcase.result, hbuf, TESTLEN));\n}\n\nstatic void\nselectsmix(void)\n{\n\n#ifdef CPUSUPPORT_X86_SSE2\n\t/* If we're running on an SSE2-capable CPU, try that code. */\n\tif (cpusupport_x86_sse2()) {\n\t\t/* If SSE2ized smix works, use it. */\n\t\tif (!testsmix(crypto_scrypt_smix_sse2)) {\n\t\t\tsmix_func = crypto_scrypt_smix_sse2;\n\t\t\treturn;\n\t\t}\n\t\twarn0(\"Disabling broken SSE2 scrypt support - please report bug!\");\n\t}\n#endif\n\n\t/* If generic smix works, use it. */\n\tif (!testsmix(crypto_scrypt_smix)) {\n\t\tsmix_func = crypto_scrypt_smix;\n\t\treturn;\n\t}\n\twarn0(\"Generic scrypt code is broken - please report bug!\");\n\n\t/* If we get here, something really bad happened. */\n\tabort();\n}\n\n/**\n * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):\n * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,\n * p, buflen) and write the result into buf.  The parameters r, p, and buflen\n * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N\n * must be a power of 2 greater than 1.\n *\n * Return 0 on success; or -1 on error.\n */\nint\ncrypto_scrypt(const uint8_t * passwd, size_t passwdlen,\n    const uint8_t * salt, size_t saltlen, uint64_t N, uint32_t _r, uint32_t _p,\n    uint8_t * buf, size_t buflen)\n{\n\n\tif (smix_func == NULL)\n\t\tselectsmix();\n\n\treturn (_crypto_scrypt(passwd, passwdlen, salt, saltlen, N, _r, _p,\n\t    buf, buflen, smix_func));\n}\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt.h",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#ifndef _CRYPTO_SCRYPT_H_\n#define _CRYPTO_SCRYPT_H_\n\n#include <stdint.h>\n#include <unistd.h>\n\n/**\n * crypto_scrypt(passwd, passwdlen, salt, saltlen, N, r, p, buf, buflen):\n * Compute scrypt(passwd[0 .. passwdlen - 1], salt[0 .. saltlen - 1], N, r,\n * p, buflen) and write the result into buf.  The parameters r, p, and buflen\n * must satisfy r * p < 2^30 and buflen <= (2^32 - 1) * 32.  The parameter N\n * must be a power of 2 greater than 1.\n *\n * Return 0 on success; or -1 on error.\n */\nint crypto_scrypt(const uint8_t *, size_t, const uint8_t *, size_t, uint64_t,\n    uint32_t, uint32_t, uint8_t *, size_t);\n\n#endif /* !_CRYPTO_SCRYPT_H_ */\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt_internal.h",
    "content": ""
  },
  {
    "path": "ext/scrypt/crypto_scrypt_smix.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include <stdint.h>\n#include <string.h>\n\n#include \"sysendian.h\"\n\n#include \"crypto_scrypt_smix.h\"\n\nstatic void blkcpy(void *, const void *, size_t);\nstatic void blkxor(void *, const void *, size_t);\nstatic void salsa20_8(uint32_t[16]);\nstatic void blockmix_salsa8(const uint32_t *, uint32_t *, uint32_t *, size_t);\nstatic uint64_t integerify(const void *, size_t);\n\nstatic void\nblkcpy(void * dest, const void * src, size_t len)\n{\n\tsize_t * D = dest;\n\tconst size_t * S = src;\n\tsize_t L = len / sizeof(size_t);\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] = S[i];\n}\n\nstatic void\nblkxor(void * dest, const void * src, size_t len)\n{\n\tsize_t * D = dest;\n\tconst size_t * S = src;\n\tsize_t L = len / sizeof(size_t);\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] ^= S[i];\n}\n\n/**\n * salsa20_8(B):\n * Apply the salsa20/8 core to the provided block.\n */\nstatic void\nsalsa20_8(uint32_t B[16])\n{\n\tuint32_t x[16];\n\tsize_t i;\n\n\tblkcpy(x, B, 64);\n\tfor (i = 0; i < 8; i += 2) {\n#define R(a,b) (((a) << (b)) | ((a) >> (32 - (b))))\n\t\t/* Operate on columns. */\n\t\tx[ 4] ^= R(x[ 0]+x[12], 7);  x[ 8] ^= R(x[ 4]+x[ 0], 9);\n\t\tx[12] ^= R(x[ 8]+x[ 4],13);  x[ 0] ^= R(x[12]+x[ 8],18);\n\n\t\tx[ 9] ^= R(x[ 5]+x[ 1], 7);  x[13] ^= R(x[ 9]+x[ 5], 9);\n\t\tx[ 1] ^= R(x[13]+x[ 9],13);  x[ 5] ^= R(x[ 1]+x[13],18);\n\n\t\tx[14] ^= R(x[10]+x[ 6], 7);  x[ 2] ^= R(x[14]+x[10], 9);\n\t\tx[ 6] ^= R(x[ 2]+x[14],13);  x[10] ^= R(x[ 6]+x[ 2],18);\n\n\t\tx[ 3] ^= R(x[15]+x[11], 7);  x[ 7] ^= R(x[ 3]+x[15], 9);\n\t\tx[11] ^= R(x[ 7]+x[ 3],13);  x[15] ^= R(x[11]+x[ 7],18);\n\n\t\t/* Operate on rows. */\n\t\tx[ 1] ^= R(x[ 0]+x[ 3], 7);  x[ 2] ^= R(x[ 1]+x[ 0], 9);\n\t\tx[ 3] ^= R(x[ 2]+x[ 1],13);  x[ 0] ^= R(x[ 3]+x[ 2],18);\n\n\t\tx[ 6] ^= R(x[ 5]+x[ 4], 7);  x[ 7] ^= R(x[ 6]+x[ 5], 9);\n\t\tx[ 4] ^= R(x[ 7]+x[ 6],13);  x[ 5] ^= R(x[ 4]+x[ 7],18);\n\n\t\tx[11] ^= R(x[10]+x[ 9], 7);  x[ 8] ^= R(x[11]+x[10], 9);\n\t\tx[ 9] ^= R(x[ 8]+x[11],13);  x[10] ^= R(x[ 9]+x[ 8],18);\n\n\t\tx[12] ^= R(x[15]+x[14], 7);  x[13] ^= R(x[12]+x[15], 9);\n\t\tx[14] ^= R(x[13]+x[12],13);  x[15] ^= R(x[14]+x[13],18);\n#undef R\n\t}\n\tfor (i = 0; i < 16; i++)\n\t\tB[i] += x[i];\n}\n\n/**\n * blockmix_salsa8(Bin, Bout, X, r):\n * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r\n * bytes in length; the output Bout must also be the same size.  The\n * temporary space X must be 64 bytes.\n */\nstatic void\nblockmix_salsa8(const uint32_t * Bin, uint32_t * Bout, uint32_t * X, size_t r)\n{\n\tsize_t i;\n\n\t/* 1: X <-- B_{2r - 1} */\n\tblkcpy(X, &Bin[(2 * r - 1) * 16], 64);\n\n\t/* 2: for i = 0 to 2r - 1 do */\n\tfor (i = 0; i < 2 * r; i += 2) {\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 16], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[i * 8], X, 64);\n\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 16 + 16], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[i * 8 + r * 16], X, 64);\n\t}\n}\n\n/**\n * integerify(B, r):\n * Return the result of parsing B_{2r-1} as a little-endian integer.\n */\nstatic uint64_t\nintegerify(const void * B, size_t r)\n{\n\tconst uint32_t * X = (const void *)((uintptr_t)(B) + (2 * r - 1) * 64);\n\n\treturn (((uint64_t)(X[1]) << 32) + X[0]);\n}\n\n/**\n * crypto_scrypt_smix(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;\n * the temporary storage V must be 128rN bytes in length; the temporary\n * storage XY must be 256r + 64 bytes in length.  The value N must be a\n * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a\n * multiple of 64 bytes.\n */\nvoid\ncrypto_scrypt_smix(uint8_t * B, size_t r, uint64_t N, void * _V, void * XY)\n{\n\tuint32_t * X = XY;\n\tuint32_t * Y = (void *)((uint8_t *)(XY) + 128 * r);\n\tuint32_t * Z = (void *)((uint8_t *)(XY) + 256 * r);\n\tuint32_t * V = _V;\n\tuint64_t i;\n\tuint64_t j;\n\tsize_t k;\n\n\t/* 1: X <-- B */\n\tfor (k = 0; k < 32 * r; k++)\n\t\tX[k] = le32dec(&B[4 * k]);\n\n\t/* 2: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy(&V[i * (32 * r)], X, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy(&V[(i + 1) * (32 * r)], Y, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 6: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(X, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(X, &V[j * (32 * r)], 128 * r);\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(Y, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(Y, &V[j * (32 * r)], 128 * r);\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 10: B' <-- X */\n\tfor (k = 0; k < 32 * r; k++)\n\t\tle32enc(&B[4 * k], X[k]);\n}\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt_smix.h",
    "content": "#ifndef _CRYPTO_SCRYPT_SMIX_H_\n#define _CRYPTO_SCRYPT_SMIX_H_\n\n/**\n * crypto_scrypt_smix(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;\n * the temporary storage V must be 128rN bytes in length; the temporary\n * storage XY must be 256r + 64 bytes in length.  The value N must be a\n * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a\n * multiple of 64 bytes.\n */\nvoid crypto_scrypt_smix(uint8_t *, size_t, uint64_t, void *, void *);\n\n#endif /* !_CRYPTO_SCRYPT_SMIX_H_ */\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt_smix_sse2.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include \"cpusupport.h\"\n#ifdef CPUSUPPORT_X86_SSE2\n\n#include <emmintrin.h>\n#include <stdint.h>\n\n#include \"sysendian.h\"\n\n#include \"crypto_scrypt_smix_sse2.h\"\n\nstatic void blkcpy(void *, const void *, size_t);\nstatic void blkxor(void *, const void *, size_t);\nstatic void salsa20_8(__m128i *);\nstatic void blockmix_salsa8(const __m128i *, __m128i *, __m128i *, size_t);\nstatic uint64_t integerify(const void *, size_t);\n\nstatic void\nblkcpy(void * dest, const void * src, size_t len)\n{\n\t__m128i * D = dest;\n\tconst __m128i * S = src;\n\tsize_t L = len / 16;\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] = S[i];\n}\n\nstatic void\nblkxor(void * dest, const void * src, size_t len)\n{\n\t__m128i * D = dest;\n\tconst __m128i * S = src;\n\tsize_t L = len / 16;\n\tsize_t i;\n\n\tfor (i = 0; i < L; i++)\n\t\tD[i] = _mm_xor_si128(D[i], S[i]);\n}\n\n/**\n * salsa20_8(B):\n * Apply the salsa20/8 core to the provided block.\n */\nstatic void\nsalsa20_8(__m128i B[4])\n{\n\t__m128i X0, X1, X2, X3;\n\t__m128i T;\n\tsize_t i;\n\n\tX0 = B[0];\n\tX1 = B[1];\n\tX2 = B[2];\n\tX3 = B[3];\n\n\tfor (i = 0; i < 8; i += 2) {\n\t\t/* Operate on \"columns\". */\n\t\tT = _mm_add_epi32(X0, X3);\n\t\tX1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 7));\n\t\tX1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 25));\n\t\tT = _mm_add_epi32(X1, X0);\n\t\tX2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));\n\t\tX2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));\n\t\tT = _mm_add_epi32(X2, X1);\n\t\tX3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 13));\n\t\tX3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 19));\n\t\tT = _mm_add_epi32(X3, X2);\n\t\tX0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));\n\t\tX0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));\n\n\t\t/* Rearrange data. */\n\t\tX1 = _mm_shuffle_epi32(X1, 0x93);\n\t\tX2 = _mm_shuffle_epi32(X2, 0x4E);\n\t\tX3 = _mm_shuffle_epi32(X3, 0x39);\n\n\t\t/* Operate on \"rows\". */\n\t\tT = _mm_add_epi32(X0, X1);\n\t\tX3 = _mm_xor_si128(X3, _mm_slli_epi32(T, 7));\n\t\tX3 = _mm_xor_si128(X3, _mm_srli_epi32(T, 25));\n\t\tT = _mm_add_epi32(X3, X0);\n\t\tX2 = _mm_xor_si128(X2, _mm_slli_epi32(T, 9));\n\t\tX2 = _mm_xor_si128(X2, _mm_srli_epi32(T, 23));\n\t\tT = _mm_add_epi32(X2, X3);\n\t\tX1 = _mm_xor_si128(X1, _mm_slli_epi32(T, 13));\n\t\tX1 = _mm_xor_si128(X1, _mm_srli_epi32(T, 19));\n\t\tT = _mm_add_epi32(X1, X2);\n\t\tX0 = _mm_xor_si128(X0, _mm_slli_epi32(T, 18));\n\t\tX0 = _mm_xor_si128(X0, _mm_srli_epi32(T, 14));\n\n\t\t/* Rearrange data. */\n\t\tX1 = _mm_shuffle_epi32(X1, 0x39);\n\t\tX2 = _mm_shuffle_epi32(X2, 0x4E);\n\t\tX3 = _mm_shuffle_epi32(X3, 0x93);\n\t}\n\n\tB[0] = _mm_add_epi32(B[0], X0);\n\tB[1] = _mm_add_epi32(B[1], X1);\n\tB[2] = _mm_add_epi32(B[2], X2);\n\tB[3] = _mm_add_epi32(B[3], X3);\n}\n\n/**\n * blockmix_salsa8(Bin, Bout, X, r):\n * Compute Bout = BlockMix_{salsa20/8, r}(Bin).  The input Bin must be 128r\n * bytes in length; the output Bout must also be the same size.  The\n * temporary space X must be 64 bytes.\n */\nstatic void\nblockmix_salsa8(const __m128i * Bin, __m128i * Bout, __m128i * X, size_t r)\n{\n\tsize_t i;\n\n\t/* 1: X <-- B_{2r - 1} */\n\tblkcpy(X, &Bin[8 * r - 4], 64);\n\n\t/* 2: for i = 0 to 2r - 1 do */\n\tfor (i = 0; i < r; i++) {\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 8], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[i * 4], X, 64);\n\n\t\t/* 3: X <-- H(X \\xor B_i) */\n\t\tblkxor(X, &Bin[i * 8 + 4], 64);\n\t\tsalsa20_8(X);\n\n\t\t/* 4: Y_i <-- X */\n\t\t/* 6: B' <-- (Y_0, Y_2 ... Y_{2r-2}, Y_1, Y_3 ... Y_{2r-1}) */\n\t\tblkcpy(&Bout[(r + i) * 4], X, 64);\n\t}\n}\n\n/**\n * integerify(B, r):\n * Return the result of parsing B_{2r-1} as a little-endian integer.\n * Note that B's layout is permuted compared to the generic implementation.\n */\nstatic uint64_t\nintegerify(const void * B, size_t r)\n{\n\tconst uint32_t * X = (const void *)((uintptr_t)(B) + (2 * r - 1) * 64);\n\n\treturn (((uint64_t)(X[13]) << 32) + X[0]);\n}\n\n/**\n * crypto_scrypt_smix_sse2(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;\n * the temporary storage V must be 128rN bytes in length; the temporary\n * storage XY must be 256r + 64 bytes in length.  The value N must be a\n * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a\n * multiple of 64 bytes.\n *\n * Use SSE2 instructions.\n */\nvoid\ncrypto_scrypt_smix_sse2(uint8_t * B, size_t r, uint64_t N, void * V, void * XY)\n{\n\t__m128i * X = XY;\n\t__m128i * Y = (void *)((uintptr_t)(XY) + 128 * r);\n\t__m128i * Z = (void *)((uintptr_t)(XY) + 256 * r);\n\tuint32_t * X32 = (void *)X;\n\tuint64_t i, j;\n\tsize_t k;\n\n\t/* 1: X <-- B */\n\tfor (k = 0; k < 2 * r; k++) {\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tX32[k * 16 + i] =\n\t\t\t    le32dec(&B[(k * 16 + (i * 5 % 16)) * 4]);\n\t\t}\n\t}\n\n\t/* 2: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy((void *)((uintptr_t)(V) + i * 128 * r), X, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 3: V_i <-- X */\n\t\tblkcpy((void *)((uintptr_t)(V) + (i + 1) * 128 * r),\n\t\t    Y, 128 * r);\n\n\t\t/* 4: X <-- H(X) */\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 6: for i = 0 to N - 1 do */\n\tfor (i = 0; i < N; i += 2) {\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(X, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(X, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);\n\t\tblockmix_salsa8(X, Y, Z, r);\n\n\t\t/* 7: j <-- Integerify(X) mod N */\n\t\tj = integerify(Y, r) & (N - 1);\n\n\t\t/* 8: X <-- H(X \\xor V_j) */\n\t\tblkxor(Y, (void *)((uintptr_t)(V) + j * 128 * r), 128 * r);\n\t\tblockmix_salsa8(Y, X, Z, r);\n\t}\n\n\t/* 10: B' <-- X */\n\tfor (k = 0; k < 2 * r; k++) {\n\t\tfor (i = 0; i < 16; i++) {\n\t\t\tle32enc(&B[(k * 16 + (i * 5 % 16)) * 4],\n\t\t\t    X32[k * 16 + i]);\n\t\t}\n\t}\n}\n\n#endif /* CPUSUPPORT_X86_SSE2 */\n"
  },
  {
    "path": "ext/scrypt/crypto_scrypt_smix_sse2.h",
    "content": "#ifndef _CRYPTO_SCRYPT_SMIX_SSE2_H_\n#define _CRYPTO_SCRYPT_SMIX_SSE2_H_\n\n/**\n * crypto_scrypt_smix_sse2(B, r, N, V, XY):\n * Compute B = SMix_r(B, N).  The input B must be 128r bytes in length;\n * the temporary storage V must be 128rN bytes in length; the temporary\n * storage XY must be 256r + 64 bytes in length.  The value N must be a\n * power of 2 greater than 1.  The arrays B, V, and XY must be aligned to a\n * multiple of 64 bytes.\n *\n * Use SSE2 instructions.\n */\nvoid crypto_scrypt_smix_sse2(uint8_t *, size_t, uint64_t, void *, void *);\n\n#endif /* !_CRYPTO_SCRYPT_SMIX_SSE2_H_ */\n"
  },
  {
    "path": "ext/scrypt/insecure_memzero.c",
    "content": "#include <stddef.h>\n#include <stdint.h>\n\n#include \"insecure_memzero.h\"\n\n/* Function which does the zeroing. */\nstatic void\ninsecure_memzero_func(volatile void * buf, size_t len)\n{\n\tvolatile uint8_t * _buf = buf;\n\tsize_t i;\n\n\tfor (i = 0; i < len; i++)\n\t\t_buf[i] = 0;\n}\n\n/* Pointer to memory-zeroing function. */\nvoid (* volatile insecure_memzero_ptr)(volatile void *, size_t) =\n    insecure_memzero_func;\n"
  },
  {
    "path": "ext/scrypt/insecure_memzero.h",
    "content": "#ifndef _INSECURE_MEMZERO_H_\n#define _INSECURE_MEMZERO_H_\n\n#include <stddef.h>\n\n/* Pointer to memory-zeroing function. */\nextern void (* volatile insecure_memzero_ptr)(volatile void *, size_t);\n\n/**\n * insecure_memzero(buf, len):\n * Attempt to zero ${len} bytes at ${buf} in spite of optimizing compilers'\n * best (standards-compliant) attempts to remove the buffer-zeroing.  In\n * particular, to avoid performing the zeroing, a compiler would need to\n * use optimistic devirtualization; recognize that non-volatile objects do not\n * need to be treated as volatile, even if they are accessed via volatile\n * qualified pointers; and perform link-time optimization; in addition to the\n * dead-code elimination which often causes buffer-zeroing to be elided.\n *\n * Note however that zeroing a buffer does not guarantee that the data held\n * in the buffer is not stored elsewhere; in particular, there may be copies\n * held in CPU registers or in anonymous allocations on the stack, even if\n * every named variable is successfully sanitized.  Solving the \"wipe data\n * from the system\" problem will require a C language extension which does not\n * yet exist.\n *\n * For more information, see:\n * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html\n * http://www.daemonology.net/blog/2014-09-06-zeroing-buffers-is-insufficient.html\n */\nstatic inline void\ninsecure_memzero(volatile void * buf, size_t len)\n{\n\n\t(insecure_memzero_ptr)(buf, len);\n}\n\n#endif /* !_INSECURE_MEMZERO_H_ */\n"
  },
  {
    "path": "ext/scrypt/memlimit.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include \"scrypt_platform.h\"\n\n#include <sys/types.h>\n#ifndef __MINGW32__\n#include <sys/resource.h>\n#endif\n\n#ifdef HAVE_SYS_PARAM_H\n#include <sys/param.h>\n#endif\n#ifdef HAVE_SYSCTL_HW_USERMEM\n#include <sys/sysctl.h>\n#endif\n#ifdef HAVE_SYS_SYSINFO_H\n#include <sys/sysinfo.h>\n#endif\n\n#include <errno.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <unistd.h>\n\n#ifdef DEBUG\n#include <stdio.h>\n#endif\n\n#include \"memlimit.h\"\n\n#ifdef HAVE_SYSCTL_HW_USERMEM\nstatic int\nmemlimit_sysctl_hw_usermem(size_t * memlimit)\n{\n\tint mib[2];\n\tuint8_t usermembuf[8];\n\tsize_t usermemlen = 8;\n\tuint64_t usermem;\n\n\t/* Ask the kernel how much RAM we have. */\n\tmib[0] = CTL_HW;\n\tmib[1] = HW_USERMEM;\n\tif (sysctl(mib, 2, usermembuf, &usermemlen, NULL, 0))\n\t\treturn (1);\n\n\t/*\n\t * Parse as either a uint64_t or a uint32_t based on the length of\n\t * output the kernel reports having copied out.  It appears that all\n\t * systems providing a sysctl interface for reading integers copy\n\t * them out as system-endian values, so we don't need to worry about\n\t * parsing them.\n\t */\n\tif (usermemlen == sizeof(uint64_t))\n\t\tusermem = *(uint64_t *)usermembuf;\n\telse if (usermemlen == sizeof(uint32_t))\n\t\tusermem = *(uint32_t *)usermembuf;\n\telse\n\t\treturn (1);\n\n\t/* Return the sysctl value, but clamp to SIZE_MAX if necessary. */\n#if UINT64_MAX > SIZE_MAX\n\tif (usermem > SIZE_MAX)\n\t\t*memlimit = SIZE_MAX;\n\telse\n\t\t*memlimit = usermem;\n#else\n\t*memlimit = usermem;\n#endif\n\n\t/* Success! */\n\treturn (0);\n}\n#endif\n\n/* If we don't HAVE_STRUCT_SYSINFO, we can't use sysinfo. */\n#ifndef HAVE_STRUCT_SYSINFO\n#undef HAVE_SYSINFO\n#endif\n\n/* If we don't HAVE_STRUCT_SYSINFO_TOTALRAM, we can't use sysinfo. */\n#ifndef HAVE_STRUCT_SYSINFO_TOTALRAM\n#undef HAVE_SYSINFO\n#endif\n\n#ifdef HAVE_SYSINFO\nstatic int\nmemlimit_sysinfo(size_t * memlimit)\n{\n\tstruct sysinfo info;\n\tuint64_t totalmem;\n\n\t/* Get information from the kernel. */\n\tif (sysinfo(&info))\n\t\treturn (1);\n\ttotalmem = info.totalram;\n\n\t/* If we're on a modern kernel, adjust based on mem_unit. */\n#ifdef HAVE_STRUCT_SYSINFO_MEM_UNIT\n\ttotalmem = totalmem * info.mem_unit;\n#endif\n\n\t/* Return the value, but clamp to SIZE_MAX if necessary. */\n#if UINT64_MAX > SIZE_MAX\n\tif (totalmem > SIZE_MAX)\n\t\t*memlimit = SIZE_MAX;\n\telse\n\t\t*memlimit = totalmem;\n#else\n\t*memlimit = totalmem;\n#endif\n\n\t/* Success! */\n\treturn (0);\n}\n#endif /* HAVE_SYSINFO */\n\nstatic int\nmemlimit_rlimit(size_t * memlimit)\n{\n#ifndef __MINGW32__\n\tstruct rlimit rl;\n\tuint64_t memrlimit;\n\n\t/* Find the least of... */\n\tmemrlimit = (uint64_t)(-1);\n\n\t/* ... RLIMIT_AS... */\n#ifdef RLIMIT_AS\n\tif (getrlimit(RLIMIT_AS, &rl))\n\t\treturn (1);\n\tif ((rl.rlim_cur != RLIM_INFINITY) &&\n\t    ((uint64_t)rl.rlim_cur < memrlimit))\n\t\tmemrlimit = rl.rlim_cur;\n#endif\n\n\t/* ... RLIMIT_DATA... */\n\tif (getrlimit(RLIMIT_DATA, &rl))\n\t\treturn (1);\n\tif ((rl.rlim_cur != RLIM_INFINITY) &&\n\t    ((uint64_t)rl.rlim_cur < memrlimit))\n\t\tmemrlimit = rl.rlim_cur;\n\n\t/* ... and RLIMIT_RSS. */\n#ifdef RLIMIT_RSS\n\tif (getrlimit(RLIMIT_RSS, &rl))\n\t\treturn (1);\n\tif ((rl.rlim_cur != RLIM_INFINITY) &&\n\t    ((uint64_t)rl.rlim_cur < memrlimit))\n\t\tmemrlimit = rl.rlim_cur;\n#endif\n\n\t/* Return the value, but clamp to SIZE_MAX if necessary. */\n#if UINT64_MAX > SIZE_MAX\n\tif (memrlimit > SIZE_MAX)\n\t\t*memlimit = SIZE_MAX;\n\telse\n\t\t*memlimit = memrlimit;\n#else\n\t*memlimit = memrlimit;\n#endif\n#else\n\t*memlimit = SIZE_MAX;\n#endif\n\t/* Success! */\n\treturn (0);\n}\n\n#ifdef _SC_PHYS_PAGES\n\n/* Some systems define _SC_PAGESIZE instead of _SC_PAGE_SIZE. */\n#ifndef _SC_PAGE_SIZE\n#define _SC_PAGE_SIZE _SC_PAGESIZE\n#endif\n\nstatic int\nmemlimit_sysconf(size_t * memlimit)\n{\n\tlong pagesize;\n\tlong physpages;\n\tuint64_t totalmem;\n\n\t/* Set errno to 0 in order to distinguish \"no limit\" from \"error\". */\n\terrno = 0;\n\n\t/* Read the two limits. */\n\tif (((pagesize = sysconf(_SC_PAGE_SIZE)) == -1) ||\n\t    ((physpages = sysconf(_SC_PHYS_PAGES)) == -1)) {\n\t\t/* Did an error occur? */\n\t\tif (errno != 0)\n\t\t\treturn (1);\n\n\t\t/* If not, there is no limit. */\n\t\ttotalmem = (uint64_t)(-1);\n\t} else {\n\t\t/* Compute the limit. */\n\t\ttotalmem = (uint64_t)(pagesize) * (uint64_t)(physpages);\n\t}\n\n\t/* Return the value, but clamp to SIZE_MAX if necessary. */\n#if UINT64_MAX > SIZE_MAX\n\tif (totalmem > SIZE_MAX)\n\t\t*memlimit = SIZE_MAX;\n\telse\n\t\t*memlimit = totalmem;\n#else\n\t*memlimit = totalmem;\n#endif\n\n\t/* Success! */\n\treturn (0);\n}\n#endif\n\nint\nmemtouse(size_t maxmem, double maxmemfrac, size_t * memlimit)\n{\n\tsize_t sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit;\n\tsize_t sysconf_memlimit;\n\tsize_t memlimit_min;\n\tsize_t memavail;\n\n\t/* Get memory limits. */\n#ifdef HAVE_SYSCTL_HW_USERMEM\n\tif (memlimit_sysctl_hw_usermem(&sysctl_memlimit))\n\t\treturn (1);\n#else\n\tsysctl_memlimit = (size_t)(-1);\n#endif\n#ifdef HAVE_SYSINFO\n\tif (memlimit_sysinfo(&sysinfo_memlimit))\n\t\treturn (1);\n#else\n\tsysinfo_memlimit = (size_t)(-1);\n#endif\n\tif (memlimit_rlimit(&rlimit_memlimit))\n\t\treturn (1);\n#ifdef _SC_PHYS_PAGES\n\tif (memlimit_sysconf(&sysconf_memlimit))\n\t\treturn (1);\n#else\n\tsysconf_memlimit = (size_t)(-1);\n#endif\n\n#ifdef DEBUG\n\tfprintf(stderr, \"Memory limits are %zu %zu %zu %zu\\n\",\n\t    sysctl_memlimit, sysinfo_memlimit, rlimit_memlimit,\n\t    sysconf_memlimit);\n#endif\n\n\t/* Find the smallest of them. */\n\tmemlimit_min = (size_t)(-1);\n\tif (memlimit_min > sysctl_memlimit)\n\t\tmemlimit_min = sysctl_memlimit;\n\tif (memlimit_min > sysinfo_memlimit)\n\t\tmemlimit_min = sysinfo_memlimit;\n\tif (memlimit_min > rlimit_memlimit)\n\t\tmemlimit_min = rlimit_memlimit;\n\tif (memlimit_min > sysconf_memlimit)\n\t\tmemlimit_min = sysconf_memlimit;\n\n\t/* Only use the specified fraction of the available memory. */\n\tif ((maxmemfrac > 0.5) || (maxmemfrac == 0.0))\n\t\tmaxmemfrac = 0.5;\n\tmemavail = maxmemfrac * memlimit_min;\n\n\t/* Don't use more than the specified maximum. */\n\tif ((maxmem > 0) && (memavail > maxmem))\n\t\tmemavail = maxmem;\n\n\t/* But always allow at least 1 MiB. */\n\tif (memavail < 1048576)\n\t\tmemavail = 1048576;\n\n#ifdef DEBUG\n\tfprintf(stderr, \"Allowing up to %zu memory to be used\\n\", memavail);\n#endif\n\n\t/* Return limit via the provided pointer. */\n\t*memlimit = memavail;\n\treturn (0);\n}\n"
  },
  {
    "path": "ext/scrypt/memlimit.h",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#ifndef _MEMLIMIT_H_\n#define _MEMLIMIT_H_\n\n#include <stddef.h>\n\n/**\n * memtouse(maxmem, maxmemfrac, memlimit):\n * Examine the system and return via memlimit the amount of RAM which should\n * be used -- the specified fraction of the available RAM, but no more than\n * maxmem, and no less than 1MiB.\n */\nint memtouse(size_t, double, size_t *);\n\n#endif /* !_MEMLIMIT_H_ */\n"
  },
  {
    "path": "ext/scrypt/scrypt_calibrate.c",
    "content": "/*\n *  scrypt_calibrate.c\n *  scrypt\n *\n *  Created by Patrick Hogan on 12/15/10.\n *  Copyright 2010 __MyCompanyName__. All rights reserved.\n *\n */\n\n#include \"scrypt_platform.h\"\n\n#include <errno.h>\n#include <fcntl.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <unistd.h>\n\n#include \"memlimit.h\"\n#include \"scryptenc_cpuperf.h\"\n#include \"sysendian.h\"\n\n#include \"scrypt_calibrate.h\"\n\n\nstatic int\npickparams(size_t maxmem, double maxmemfrac, double maxtime, int * logN, uint32_t * r, uint32_t * p)\n{\n\tsize_t memlimit;\n\tdouble opps;\n\tdouble opslimit;\n\tdouble maxN, maxrp;\n\tint rc;\n\n\t/* Figure out how much memory to use. */\n\tif (memtouse(maxmem, maxmemfrac, &memlimit))\n\t\treturn (1);\n\n\t/* Figure out how fast the CPU is. */\n\tif ((rc = scryptenc_cpuperf(&opps)) != 0)\n\t\treturn (rc);\n\topslimit = opps * maxtime;\n\n\t/* Allow a minimum of 2^15 salsa20/8 cores. */\n\tif (opslimit < 32768)\n\t\topslimit = 32768;\n\n\t/* Fix r = 8 for now. */\n\t*r = 8;\n\n\t/*\n\t * The memory limit requires that 128Nr <= memlimit, while the CPU\n\t * limit requires that 4Nrp <= opslimit.  If opslimit < memlimit/32,\n\t * opslimit imposes the stronger limit on N.\n\t */\n#ifdef DEBUG\n\tfprintf(stderr, \"Requiring 128Nr <= %zu, 4Nrp <= %f\\n\",\n\t\t\tmemlimit, opslimit);\n#endif\n\tif (opslimit < memlimit/32) {\n\t\t/* Set p = 1 and choose N based on the CPU limit. */\n\t\t*p = 1;\n\t\tmaxN = opslimit / (*r * 4);\n\t\tfor (*logN = 1; *logN < 63; *logN += 1) {\n\t\t\tif ((uint64_t)(1) << *logN > maxN / 2)\n\t\t\t\tbreak;\n\t\t}\n\t} else {\n\t\t/* Set N based on the memory limit. */\n\t\tmaxN = memlimit / (*r * 128);\n\t\tfor (*logN = 1; *logN < 63; *logN += 1) {\n\t\t\tif ((uint64_t)(1) << *logN > maxN / 2)\n\t\t\t\tbreak;\n\t\t}\n\n\t\t/* Choose p based on the CPU limit. */\n\t\tmaxrp = (opslimit / 4) / ((uint64_t)(1) << *logN);\n\t\tif (maxrp > 0x3fffffff)\n\t\t\tmaxrp = 0x3fffffff;\n\t\t*p = (uint32_t)(maxrp) / *r;\n\t}\n\n#ifdef DEBUG\n\tfprintf(stderr, \"N = %zu r = %d p = %d\\n\",\n\t\t\t(size_t)(1) << *logN, (int)(*r), (int)(*p));\n#endif\n\n\t/* Success! */\n\treturn (0);\n}\n\nint\ncalibrate(size_t maxmem, double maxmemfrac, double maxtime, uint64_t * n, uint32_t * r, uint32_t * p)\n{\n\tint logN = 0;\n\tint result = pickparams( maxmem, maxmemfrac, maxtime, & logN, r, p );\n\tif (result == 0)\n\t{\n\t\t*n = (uint64_t)(1) << logN;\n\t}\n\treturn result;\n}"
  },
  {
    "path": "ext/scrypt/scrypt_calibrate.h",
    "content": "/*\n *  scrypt_calibrate.h\n *  scrypt\n *\n *  Created by Patrick Hogan on 12/15/10.\n *\n */\n\n#ifndef _SCRYPT_CALIBRATE_H_\n#define _SCRYPT_CALIBRATE_H_\n\n#include <stdint.h>\n#include <stdio.h>\n\nint calibrate( size_t maxmem, double maxmemfrac, double maxtime, uint64_t * n, uint32_t * r, uint32_t * p );\n\n#endif\n\n\n"
  },
  {
    "path": "ext/scrypt/scrypt_ext.c",
    "content": "#include \"scrypt_ext.h\"\n#include \"scrypt_calibrate.h\"\n#include \"crypto_scrypt.h\"\n\n\ntypedef struct {\n  uint64_t n;\n  uint32_t r;\n  uint32_t p;\n} Calibration;\n\n\nRBFFI_EXPORT int sc_calibrate(size_t maxmem, double maxmemfrac, double maxtime, Calibration *result)\n{\n    return calibrate(maxmem, maxmemfrac, maxtime, &result->n, &result->r, &result->p);    // 0 == success\n}\n"
  },
  {
    "path": "ext/scrypt/scrypt_ext.h",
    "content": "#ifndef SCRYPT_EXT_H\n#define SCRYPT_EXT_H 1\n\n#ifndef RBFFI_EXPORT\n# ifdef __cplusplus\n#  define RBFFI_EXPORT extern \"C\"\n# else\n#  define RBFFI_EXPORT\n# endif\n#endif\n\n\n#endif /* SCRYPT_EXT_H */\n"
  },
  {
    "path": "ext/scrypt/scrypt_platform.h",
    "content": "#ifndef _SCRYPT_PLATFORM_H_\n#define\t_SCRYPT_PLATFORM_H_\n\n#endif\n"
  },
  {
    "path": "ext/scrypt/scryptenc_cpuperf.c",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#include \"scrypt_platform.h\"\n\n#include <sys/time.h>\n\n#include <stdint.h>\n#include <stdio.h>\n#include <time.h>\n\n#include \"crypto_scrypt.h\"\n\n#include \"scryptenc_cpuperf.h\"\n\n#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)\nstruct timespec {\n\tlong tv_sec;\n\tlong tv_nsec;\n};\n#endif\n\n#ifdef HAVE_CLOCK_GETTIME\n\nstatic clock_t clocktouse;\n\nstatic int\ngetclockres(double * resd)\n{\n\tstruct timespec res;\n\n\t/*\n\t * Try clocks in order of preference until we find one which works.\n\t * (We assume that if clock_getres works, clock_gettime will, too.)\n\t * The use of if/else/if/else/if/else rather than if/elif/elif/else\n\t * is ugly but legal, and allows us to #ifdef things appropriately.\n\t */\n#ifdef CLOCK_VIRTUAL\n\tif (clock_getres(CLOCK_VIRTUAL, &res) == 0)\n\t\tclocktouse = CLOCK_VIRTUAL;\n\telse\n#endif\n#ifdef CLOCK_MONOTONIC\n\tif (clock_getres(CLOCK_MONOTONIC, &res) == 0)\n\t\tclocktouse = CLOCK_MONOTONIC;\n\telse\n#endif\n\tif (clock_getres(CLOCK_REALTIME, &res) == 0)\n\t\tclocktouse = CLOCK_REALTIME;\n\telse\n\t\treturn (-1);\n\n\t/* Convert clock resolution to a double. */\n\t*resd = res.tv_sec + res.tv_nsec * 0.000000001;\n\n\treturn (0);\n}\n\nstatic int\ngetclocktime(struct timespec * ts)\n{\n\n\tif (clock_gettime(clocktouse, ts))\n\t\treturn (-1);\n\n\treturn (0);\n}\n\n#else\nstatic int\ngetclockres(double * resd)\n{\n\n\t*resd = 1.0 / CLOCKS_PER_SEC;\n\n\treturn (0);\n}\n\nstatic int\ngetclocktime(struct timespec * ts)\n{\n\tstruct timeval tv;\n\n\tif (gettimeofday(&tv, NULL))\n\t\treturn (-1);\n\tts->tv_sec = tv.tv_sec;\n\tts->tv_nsec = tv.tv_usec * 1000;\n\n\treturn (0);\n}\n#endif\n\nstatic int\ngetclockdiff(struct timespec * st, double * diffd)\n{\n\tstruct timespec en;\n\n\tif (getclocktime(&en))\n\t\treturn (1);\n\t*diffd = (en.tv_nsec - st->tv_nsec) * 0.000000001 +\n\t\t\t(en.tv_sec - st->tv_sec);\n\n\treturn (0);\n}\n\n/**\n * scryptenc_cpuperf(opps):\n * Estimate the number of salsa20/8 cores which can be executed per second,\n * and return the value via opps.\n */\nint\nscryptenc_cpuperf(double * opps)\n{\n\tstruct timespec st;\n\tdouble resd, diffd;\n\tuint64_t i = 0;\n\n\t/* Get the clock resolution. */\n\tif (getclockres(&resd))\n\t\treturn (2);\n\n#ifdef DEBUG\n\tfprintf(stderr, \"Clock resolution is %f\\n\", resd);\n#endif\n\n\t/* Loop until the clock ticks. */\n\tif (getclocktime(&st))\n\t\treturn (2);\n\tdo {\n\t\t/* Do an scrypt. */\n\t\tif (crypto_scrypt(NULL, 0, NULL, 0, 16, 1, 1, NULL, 0))\n\t\t\treturn (3);\n\n\t\t/* Has the clock ticked? */\n\t\tif (getclockdiff(&st, &diffd))\n\t\t\treturn (2);\n\t\tif (diffd > 0)\n\t\t\tbreak;\n\t} while (1);\n\n\t/* Count how many scrypts we can do before the next tick. */\n\tif (getclocktime(&st))\n\t\treturn (2);\n\tdo {\n\t\t/* Do an scrypt. */\n\t\tif (crypto_scrypt(NULL, 0, NULL, 0, 128, 1, 1, NULL, 0))\n\t\t\treturn (3);\n\n\t\t/* We invoked the salsa20/8 core 512 times. */\n\t\ti += 512;\n\n\t\t/* Check if we have looped for long enough. */\n\t\tif (getclockdiff(&st, &diffd))\n\t\t\treturn (2);\n\t\tif (diffd > resd)\n\t\t\tbreak;\n\t} while (1);\n\n#ifdef DEBUG\n\tfprintf(stderr, \"%ju salsa20/8 cores performed in %f seconds\\n\",\n\t\t\t(uintmax_t)i, diffd);\n#endif\n\n\t/* We can do approximately i salsa20/8 cores per diffd seconds. */\n\t*opps = i / diffd;\n\treturn (0);\n}\n"
  },
  {
    "path": "ext/scrypt/scryptenc_cpuperf.h",
    "content": "/*-\n * Copyright 2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#ifndef _SCRYPTENC_CPUPERF_H_\n#define _SCRYPTENC_CPUPERF_H_\n\n/**\n * scryptenc_cpuperf(opps):\n * Estimate the number of salsa20/8 cores which can be executed per second,\n * and return the value via opps.\n */\nint scryptenc_cpuperf(double *);\n\n#endif /* !_SCRYPTENC_CPUPERF_H_ */\n"
  },
  {
    "path": "ext/scrypt/sha256.c",
    "content": "#include <assert.h>\n#include <stdint.h>\n#include <string.h>\n\n#include \"insecure_memzero.h\"\n#include \"sysendian.h\"\n\n#include \"sha256.h\"\n\n/*\n * Encode a length len/4 vector of (uint32_t) into a length len vector of\n * (uint8_t) in big-endian form.  Assumes len is a multiple of 4.\n */\nstatic void\nbe32enc_vect(uint8_t * dst, const uint32_t * src, size_t len)\n{\n\tsize_t i;\n\n\t/* Sanity-check. */\n\tassert(len % 4 == 0);\n\n\t/* Encode vector, one word at a time. */\n\tfor (i = 0; i < len / 4; i++)\n\t\tbe32enc(dst + i * 4, src[i]);\n}\n\n/*\n * Decode a big-endian length len vector of (uint8_t) into a length\n * len/4 vector of (uint32_t).  Assumes len is a multiple of 4.\n */\nstatic void\nbe32dec_vect(uint32_t * dst, const uint8_t * src, size_t len)\n{\n\tsize_t i;\n\n\t/* Sanity-check. */\n\tassert(len % 4 == 0);\n\n\t/* Decode vector, one word at a time. */\n\tfor (i = 0; i < len / 4; i++)\n\t\tdst[i] = be32dec(src + i * 4);\n}\n\n/* SHA256 round constants. */\nstatic const uint32_t K[64] = {\n\t0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,\n\t0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,\n\t0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,\n\t0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,\n\t0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,\n\t0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,\n\t0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,\n\t0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,\n\t0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,\n\t0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,\n\t0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,\n\t0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,\n\t0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,\n\t0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,\n\t0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,\n\t0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2\n};\n\n/* Elementary functions used by SHA256 */\n#define Ch(x, y, z)\t((x & (y ^ z)) ^ z)\n#define Maj(x, y, z)\t((x & (y | z)) | (y & z))\n#define SHR(x, n)\t(x >> n)\n#define ROTR(x, n)\t((x >> n) | (x << (32 - n)))\n#define S0(x)\t\t(ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))\n#define S1(x)\t\t(ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))\n#define s0(x)\t\t(ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))\n#define s1(x)\t\t(ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))\n\n/* SHA256 round function */\n#define RND(a, b, c, d, e, f, g, h, k)\t\t\t\\\n\th += S1(e) + Ch(e, f, g) + k;\t\t\t\\\n\td += h;\t\t\t\t\t\t\\\n\th += S0(a) + Maj(a, b, c);\n\n/* Adjusted round function for rotating state */\n#define RNDr(S, W, i, ii)\t\t\t\\\n\tRND(S[(64 - i) % 8], S[(65 - i) % 8],\t\\\n\t    S[(66 - i) % 8], S[(67 - i) % 8],\t\\\n\t    S[(68 - i) % 8], S[(69 - i) % 8],\t\\\n\t    S[(70 - i) % 8], S[(71 - i) % 8],\t\\\n\t    W[i + ii] + K[i + ii])\n\n/* Message schedule computation */\n#define MSCH(W, ii, i)\t\t\t\t\\\n\tW[i + ii + 16] = s1(W[i + ii + 14]) + W[i + ii + 9] + s0(W[i + ii + 1]) + W[i + ii]\n\n/*\n * SHA256 block compression function.  The 256-bit state is transformed via\n * the 512-bit input block to produce a new state.\n */\nstatic void\nSHA256_Transform(uint32_t state[static restrict 8],\n    const uint8_t block[static restrict 64],\n    uint32_t W[static restrict 64], uint32_t S[static restrict 8])\n{\n\tint i;\n\n\t/* 1. Prepare the first part of the message schedule W. */\n\tbe32dec_vect(W, block, 64);\n\n\t/* 2. Initialize working variables. */\n\tmemcpy(S, state, 32);\n\n\t/* 3. Mix. */\n\tfor (i = 0; i < 64; i += 16) {\n\t\tRNDr(S, W, 0, i);\n\t\tRNDr(S, W, 1, i);\n\t\tRNDr(S, W, 2, i);\n\t\tRNDr(S, W, 3, i);\n\t\tRNDr(S, W, 4, i);\n\t\tRNDr(S, W, 5, i);\n\t\tRNDr(S, W, 6, i);\n\t\tRNDr(S, W, 7, i);\n\t\tRNDr(S, W, 8, i);\n\t\tRNDr(S, W, 9, i);\n\t\tRNDr(S, W, 10, i);\n\t\tRNDr(S, W, 11, i);\n\t\tRNDr(S, W, 12, i);\n\t\tRNDr(S, W, 13, i);\n\t\tRNDr(S, W, 14, i);\n\t\tRNDr(S, W, 15, i);\n\n\t\tif (i == 48)\n\t\t\tbreak;\n\t\tMSCH(W, 0, i);\n\t\tMSCH(W, 1, i);\n\t\tMSCH(W, 2, i);\n\t\tMSCH(W, 3, i);\n\t\tMSCH(W, 4, i);\n\t\tMSCH(W, 5, i);\n\t\tMSCH(W, 6, i);\n\t\tMSCH(W, 7, i);\n\t\tMSCH(W, 8, i);\n\t\tMSCH(W, 9, i);\n\t\tMSCH(W, 10, i);\n\t\tMSCH(W, 11, i);\n\t\tMSCH(W, 12, i);\n\t\tMSCH(W, 13, i);\n\t\tMSCH(W, 14, i);\n\t\tMSCH(W, 15, i);\n\t}\n\n\t/* 4. Mix local working variables into global state. */\n\tfor (i = 0; i < 8; i++)\n\t\tstate[i] += S[i];\n}\n\nstatic const uint8_t PAD[64] = {\n\t0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\t0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n};\n\n/* Add padding and terminating bit-count. */\nstatic void\nSHA256_Pad(SHA256_CTX * ctx, uint32_t tmp32[static restrict 72])\n{\n\tsize_t r;\n\n\t/* Figure out how many bytes we have buffered. */\n\tr = (ctx->count >> 3) & 0x3f;\n\n\t/* Pad to 56 mod 64, transforming if we finish a block en route. */\n\tif (r < 56) {\n\t\t/* Pad to 56 mod 64. */\n\t\tmemcpy(&ctx->buf[r], PAD, 56 - r);\n\t} else {\n\t\t/* Finish the current block and mix. */\n\t\tmemcpy(&ctx->buf[r], PAD, 64 - r);\n\t\tSHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);\n\n\t\t/* The start of the final block is all zeroes. */\n\t\tmemset(&ctx->buf[0], 0, 56);\n\t}\n\n\t/* Add the terminating bit-count. */\n\tbe64enc(&ctx->buf[56], ctx->count);\n\n\t/* Mix in the final block. */\n\tSHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);\n}\n\n/* Magic initialization constants. */\nstatic const uint32_t initstate[8] = {\n\t0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A,\n\t0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19\n};\n\n/**\n * SHA256_Init(ctx):\n * Initialize the SHA256 context ${ctx}.\n */\nvoid\nSHA256_Init(SHA256_CTX * ctx)\n{\n\n\t/* Zero bits processed so far. */\n\tctx->count = 0;\n\n\t/* Initialize state. */\n\tmemcpy(ctx->state, initstate, sizeof(initstate));\n}\n\n/**\n * SHA256_Update(ctx, in, len):\n * Input ${len} bytes from ${in} into the SHA256 context ${ctx}.\n */\nstatic void\n_SHA256_Update(SHA256_CTX * ctx, const void * in, size_t len,\n    uint32_t tmp32[static restrict 72])\n{\n\tuint32_t r;\n\tconst uint8_t * src = in;\n\n\t/* Return immediately if we have nothing to do. */\n\tif (len == 0)\n\t\treturn;\n\n\t/* Number of bytes left in the buffer from previous updates. */\n\tr = (ctx->count >> 3) & 0x3f;\n\n\t/* Update number of bits. */\n\tctx->count += (uint64_t)(len) << 3;\n\n\t/* Handle the case where we don't need to perform any transforms. */\n\tif (len < 64 - r) {\n\t\tmemcpy(&ctx->buf[r], src, len);\n\t\treturn;\n\t}\n\n\t/* Finish the current block. */\n\tmemcpy(&ctx->buf[r], src, 64 - r);\n\tSHA256_Transform(ctx->state, ctx->buf, &tmp32[0], &tmp32[64]);\n\tsrc += 64 - r;\n\tlen -= 64 - r;\n\n\t/* Perform complete blocks. */\n\twhile (len >= 64) {\n\t\tSHA256_Transform(ctx->state, src, &tmp32[0], &tmp32[64]);\n\t\tsrc += 64;\n\t\tlen -= 64;\n\t}\n\n\t/* Copy left over data into buffer. */\n\tmemcpy(ctx->buf, src, len);\n}\n\n/* Wrapper function for intermediate-values sanitization. */\nvoid\nSHA256_Update(SHA256_CTX * ctx, const void * in, size_t len)\n{\n\tuint32_t tmp32[72];\n\n\t/* Call the real function. */\n\t_SHA256_Update(ctx, in, len, tmp32);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(tmp32, 288);\n}\n\n/**\n * SHA256_Final(digest, ctx):\n * Output the SHA256 hash of the data input to the context ${ctx} into the\n * buffer ${digest}.\n */\nstatic void\n_SHA256_Final(uint8_t digest[32], SHA256_CTX * ctx,\n    uint32_t tmp32[static restrict 72])\n{\n\n\t/* Add padding. */\n\tSHA256_Pad(ctx, tmp32);\n\n\t/* Write the hash. */\n\tbe32enc_vect(digest, ctx->state, 32);\n}\n\n/* Wrapper function for intermediate-values sanitization. */\nvoid\nSHA256_Final(uint8_t digest[32], SHA256_CTX * ctx)\n{\n\tuint32_t tmp32[72];\n\n\t/* Call the real function. */\n\t_SHA256_Final(digest, ctx, tmp32);\n\n\t/* Clear the context state. */\n\tinsecure_memzero(ctx, sizeof(SHA256_CTX));\n\n\t/* Clean the stack. */\n\tinsecure_memzero(tmp32, 288);\n}\n\n/**\n * SHA256_Buf(in, len, digest):\n * Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.\n */\nvoid\nSHA256_Buf(const void * in, size_t len, uint8_t digest[32])\n{\n\tSHA256_CTX ctx;\n\tuint32_t tmp32[72];\n\n\tSHA256_Init(&ctx);\n\t_SHA256_Update(&ctx, in, len, tmp32);\n\t_SHA256_Final(digest, &ctx, tmp32);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(&ctx, sizeof(SHA256_CTX));\n\tinsecure_memzero(tmp32, 288);\n}\n\n/**\n * HMAC_SHA256_Init(ctx, K, Klen):\n * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from\n * ${K}.\n */\nstatic void\n_HMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen,\n    uint32_t tmp32[static restrict 72], uint8_t pad[static restrict 64],\n    uint8_t khash[static restrict 32])\n{\n\tconst uint8_t * K = _K;\n\tsize_t i;\n\n\t/* If Klen > 64, the key is really SHA256(K). */\n\tif (Klen > 64) {\n\t\tSHA256_Init(&ctx->ictx);\n\t\t_SHA256_Update(&ctx->ictx, K, Klen, tmp32);\n\t\t_SHA256_Final(khash, &ctx->ictx, tmp32);\n\t\tK = khash;\n\t\tKlen = 32;\n\t}\n\n\t/* Inner SHA256 operation is SHA256(K xor [block of 0x36] || data). */\n\tSHA256_Init(&ctx->ictx);\n\tmemset(pad, 0x36, 64);\n\tfor (i = 0; i < Klen; i++)\n\t\tpad[i] ^= K[i];\n\t_SHA256_Update(&ctx->ictx, pad, 64, tmp32);\n\n\t/* Outer SHA256 operation is SHA256(K xor [block of 0x5c] || hash). */\n\tSHA256_Init(&ctx->octx);\n\tmemset(pad, 0x5c, 64);\n\tfor (i = 0; i < Klen; i++)\n\t\tpad[i] ^= K[i];\n\t_SHA256_Update(&ctx->octx, pad, 64, tmp32);\n}\n\n/* Wrapper function for intermediate-values sanitization. */\nvoid\nHMAC_SHA256_Init(HMAC_SHA256_CTX * ctx, const void * _K, size_t Klen)\n{\n\tuint32_t tmp32[72];\n\tuint8_t pad[64];\n\tuint8_t khash[32];\n\n\t/* Call the real function. */\n\t_HMAC_SHA256_Init(ctx, _K, Klen, tmp32, pad, khash);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(tmp32, 288);\n\tinsecure_memzero(khash, 32);\n\tinsecure_memzero(pad, 64);\n}\n\n/**\n * HMAC_SHA256_Update(ctx, in, len):\n * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.\n */\nstatic void\n_HMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len,\n    uint32_t tmp32[static restrict 72])\n{\n\n\t/* Feed data to the inner SHA256 operation. */\n\t_SHA256_Update(&ctx->ictx, in, len, tmp32);\n}\n\n/* Wrapper function for intermediate-values sanitization. */\nvoid\nHMAC_SHA256_Update(HMAC_SHA256_CTX * ctx, const void * in, size_t len)\n{\n\tuint32_t tmp32[72];\n\n\t/* Call the real function. */\n\t_HMAC_SHA256_Update(ctx, in, len, tmp32);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(tmp32, 288);\n}\n\n/**\n * HMAC_SHA256_Final(digest, ctx):\n * Output the HMAC-SHA256 of the data input to the context ${ctx} into the\n * buffer ${digest}.\n */\nstatic void\n_HMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx,\n    uint32_t tmp32[static restrict 72], uint8_t ihash[static restrict 32])\n{\n\n\t/* Finish the inner SHA256 operation. */\n\t_SHA256_Final(ihash, &ctx->ictx, tmp32);\n\n\t/* Feed the inner hash to the outer SHA256 operation. */\n\t_SHA256_Update(&ctx->octx, ihash, 32, tmp32);\n\n\t/* Finish the outer SHA256 operation. */\n\t_SHA256_Final(digest, &ctx->octx, tmp32);\n}\n\n/* Wrapper function for intermediate-values sanitization. */\nvoid\nHMAC_SHA256_Final(uint8_t digest[32], HMAC_SHA256_CTX * ctx)\n{\n\tuint32_t tmp32[72];\n\tuint8_t ihash[32];\n\n\t/* Call the real function. */\n\t_HMAC_SHA256_Final(digest, ctx, tmp32, ihash);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(tmp32, 288);\n\tinsecure_memzero(ihash, 32);\n}\n\n/**\n * HMAC_SHA256_Buf(K, Klen, in, len, digest):\n * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of\n * length ${Klen}, and write the result to ${digest}.\n */\nvoid\nHMAC_SHA256_Buf(const void * K, size_t Klen, const void * in, size_t len,\n    uint8_t digest[32])\n{\n\tHMAC_SHA256_CTX ctx;\n\tuint32_t tmp32[72];\n\tuint8_t tmp8[96];\n\n\t_HMAC_SHA256_Init(&ctx, K, Klen, tmp32, &tmp8[0], &tmp8[64]);\n\t_HMAC_SHA256_Update(&ctx, in, len, tmp32);\n\t_HMAC_SHA256_Final(digest, &ctx, tmp32, &tmp8[0]);\n\n\t/* Clean the stack. */\n\tinsecure_memzero(&ctx, sizeof(HMAC_SHA256_CTX));\n\tinsecure_memzero(tmp32, 288);\n\tinsecure_memzero(tmp8, 96);\n}\n\n/**\n * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):\n * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and\n * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1).\n */\nvoid\nPBKDF2_SHA256(const uint8_t * passwd, size_t passwdlen, const uint8_t * salt,\n    size_t saltlen, uint64_t c, uint8_t * buf, size_t dkLen)\n{\n\tHMAC_SHA256_CTX Phctx, PShctx, hctx;\n\tuint32_t tmp32[72];\n\tuint8_t tmp8[96];\n\tsize_t i;\n\tuint8_t ivec[4];\n\tuint8_t U[32];\n\tuint8_t T[32];\n\tuint64_t j;\n\tint k;\n\tsize_t clen;\n\n\t/* Sanity-check. */\n\tassert(dkLen <= 32 * (size_t)(UINT32_MAX));\n\n\t/* Compute HMAC state after processing P. */\n\t_HMAC_SHA256_Init(&Phctx, passwd, passwdlen,\n\t    tmp32, &tmp8[0], &tmp8[64]);\n\n\t/* Compute HMAC state after processing P and S. */\n\tmemcpy(&PShctx, &Phctx, sizeof(HMAC_SHA256_CTX));\n\t_HMAC_SHA256_Update(&PShctx, salt, saltlen, tmp32);\n\n\t/* Iterate through the blocks. */\n\tfor (i = 0; i * 32 < dkLen; i++) {\n\t\t/* Generate INT(i + 1). */\n\t\tbe32enc(ivec, (uint32_t)(i + 1));\n\n\t\t/* Compute U_1 = PRF(P, S || INT(i)). */\n\t\tmemcpy(&hctx, &PShctx, sizeof(HMAC_SHA256_CTX));\n\t\t_HMAC_SHA256_Update(&hctx, ivec, 4, tmp32);\n\t\t_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);\n\n\t\t/* T_i = U_1 ... */\n\t\tmemcpy(T, U, 32);\n\n\t\tfor (j = 2; j <= c; j++) {\n\t\t\t/* Compute U_j. */\n\t\t\tmemcpy(&hctx, &Phctx, sizeof(HMAC_SHA256_CTX));\n\t\t\t_HMAC_SHA256_Update(&hctx, U, 32, tmp32);\n\t\t\t_HMAC_SHA256_Final(U, &hctx, tmp32, tmp8);\n\n\t\t\t/* ... xor U_j ... */\n\t\t\tfor (k = 0; k < 32; k++)\n\t\t\t\tT[k] ^= U[k];\n\t\t}\n\n\t\t/* Copy as many bytes as necessary into buf. */\n\t\tclen = dkLen - i * 32;\n\t\tif (clen > 32)\n\t\t\tclen = 32;\n\t\tmemcpy(&buf[i * 32], T, clen);\n\t}\n\n\t/* Clean the stack. */\n\tinsecure_memzero(&Phctx, sizeof(HMAC_SHA256_CTX));\n\tinsecure_memzero(&PShctx, sizeof(HMAC_SHA256_CTX));\n\tinsecure_memzero(&hctx, sizeof(HMAC_SHA256_CTX));\n\tinsecure_memzero(tmp32, 288);\n\tinsecure_memzero(tmp8, 96);\n\tinsecure_memzero(U, 32);\n\tinsecure_memzero(T, 32);\n}\n"
  },
  {
    "path": "ext/scrypt/sha256.h",
    "content": "#ifndef _SHA256_H_\n#define _SHA256_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n/*\n * Use #defines in order to avoid namespace collisions with anyone else's\n * SHA256 code (e.g., the code in OpenSSL).\n */\n#define SHA256_Init libcperciva_SHA256_Init\n#define SHA256_Update libcperciva_SHA256_Update\n#define SHA256_Final libcperciva_SHA256_Final\n#define SHA256_Buf libcperciva_SHA256_Buf\n#define SHA256_CTX libcperciva_SHA256_CTX\n#define HMAC_SHA256_Init libcperciva_HMAC_SHA256_Init\n#define HMAC_SHA256_Update libcperciva_HMAC_SHA256_Update\n#define HMAC_SHA256_Final libcperciva_HMAC_SHA256_Final\n#define HMAC_SHA256_Buf libcperciva_HMAC_SHA256_Buf\n#define HMAC_SHA256_CTX libcperciva_HMAC_SHA256_CTX\n\n/* Context structure for SHA256 operations. */\ntypedef struct {\n\tuint32_t state[8];\n\tuint64_t count;\n\tuint8_t buf[64];\n} SHA256_CTX;\n\n/**\n * SHA256_Init(ctx):\n * Initialize the SHA256 context ${ctx}.\n */\nvoid SHA256_Init(SHA256_CTX *);\n\n/**\n * SHA256_Update(ctx, in, len):\n * Input ${len} bytes from ${in} into the SHA256 context ${ctx}.\n */\nvoid SHA256_Update(SHA256_CTX *, const void *, size_t);\n\n/**\n * SHA256_Final(digest, ctx):\n * Output the SHA256 hash of the data input to the context ${ctx} into the\n * buffer ${digest}.\n */\nvoid SHA256_Final(uint8_t[32], SHA256_CTX *);\n\n/**\n * SHA256_Buf(in, len, digest):\n * Compute the SHA256 hash of ${len} bytes from $in} and write it to ${digest}.\n */\nvoid SHA256_Buf(const void *, size_t, uint8_t[32]);\n\n/* Context structure for HMAC-SHA256 operations. */\ntypedef struct {\n\tSHA256_CTX ictx;\n\tSHA256_CTX octx;\n} HMAC_SHA256_CTX;\n\n/**\n * HMAC_SHA256_Init(ctx, K, Klen):\n * Initialize the HMAC-SHA256 context ${ctx} with ${Klen} bytes of key from\n * ${K}.\n */\nvoid HMAC_SHA256_Init(HMAC_SHA256_CTX *, const void *, size_t);\n\n/**\n * HMAC_SHA256_Update(ctx, in, len):\n * Input ${len} bytes from ${in} into the HMAC-SHA256 context ${ctx}.\n */\nvoid HMAC_SHA256_Update(HMAC_SHA256_CTX *, const void *, size_t);\n\n/**\n * HMAC_SHA256_Final(digest, ctx):\n * Output the HMAC-SHA256 of the data input to the context ${ctx} into the\n * buffer ${digest}.\n */\nvoid HMAC_SHA256_Final(uint8_t[32], HMAC_SHA256_CTX *);\n\n/**\n * HMAC_SHA256_Buf(K, Klen, in, len, digest):\n * Compute the HMAC-SHA256 of ${len} bytes from ${in} using the key ${K} of\n * length ${Klen}, and write the result to ${digest}.\n */\nvoid HMAC_SHA256_Buf(const void *, size_t, const void *, size_t, uint8_t[32]);\n\n/**\n * PBKDF2_SHA256(passwd, passwdlen, salt, saltlen, c, buf, dkLen):\n * Compute PBKDF2(passwd, salt, c, dkLen) using HMAC-SHA256 as the PRF, and\n * write the output to buf.  The value dkLen must be at most 32 * (2^32 - 1).\n */\nvoid PBKDF2_SHA256(const uint8_t *, size_t, const uint8_t *, size_t,\n    uint64_t, uint8_t *, size_t);\n\n#endif /* !_SHA256_H_ */\n"
  },
  {
    "path": "ext/scrypt/sysendian.h",
    "content": "/*-\n * Copyright 2007-2009 Colin Percival\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * This file was originally written by Colin Percival as part of the Tarsnap\n * online backup system.\n */\n#ifndef _SYSENDIAN_H_\n#define _SYSENDIAN_H_\n\n#include \"scrypt_platform.h\"\n\n/* If we don't have be64enc, the <sys/endian.h> we have isn't usable. */\n#if !HAVE_DECL_BE64ENC\n#undef HAVE_SYS_ENDIAN_H\n#endif\n\n#ifdef HAVE_SYS_ENDIAN_H\n\n#include <sys/endian.h>\n\n#else\n\n#include <stdint.h>\n\nstatic inline uint32_t\nbe32dec(const void *pp)\n{\n\tconst uint8_t *p = (uint8_t const *)pp;\n\n\treturn ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8) +\n\t\t((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));\n}\n\nstatic inline void\nbe32enc(void *pp, uint32_t x)\n{\n\tuint8_t * p = (uint8_t *)pp;\n\n\tp[3] = x & 0xff;\n\tp[2] = (x >> 8) & 0xff;\n\tp[1] = (x >> 16) & 0xff;\n\tp[0] = (x >> 24) & 0xff;\n}\n\nstatic inline uint64_t\nbe64dec(const void *pp)\n{\n\tconst uint8_t *p = (uint8_t const *)pp;\n\n\treturn ((uint64_t)(p[7]) + ((uint64_t)(p[6]) << 8) +\n\t\t((uint64_t)(p[5]) << 16) + ((uint64_t)(p[4]) << 24) +\n\t\t((uint64_t)(p[3]) << 32) + ((uint64_t)(p[2]) << 40) +\n\t\t((uint64_t)(p[1]) << 48) + ((uint64_t)(p[0]) << 56));\n}\n\nstatic inline void\nbe64enc(void *pp, uint64_t x)\n{\n\tuint8_t * p = (uint8_t *)pp;\n\n\tp[7] = x & 0xff;\n\tp[6] = (x >> 8) & 0xff;\n\tp[5] = (x >> 16) & 0xff;\n\tp[4] = (x >> 24) & 0xff;\n\tp[3] = (x >> 32) & 0xff;\n\tp[2] = (x >> 40) & 0xff;\n\tp[1] = (x >> 48) & 0xff;\n\tp[0] = (x >> 56) & 0xff;\n}\n\nstatic inline uint32_t\nle32dec(const void *pp)\n{\n\tconst uint8_t *p = (uint8_t const *)pp;\n\n\treturn ((uint32_t)(p[0]) + ((uint32_t)(p[1]) << 8) +\n\t    ((uint32_t)(p[2]) << 16) + ((uint32_t)(p[3]) << 24));\n}\n\nstatic inline void\nle32enc(void *pp, uint32_t x)\n{\n\tuint8_t * p = (uint8_t *)pp;\n\n\tp[0] = x & 0xff;\n\tp[1] = (x >> 8) & 0xff;\n\tp[2] = (x >> 16) & 0xff;\n\tp[3] = (x >> 24) & 0xff;\n}\n\nstatic inline uint64_t\nle64dec(const void *pp)\n{\n\tconst uint8_t *p = (uint8_t const *)pp;\n\n\treturn ((uint64_t)(p[0]) + ((uint64_t)(p[1]) << 8) +\n\t\t((uint64_t)(p[2]) << 16) + ((uint64_t)(p[3]) << 24) +\n\t\t((uint64_t)(p[4]) << 32) + ((uint64_t)(p[5]) << 40) +\n\t\t((uint64_t)(p[6]) << 48) + ((uint64_t)(p[7]) << 56));\n}\n\nstatic inline void\nle64enc(void *pp, uint64_t x)\n{\n\tuint8_t * p = (uint8_t *)pp;\n\n\tp[0] = x & 0xff;\n\tp[1] = (x >> 8) & 0xff;\n\tp[2] = (x >> 16) & 0xff;\n\tp[3] = (x >> 24) & 0xff;\n\tp[4] = (x >> 32) & 0xff;\n\tp[5] = (x >> 40) & 0xff;\n\tp[6] = (x >> 48) & 0xff;\n\tp[7] = (x >> 56) & 0xff;\n}\n#endif /* !HAVE_SYS_ENDIAN_H */\n\n#endif /* !_SYSENDIAN_H_ */\n"
  },
  {
    "path": "ext/scrypt/warnp.c",
    "content": "#include <errno.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"warnp.h\"\n\nstatic int initialized = 0;\nstatic char * name = NULL;\n\n/* Free the name string. */\nstatic void\ndone(void)\n{\n\n\tfree(name);\n\tname = NULL;\n}\n\n/**\n * warnp_setprogname(progname):\n * Set the program name to be used by warn() and warnx() to ${progname}.\n */\nvoid\nwarnp_setprogname(const char * progname)\n{\n\tconst char * p;\n\n\t/* Free the name if we already have one. */\n\tfree(name);\n\n\t/* Find the last segment of the program name. */\n\tfor (p = progname; progname[0] != '\\0'; progname++)\n\t\tif (progname[0] == '/')\n\t\t\tp = progname + 1;\n\n\t/* Copy the name string. */\n\tname = malloc(strlen(p) + 1);\n\tif (name == NULL) {\n\t\t/* No cleanup handler needs to be registered on failure. */\n\t\treturn;\n\t}\n\tstrncpy(name, p, strlen(p) + 1);\n\tname[strlen(p)] = '\\0';  /* Ensure null termination */\n\n\t/* If we haven't already done so, register our exit handler. */\n\tif (initialized == 0) {\n\t\tatexit(done);\n\t\tinitialized = 1;\n\t}\n}\n\nvoid\nwarn(const char * fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s\", (name != NULL) ? name : \"(unknown)\");\n\tif (fmt != NULL) {\n\t\tfprintf(stderr, \": \");\n\t\tvfprintf(stderr, fmt, ap);\n\t}\n\tfprintf(stderr, \": %s\\n\", strerror(errno));\n\tva_end(ap);\n}\n\nvoid\nwarnx(const char * fmt, ...)\n{\n\tva_list ap;\n\n\tva_start(ap, fmt);\n\tfprintf(stderr, \"%s\", (name != NULL) ? name : \"(unknown)\");\n\tif (fmt != NULL) {\n\t\tfprintf(stderr, \": \");\n\t\tvfprintf(stderr, fmt, ap);\n\t}\n\tfprintf(stderr, \"\\n\");\n\tva_end(ap);\n}\n"
  },
  {
    "path": "ext/scrypt/warnp.h",
    "content": "#ifndef _WARNP_H_\n#define _WARNP_H_\n\n#include <errno.h>\n\n/* Avoid namespace collisions with BSD <err.h>. */\n#define warn libcperciva_warn\n#define warnx libcperciva_warnx\n\n/**\n * warnp_setprogname(progname):\n * Set the program name to be used by warn() and warnx() to ${progname}.\n */\nvoid warnp_setprogname(const char *);\n#define WARNP_INIT\tdo {\t\t\\\n\tif (argv[0] != NULL)\t\t\\\n\t\twarnp_setprogname(argv[0]);\t\\\n} while (0)\n\n/* As in BSD <err.h>. */\nvoid warn(const char *, ...);\nvoid warnx(const char *, ...);\n\n/*\n * If compiled with DEBUG defined, print __FILE__ and __LINE__.\n */\n#ifdef DEBUG\n#define warnline\tdo {\t\t\t\t\\\n\twarnx(\"%s, %d\", __FILE__, __LINE__);\t\\\n} while (0)\n#else\n#define warnline\n#endif\n\n/*\n * Call warn(3) or warnx(3) depending upon whether errno == 0; and clear\n * errno (so that the standard error message isn't repeated later).\n */\n#define\twarnp(...) do {\t\t\t\t\t\\\n\twarnline;\t\t\t\t\t\\\n\tif (errno != 0) {\t\t\t\t\\\n\t\twarn(__VA_ARGS__);\t\t\\\n\t\terrno = 0;\t\t\t\t\\\n\t} else\t\t\t\t\t\t\\\n\t\twarnx(__VA_ARGS__);\t\t\\\n} while (0)\n\n/*\n * Call warnx(3) and set errno == 0.  Unlike warnp, this should be used\n * in cases where we're reporting a problem which we discover ourselves\n * rather than one which is reported to us from a library or the kernel.\n */\n#define warn0(...) do {\t\t\t\t\t\\\n\twarnline;\t\t\t\t\t\\\n\twarnx(__VA_ARGS__);\t\t\t\\\n\terrno = 0;\t\t\t\t\t\\\n} while (0)\n\n#endif /* !_WARNP_H_ */\n"
  },
  {
    "path": "lib/scrypt/engine.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'ffi'\nrequire 'openssl'\n\nmodule SCrypt\n  module Ext\n    # Bind the external functions\n    attach_function :sc_calibrate,\n                    %i[size_t double double pointer],\n                    :int,\n                    blocking: true\n\n    attach_function :crypto_scrypt,\n                    %i[pointer size_t pointer size_t uint64 uint32 uint32 pointer size_t],\n                    :int,\n                    blocking: true # Use blocking: true for CPU-intensive operations to avoid GIL issues\n  end\n\n  class Engine\n    # Regular expressions for validation\n    COST_PATTERN = /^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$$/.freeze\n    SALT_PATTERN = /^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$[A-Za-z0-9]{16,64}$/.freeze\n    HASH_PATTERN = /^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$[A-Za-z0-9]{16,64}\\$[A-Za-z0-9]{32,1024}$/.freeze\n\n    # Constants for salt handling\n    OLD_STYLE_SALT_LENGTH = 40\n    SALT_MIN_LENGTH = 16\n\n    DEFAULTS = {\n      key_len: 32,\n      salt_size: 32,\n      max_mem: 16 * 1024 * 1024,\n      max_memfrac: 0.5,\n      max_time: 0.2,\n      cost: nil\n    }.freeze\n\n    # Class variable to store calibrated cost, separate from defaults\n    @calibrated_cost = nil\n\n    class << self\n      attr_accessor :calibrated_cost\n    end\n\n    class Calibration < FFI::Struct\n      layout  :n, :uint64,\n              :r, :uint32,\n              :p, :uint32\n    end\n\n    class << self\n      def scrypt(secret, salt, *args)\n        case args.length\n        when 2\n          # args is [cost_string, key_len]\n          cost_string, key_len = args\n          cpu_cost, memory_cost, parallelization = parse_cost_string(cost_string)\n          __sc_crypt(secret, salt, cpu_cost, memory_cost, parallelization, key_len)\n        when 4\n          # args is [n, r, p, key_len]\n          cpu_cost, memory_cost, parallelization, key_len = args\n          __sc_crypt(secret, salt, cpu_cost, memory_cost, parallelization, key_len)\n        else\n          raise ArgumentError, 'invalid number of arguments (4 or 6)'\n        end\n      end\n\n      # Given a secret and a valid salt (see SCrypt::Engine.generate_salt) calculates an scrypt password hash.\n      def hash_secret(secret, salt, key_len = DEFAULTS[:key_len])\n        raise Errors::InvalidSecret, 'invalid secret' unless valid_secret?(secret)\n        raise Errors::InvalidSalt, 'invalid salt' unless valid_salt?(salt)\n\n        cost = autodetect_cost(salt)\n        salt_only = extract_salt_from_string(salt)\n\n        if old_style_hash?(salt_only)\n          generate_old_style_hash(secret, salt, cost)\n        else\n          generate_new_style_hash(secret, salt, salt_only, cost, key_len)\n        end\n      end\n\n      # Generates a random salt with a given computational cost.  Uses a saved\n      # cost if SCrypt::Engine.calibrate! has been called.\n      #\n      # Options:\n      # <tt>:cost</tt> is a cost string returned by SCrypt::Engine.calibrate\n      def generate_salt(options = {})\n        options = DEFAULTS.merge(options)\n        cost = options[:cost] || @calibrated_cost || calibrate(options)\n        salt = OpenSSL::Random.random_bytes(options[:salt_size]).unpack('H*').first.rjust(SALT_MIN_LENGTH, '0')\n\n        salt = avoid_old_style_collision(salt)\n        cost + salt\n      end\n\n      # Returns true if +cost+ is a valid cost, false if not.\n      def valid_cost?(cost)\n        !COST_PATTERN.match(cost).nil?\n      end\n\n      # Returns true if +salt+ is a valid salt, false if not.\n      def valid_salt?(salt)\n        !SALT_PATTERN.match(salt).nil?\n      end\n\n      # Returns true if +secret+ is a valid secret, false if not.\n      def valid_secret?(secret)\n        secret.respond_to?(:to_s)\n      end\n\n      # Returns the cost value which will result in computation limits less than the given options.\n      #\n      # Options:\n      # <tt>:max_time</tt> specifies the maximum number of seconds the computation should take.\n      # <tt>:max_mem</tt> specifies the maximum number of bytes the computation should take.\n      # A value of 0 specifies no upper limit. The minimum is always 1 MB.\n      # <tt>:max_memfrac</tt> specifies the maximum memory in a fraction of available resources to use.\n      # Any value equal to 0 or greater than 0.5 will result in 0.5 being used.\n      #\n      # Example:\n      #\n      #   # should take less than 200ms\n      #   SCrypt::Engine.calibrate(:max_time => 0.2)\n      #\n      def calibrate(options = {})\n        options = DEFAULTS.merge(options)\n        '%x$%x$%x$' % __sc_calibrate(options[:max_mem], options[:max_memfrac], options[:max_time])\n      end\n\n      # Calls SCrypt::Engine.calibrate and saves the cost string for future calls to\n      # SCrypt::Engine.generate_salt.\n      def calibrate!(options = {})\n        @calibrated_cost = calibrate(options)\n      end\n\n      # Computes the memory use of the given +cost+\n      def memory_use(cost)\n        cpu_cost, memory_cost, parallelization = parse_cost_string(cost)\n        (128 * memory_cost * parallelization) + (256 * memory_cost) + (128 * memory_cost * cpu_cost)\n      end\n\n      # Autodetects the cost from the salt string.\n      def autodetect_cost(salt)\n        salt[/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$/]\n      end\n\n      private\n\n      # Extracts the salt portion from a salt string\n      def extract_salt_from_string(salt)\n        salt[/\\$([A-Za-z0-9]{16,64})$/, 1]\n      end\n\n      # Checks if this is an old-style hash based on salt length\n      def old_style_hash?(salt_only)\n        salt_only.length == OLD_STYLE_SALT_LENGTH\n      end\n\n      # Generates old-style hash with SHA1\n      def generate_old_style_hash(secret, salt, cost)\n        \"#{salt}$#{Digest::SHA1.hexdigest(scrypt(secret.to_s, salt, cost, 256))}\"\n      end\n\n      # Generates new-style hash\n      def generate_new_style_hash(secret, salt, salt_only, cost, key_len)\n        processed_salt = [salt_only.sub(/^(00)+/, '')].pack('H*')\n        hash_bytes = scrypt(secret.to_s, processed_salt, cost, key_len)\n        \"#{salt}$#{hash_bytes.unpack('H*').first.rjust(key_len * 2, '0')}\"\n      end\n\n      # Avoids collision with old-style hash detection\n      def avoid_old_style_collision(salt)\n        if salt.length == OLD_STYLE_SALT_LENGTH\n          # If salt is 40 characters, the regexp will think that it is an old-style hash, so add a '0'.\n          \"0#{salt}\"\n        else\n          salt\n        end\n      end\n\n      # Parses a cost string into its component values\n      def parse_cost_string(cost_string)\n        cost_string.split('$').map { |component| component.to_i(16) }\n      end\n\n      def __sc_calibrate(max_mem, max_memfrac, max_time)\n        raise ArgumentError, 'max_mem must be non-negative' if max_mem.negative?\n        raise ArgumentError, 'max_memfrac must be between 0 and 1' unless (0..1).cover?(max_memfrac)\n        raise ArgumentError, 'max_time must be positive' if max_time <= 0\n\n        calibration = Calibration.new\n        ret_val = SCrypt::Ext.sc_calibrate(max_mem, max_memfrac, max_time, calibration)\n\n        raise \"calibration error: return value #{ret_val}\" unless ret_val.zero?\n\n        [calibration[:n], calibration[:r], calibration[:p]]\n      end\n\n      def __sc_crypt(secret, salt, cpu_cost, memory_cost, parallelization, key_len)\n        raise ArgumentError, 'secret cannot be nil' if secret.nil?\n        raise ArgumentError, 'salt cannot be nil' if salt.nil?\n        raise ArgumentError, 'key_len must be positive' if key_len <= 0\n        raise ArgumentError, 'cpu_cost must be positive' if cpu_cost <= 0\n        raise ArgumentError, 'memory_cost must be positive' if memory_cost <= 0\n        raise ArgumentError, 'parallelization must be positive' if parallelization <= 0\n\n        result = nil\n\n        FFI::MemoryPointer.new(:char, key_len) do |buffer|\n          ret_val = SCrypt::Ext.crypto_scrypt(\n            secret, secret.bytesize, salt, salt.bytesize,\n            cpu_cost, memory_cost, parallelization,\n            buffer, key_len\n          )\n\n          raise \"scrypt error: return value #{ret_val}\" unless ret_val.zero?\n\n          result = buffer.read_string(key_len)\n        end\n\n        result\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/scrypt/errors.rb",
    "content": "# frozen_string_literal: true\n\nmodule SCrypt\n  module Errors\n    # The salt parameter provided is invalid.\n    class InvalidSalt   < StandardError; end\n\n    # The hash parameter provided is invalid.\n    class InvalidHash   < StandardError; end\n\n    # The secret parameter provided is invalid.\n    class InvalidSecret < StandardError; end\n  end\nend\n"
  },
  {
    "path": "lib/scrypt/password.rb",
    "content": "# frozen_string_literal: true\n\nmodule SCrypt\n  # A password management class which allows you to safely store users' passwords and compare them.\n  #\n  # Example usage:\n  #\n  #   include \"scrypt\"\n  #\n  #   # hash a user's password\n  #   @password = Password.create(\"my grand secret\")\n  #   @password #=> \"2000$8$1$f5f2fa5fe5484a7091f1299768fbe92b5a7fbc77$6a385f22c54d92c314b71a4fd5ef33967c93d679\"\n  #\n  #   # store it safely\n  #   @user.update_attribute(:password, @password)\n  #\n  #   # read it back\n  #   @user.reload!\n  #   @db_password = Password.new(@user.password)\n  #\n  #   # compare it after retrieval\n  #   @db_password == \"my grand secret\" #=> true\n  #   @db_password == \"a paltry guess\"  #=> false\n  #\n  class Password < String\n    # Key length constraints\n    MIN_KEY_LENGTH = 16\n    MAX_KEY_LENGTH = 512\n    # Salt size constraints\n    MIN_SALT_SIZE = 8\n    MAX_SALT_SIZE = 32\n\n    # The hash portion of the stored password hash.\n    attr_reader :digest\n    # The salt of the store password hash\n    attr_reader :salt\n    # The cost factor used to create the hash.\n    attr_reader :cost\n\n    class << self\n      # Hashes a secret, returning a SCrypt::Password instance.\n      # Takes five options (optional), which will determine the salt/key's length and\n      # the cost limits of the computation.\n      # <tt>:key_len</tt> specifies the length in bytes of the key you want to generate.\n      # The default is 32 bytes (256 bits). Minimum is 16 bytes (128 bits). Maximum is 512 bytes (4096 bits).\n      # <tt>:salt_size</tt> specifies the size in bytes of the random salt you want to generate.\n      # The default and minimum is 8 bytes (64 bits). Maximum is 32 bytes (256 bits).\n      # <tt>:max_time</tt> specifies the maximum number of seconds the computation should take.\n      # <tt>:max_mem</tt> specifies the maximum number of bytes the computation should take.\n      # A value of 0 specifies no upper limit. The minimum is always 1 MB.\n      # <tt>:max_memfrac</tt> specifies the maximum memory in a fraction of available resources to use.\n      # Any value equal to 0 or greater than 0.5 will result in 0.5 being used.\n      # The scrypt key derivation function is designed to be far more secure against hardware\n      # brute-force attacks than alternative functions such as PBKDF2 or bcrypt.\n      # The designers of scrypt estimate that on modern (2009) hardware, if 5 seconds are spent\n      # computing a derived key, the cost of a hardware brute-force attack against scrypt is roughly\n      # 4000 times greater than the cost of a similar attack against bcrypt (to find the same password),\n      # and 20000 times greater than a similar attack against PBKDF2.\n      # Default options will result in calculation time of approx. 200 ms with 1 MB memory use.\n      #\n      # Example:\n      #   @password = SCrypt::Password.create(\"my secret\", :max_time => 0.25)\n      #\n      def create(secret, options = {})\n        options = SCrypt::Engine::DEFAULTS.merge(options)\n\n        options[:key_len] = clamp_key_length(options[:key_len])\n        options[:salt_size] = clamp_salt_size(options[:salt_size])\n\n        salt = SCrypt::Engine.generate_salt(options)\n        hash = SCrypt::Engine.hash_secret(secret, salt, options[:key_len])\n\n        Password.new(hash)\n      end\n\n      private\n\n      # Clamps key length to valid range\n      def clamp_key_length(key_len)\n        return MIN_KEY_LENGTH if key_len < MIN_KEY_LENGTH\n        return MAX_KEY_LENGTH if key_len > MAX_KEY_LENGTH\n\n        key_len\n      end\n\n      # Clamps salt size to valid range\n      def clamp_salt_size(salt_size)\n        return MIN_SALT_SIZE if salt_size < MIN_SALT_SIZE\n        return MAX_SALT_SIZE if salt_size > MAX_SALT_SIZE\n\n        salt_size\n      end\n    end\n\n    # Initializes a SCrypt::Password instance with the data from a stored hash.\n    def initialize(raw_hash)\n      raise Errors::InvalidHash, 'invalid hash' unless valid_hash?(raw_hash)\n\n      replace(raw_hash)\n\n      @cost, @salt, @digest = split_hash(to_s)\n    end\n\n    # Compares a potential secret against the hash. Returns true if the secret is the original secret, false otherwise.\n    def ==(other)\n      SecurityUtils.secure_compare(self, SCrypt::Engine.hash_secret(other, @cost + @salt, digest.length / 2))\n    end\n    alias is_password? ==\n\n    private\n\n    # Returns true if +h+ is a valid hash.\n    def valid_hash?(h)\n      !SCrypt::Engine::HASH_PATTERN.match(h).nil?\n    end\n\n    # call-seq:\n    #   split_hash(raw_hash) -> cost, salt, hash\n    #\n    # Splits +h+ into cost, salt, and hash and returns them in that order.\n    def split_hash(hash_string)\n      cpu_cost, version, memory_cost, salt, hash = hash_string.split('$')\n      cost_string = \"#{[cpu_cost, version, memory_cost].join('$')}$\"\n      [cost_string, salt, hash]\n    end\n  end\nend\n"
  },
  {
    "path": "lib/scrypt/scrypt_ext.rb",
    "content": "# frozen_string_literal: true\n\nrequire 'ffi'\nrequire 'ffi-compiler/loader'\n\nmodule SCrypt\n  module Ext\n    extend FFI::Library\n\n    begin\n      ffi_lib FFI::Compiler::Loader.find('scrypt_ext')\n    rescue LoadError => e\n      raise LoadError, \"Failed to load scrypt extension library: #{e.message}\"\n    end\n  end\nend\n"
  },
  {
    "path": "lib/scrypt/security_utils.rb",
    "content": "# frozen_string_literal: true\n\n# NOTE:: a verbatim copy of https://github.com/rails/rails/blob/c8c660002f4b0e9606de96325f20b95248b6ff2d/activesupport/lib/active_support/security_utils.rb\n# Please see the Rails license: https://github.com/rails/rails/blob/master/activesupport/MIT-LICENSE\n\nmodule SCrypt\n  module SecurityUtils\n    # Constant time string comparison.\n    #\n    # The values compared should be of fixed length, such as strings\n    # that have already been processed by HMAC. This should not be used\n    # on variable length plaintext strings because it could leak length info\n    # via timing attacks.\n    def self.secure_compare(a, b)\n      return false unless a.bytesize == b.bytesize\n\n      l = a.unpack \"C#{a.bytesize}\"\n\n      res = 0\n      b.each_byte { |byte| res |= byte ^ l.shift }\n      res.zero?\n    end\n  end\nend\n"
  },
  {
    "path": "lib/scrypt/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule SCrypt\n  VERSION = '3.1.0'\nend\n"
  },
  {
    "path": "lib/scrypt.rb",
    "content": "# frozen_string_literal: true\n\n# A wrapper for the scrypt algorithm.\n\nrequire 'scrypt/errors'\nrequire 'scrypt/scrypt_ext'\nrequire 'scrypt/security_utils'\n\nrequire 'scrypt/engine'\nrequire 'scrypt/password'\n"
  },
  {
    "path": "scrypt.gemspec",
    "content": "# frozen_string_literal: true\n\n$:.push File.expand_path('lib', __dir__)\nrequire 'scrypt/version'\n\nGem::Specification.new do |s|\n  s.name        = 'scrypt'\n  s.version     = SCrypt::VERSION\n  s.authors     = ['Patrick Hogan',\n                   'Stephen von Takach',\n                   'Rene van Paassen',\n                   'Johanns Gregorian']\n  s.email       = ['pbhogan@gmail.com',\n                   'steve@advancedcontrol.com.au',\n                   'rene.vanpaassen@gmail.com',\n                   'io+scrypt@jsg.io']\n  s.cert_chain  = ['certs/pbhogan.pem']\n  s.license     = 'BSD-3-Clause'\n\n  s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem') if $0 =~ /gem\\z/\n  s.metadata['rubygems_mfa_required'] = 'true'\n\n  s.homepage    = 'https://github.com/pbhogan/scrypt'\n  s.summary     = 'scrypt password hashing algorithm.'\n\n  s.description = <<-DESC\n    The scrypt key derivation function is designed to be far\n    more secure against hardware brute-force attacks than\n    alternative functions such as PBKDF2 or bcrypt.\n  DESC\n\n  s.required_ruby_version = '>= 2.3.0'\n\n  s.add_dependency 'ffi-compiler', '>= 1.0', '< 2.0'\n  s.add_dependency 'rake', '~> 13'\n\n  s.extensions = ['ext/scrypt/Rakefile']\n\n  s.files = %w[Rakefile scrypt.gemspec README.md COPYING] + Dir.glob('{lib,spec}/**/*')\n  s.files += Dir.glob('ext/scrypt/*')\n  s.require_paths = ['lib']\nend\n"
  },
  {
    "path": "spec/fixtures/test_vectors.yml",
    "content": "# SCrypt Test Vectors\n# These are the official test vectors from the scrypt specification\n# Used to verify our implementation matches the reference\n\nscrypt_vectors:\n  - description: \"Empty string test\"\n    password: \"\"\n    salt: \"\"\n    n: 16\n    r: 1\n    p: 1\n    key_len: 64\n    expected: \"77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906\"\n\n  - description: \"Standard test vector\"\n    password: \"password\"\n    salt: \"NaCl\"\n    n: 1024\n    r: 8\n    p: 16\n    key_len: 64\n    expected: \"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640\"\n\n  - description: \"High memory test vector\"\n    password: \"pleaseletmein\"\n    salt: \"SodiumChloride\"\n    n: 16384\n    r: 8\n    p: 1\n    key_len: 64\n    expected: \"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887\"\n\n  - description: \"Very high memory test (disabled on memory-constrained systems)\"\n    password: \"pleaseletmein\"\n    salt: \"SodiumChloride\"\n    n: 1048576\n    r: 8\n    p: 1\n    key_len: 64\n    expected: \"2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4\"\n    skip_reason: \"Memory limited systems (like Raspberry Pi) may fail this test\"\n\nhash_secret_vectors:\n  - description: \"Empty string via hash_secret\"\n    password: \"\"\n    salt: \"10$1$1$0000000000000000\"\n    key_len: 64\n    expected_pattern: \"77d6576238657b203b19ca42c18a0497f16b4844e3074ae8dfdffa3fede21442fcd0069ded0948f8326a753a0fc81f17e8d3e0fb2e0d3628cf35e20c38d18906\"\n\n  - description: \"Standard test via hash_secret\"\n    password: \"password\"\n    salt: \"400$8$10$000000004e61436c\"\n    key_len: 64\n    expected_pattern: \"fdbabe1c9d3472007856e7190d01e9fe7c6ad7cbc8237830e77376634b3731622eaf30d92e22a3886ff109279d9830dac727afb94a83ee6d8360cbdfa2cc0640\"\n\n  - description: \"High memory test via hash_secret\"\n    password: \"pleaseletmein\"\n    salt: \"4000$8$1$536f6469756d43686c6f72696465\"\n    key_len: 64\n    expected_pattern: \"7023bdcb3afd7348461c06cd81fd38ebfda8fbba904f8e3ea9b543f6545da1f2d5432955613f0fcf62d49705242a9af9e61e85dc0d651e40dfcf017b45575887\"\n\n  - description: \"Very high memory test via hash_secret (disabled)\"\n    password: \"pleaseletmein\"\n    salt: \"100000$8$1$536f6469756d43686c6f72696465\"\n    key_len: 64\n    expected_pattern: \"2101cb9b6a511aaeaddbbe09cf70f881ec568d574a2ffd4dabe5ee9820adaa478e56fd8f4ba5d09ffa1c6d927c40f4c337304049e8a952fbcbf45c6fa77a41a4\"\n    skip_reason: \"Memory limited systems may fail this test\"\n"
  },
  {
    "path": "spec/scrypt/engine_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))\n\ndescribe 'The SCrypt engine' do\n  it 'calculates a valid cost factor' do\n    first = SCrypt::Engine.calibrate(max_time: 0.2)\n    expect(SCrypt::Engine.valid_cost?(first)).to equal(true)\n  end\nend\n\ndescribe 'Generating SCrypt salts' do\n  it 'produces strings' do\n    expect(SCrypt::Engine.generate_salt).to be_an_instance_of(String)\n  end\n\n  it 'produces random data' do\n    expect(SCrypt::Engine.generate_salt).not_to equal(SCrypt::Engine.generate_salt)\n  end\n\n  it 'uses the saved cost factor' do\n    # Verify cost is different before saving\n    cost = SCrypt::Engine.calibrate(max_time: 0.01)\n    expect(SCrypt::Engine.generate_salt).not_to start_with(cost)\n\n    cost = SCrypt::Engine.calibrate!(max_time: 0.01)\n    expect(SCrypt::Engine.generate_salt).to start_with(cost)\n  end\n\n  it 'resets calibrated cost when setting new calibration' do\n    # Set initial calibration\n    first_cost = SCrypt::Engine.calibrate!(max_time: 0.01)\n    expect(SCrypt::Engine.calibrated_cost).to eq(first_cost)\n\n    # Set different calibration\n    second_cost = SCrypt::Engine.calibrate!(max_time: 0.02)\n    expect(SCrypt::Engine.calibrated_cost).to eq(second_cost)\n    expect(SCrypt::Engine.calibrated_cost).not_to eq(first_cost)\n  end\nend\n\ndescribe 'Autodetecting of salt cost' do\n  it 'works' do\n    expect(SCrypt::Engine.autodetect_cost('2a$08$c3$some_salt')).to eq('2a$08$c3$')\n  end\nend\n\ndescribe 'Generating SCrypt hashes' do\n  class MyInvalidSecret\n    undef to_s\n  end\n\n  before do\n    @salt = SCrypt::Engine.generate_salt\n    @password = 'woo'\n  end\n\n  it 'produces a string' do\n    expect(SCrypt::Engine.hash_secret(@password, @salt)).to be_an_instance_of(String)\n  end\n\n  it 'raises an InvalidSalt error if the salt is invalid' do\n    expect { SCrypt::Engine.hash_secret(@password, 'nino') }.to raise_error(SCrypt::Errors::InvalidSalt)\n  end\n\n  it 'raises an InvalidSecret error if the secret is invalid' do\n    expect { SCrypt::Engine.hash_secret(MyInvalidSecret.new, @salt) }.to raise_error(SCrypt::Errors::InvalidSecret)\n    expect { SCrypt::Engine.hash_secret(nil, @salt) }.not_to raise_error\n    expect { SCrypt::Engine.hash_secret(false, @salt) }.not_to raise_error\n  end\n\n  it 'calls #to_s on the secret and use the return value as the actual secret data' do\n    expect(SCrypt::Engine.hash_secret(false, @salt)).to eq(SCrypt::Engine.hash_secret('false', @salt))\n  end\nend\n\ndescribe 'SCrypt test vectors' do\n  it 'matches results of SCrypt function' do\n    TEST_VECTORS['scrypt_vectors'].each do |vector|\n      next if vector['skip_reason'] # Skip memory-intensive tests\n\n      result = SCrypt::Engine.scrypt(\n        vector['password'],\n        vector['salt'],\n        vector['n'],\n        vector['r'],\n        vector['p'],\n        vector['key_len']\n      ).unpack('H*').first\n\n      expect(result).to eq(vector['expected']), \"Failed for: #{vector['description']}\"\n    end\n  end\n\n  it 'matches equivalent results sent through hash_secret() function' do\n    TEST_VECTORS['hash_secret_vectors'].each do |vector|\n      next if vector['skip_reason'] # Skip memory-intensive tests\n\n      result = SCrypt::Engine.hash_secret(\n        vector['password'],\n        vector['salt'],\n        vector['key_len']\n      )\n\n      # hash_secret returns: salt + '$' + hash_digest\n      # So we expect: \"salt$expected_pattern\"\n      expected_full_hash = \"#{vector['salt']}$#{vector['expected_pattern']}\"\n      expect(result).to eq(expected_full_hash), \"Failed for: #{vector['description']}\"\n    end\n  end\nend\n\ndescribe 'Input validation' do\n  describe '#calibrate' do\n    it 'raises ArgumentError for negative max_mem' do\n      expect do\n        SCrypt::Engine.send(:__sc_calibrate, -1, 0.5, 0.2)\n      end.to raise_error(ArgumentError, 'max_mem must be non-negative')\n    end\n\n    it 'raises ArgumentError for invalid max_memfrac' do\n      expect do\n        SCrypt::Engine.send(:__sc_calibrate, 1024, -0.1,\n                            0.2)\n      end.to raise_error(ArgumentError, 'max_memfrac must be between 0 and 1')\n      expect do\n        SCrypt::Engine.send(:__sc_calibrate, 1024, 1.1,\n                            0.2)\n      end.to raise_error(ArgumentError, 'max_memfrac must be between 0 and 1')\n    end\n\n    it 'raises ArgumentError for non-positive max_time' do\n      expect do\n        SCrypt::Engine.send(:__sc_calibrate, 1024, 0.5, 0)\n      end.to raise_error(ArgumentError, 'max_time must be positive')\n\n      expect do\n        SCrypt::Engine.send(:__sc_calibrate, 1024, 0.5, -0.1)\n      end.to raise_error(ArgumentError, 'max_time must be positive')\n    end\n  end\n\n  describe '#scrypt' do\n    it 'raises ArgumentError for nil secret' do\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, nil, 'salt', 16, 1, 1, 32)\n      end.to raise_error(ArgumentError, 'secret cannot be nil')\n    end\n\n    it 'raises ArgumentError for nil salt' do\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, 'secret', nil, 16, 1, 1, 32)\n      end.to raise_error(ArgumentError, 'salt cannot be nil')\n    end\n\n    it 'raises ArgumentError for non-positive parameters' do\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, 'secret', 'salt', 0, 1, 1, 32)\n      end.to raise_error(ArgumentError, 'cpu_cost must be positive')\n\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, 'secret', 'salt', 16, 0, 1, 32)\n      end.to raise_error(ArgumentError, 'memory_cost must be positive')\n\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, 'secret', 'salt', 16, 1, 0, 32)\n      end.to raise_error(ArgumentError, 'parallelization must be positive')\n\n      expect do\n        SCrypt::Engine.send(:__sc_crypt, 'secret', 'salt', 16, 1, 1,\n                            0)\n      end.to raise_error(ArgumentError, 'key_len must be positive')\n    end\n  end\nend\n\ndescribe 'Memory usage calculation' do\n  it 'calculates memory usage correctly' do\n    cost = '400$8$1$'\n    memory = SCrypt::Engine.memory_use(cost)\n    n = 0x400\n    r = 8\n    p = 1\n    expected = (128 * r * p) + (256 * r) + (128 * r * n)\n    expect(memory).to eq(expected)\n  end\nend\n\ndescribe 'Calibrated cost management' do\n  after do\n    # Reset calibrated cost after each test\n    SCrypt::Engine.calibrated_cost = nil\n  end\n\n  it 'initializes have no calibrated cost' do\n    SCrypt::Engine.calibrated_cost = nil\n    expect(SCrypt::Engine.calibrated_cost).to be_nil\n  end\n\n  it 'stores and retrieve calibrated cost' do\n    cost = SCrypt::Engine.calibrate!(max_time: 0.01)\n    expect(SCrypt::Engine.calibrated_cost).to eq(cost)\n  end\n\n  it 'uses calibrated cost in generate_salt when available' do\n    cost = SCrypt::Engine.calibrate!(max_time: 0.01)\n    salt = SCrypt::Engine.generate_salt\n    expect(salt).to start_with(cost)\n  end\nend\n"
  },
  {
    "path": "spec/scrypt/ffi_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))\n\ndescribe 'SCrypt FFI Library Loading' do\n  describe 'Extension loading' do\n    it 'loads the scrypt extension successfully' do\n      # This test verifies that the FFI library loads without error\n      # If we get here, the library loaded successfully during require\n      expect(SCrypt::Ext).to be_a(Module)\n      expect(SCrypt::Ext).to respond_to(:sc_calibrate)\n      expect(SCrypt::Ext).to respond_to(:crypto_scrypt)\n    end\n\n    it 'has proper FFI function signatures' do\n      # Verify that the FFI functions are properly bound\n      expect(SCrypt::Ext.method(:sc_calibrate)).to be_a(Method)\n      expect(SCrypt::Ext.method(:crypto_scrypt)).to be_a(Method)\n    end\n  end\n\n  describe 'FFI function behavior' do\n    it 'handles basic calibration calls' do\n      # Test that the FFI functions are callable\n      expect { SCrypt::Engine.calibrate(max_time: 0.01) }.not_to raise_error\n    end\n\n    it 'handles basic scrypt calls' do\n      salt = SCrypt::Engine.generate_salt(max_time: 0.01)\n      expect { SCrypt::Engine.hash_secret('test', salt) }.not_to raise_error\n    end\n  end\nend\n"
  },
  {
    "path": "spec/scrypt/integration_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))\n\ndescribe 'SCrypt Integration Tests' do\n  describe 'Full password lifecycle' do\n    let(:secret) { 'my_super_secret_password' }\n    let(:options) { { max_time: 0.1, max_mem: 8 * 1024 * 1024 } }\n\n    it 'create,s store, and verify passwords correctly' do\n      # Create password\n      password = SCrypt::Password.create(secret, options)\n      expect(password).to be_a(SCrypt::Password)\n      expect(password.to_s).to match(/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$[A-Za-z0-9]+\\$[A-Za-z0-9]+$/)\n\n      # Verify password\n      expect(password == secret).to be(true)\n      expect(password == 'wrong_password').to be(false)\n\n      # Re-instantiate from stored hash\n      stored_hash = password.to_s\n      recovered_password = SCrypt::Password.new(stored_hash)\n\n      expect(recovered_password == secret).to be(true)\n      expect(recovered_password == 'wrong_password').to be(false)\n    end\n\n    it 'handles calibration workflow correctly' do\n      # Calibrate for fast testing\n      cost = SCrypt::Engine.calibrate!(max_time: 0.05)\n      expect(cost).to match(/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$$/)\n\n      # Generate salt using calibrated cost\n      salt = SCrypt::Engine.generate_salt\n      expect(salt).to start_with(cost)\n\n      # Hash secret with calibrated parameters\n      hash = SCrypt::Engine.hash_secret(secret, salt)\n      expect(hash).to be_a(String)\n      expect(hash).to include(salt)\n\n      # Verify the hash\n      password = SCrypt::Password.new(hash)\n      expect(password == secret).to be(true)\n\n      # Reset calibration\n      SCrypt::Engine.calibrated_cost = nil\n    end\n  end\n\n  describe 'Cross-compatibility tests' do\n    it 'is compatible between Engine and Password classes' do\n      # Create using Password class\n      password1 = SCrypt::Password.create('test_secret', max_time: 0.05)\n\n      # Extract components and recreate using Engine\n      cost = password1.cost\n      salt_with_cost = cost + password1.salt\n      hash2 = SCrypt::Engine.hash_secret('test_secret', salt_with_cost, password1.digest.length / 2)\n\n      # Both should verify the same secret\n      password2 = SCrypt::Password.new(hash2)\n      expect(password1 == 'test_secret').to be(true)\n      expect(password2 == 'test_secret').to be(true)\n    end\n  end\n\n  describe 'Edge cases and error conditions' do\n    it 'handles various secret types' do\n      # String secret\n      password1 = SCrypt::Password.create('string_secret', max_time: 0.05)\n      expect(password1 == 'string_secret').to be(true)\n\n      # Symbol secret\n      password2 = SCrypt::Password.create(:symbol_secret, max_time: 0.05)\n      expect(password2 == 'symbol_secret').to be(true)\n\n      # Numeric secret\n      password3 = SCrypt::Password.create(12_345, max_time: 0.05)\n      expect(password3 == '12345').to be(true)\n\n      # Boolean secret\n      password4 = SCrypt::Password.create(false, max_time: 0.05)\n      expect(password4 == 'false').to be(true)\n    end\n\n    it 'handles empty and nil secrets safely' do\n      # Empty string\n      password1 = SCrypt::Password.create('', max_time: 0.05)\n      expect(password1 == '').to be(true)\n\n      # Nil (converts to empty string)\n      password2 = SCrypt::Password.create(nil, max_time: 0.05)\n      expect(password2 == '').to be(true)\n    end\n\n    it 'validates input parameters' do\n      # Invalid hash format\n      expect { SCrypt::Password.new('invalid_hash') }.to raise_error(SCrypt::Errors::InvalidHash)\n\n      # Invalid salt\n      expect { SCrypt::Engine.hash_secret('secret', 'invalid_salt') }.to raise_error(SCrypt::Errors::InvalidSalt)\n    end\n  end\n\n  describe 'Performance and memory tests' do\n    it 'respects memory and time constraints' do\n      start_time = Time.now\n\n      # Use very low constraints for fast testing\n      password = SCrypt::Password.create('test', max_time: 0.01, max_mem: 1024 * 1024)\n\n      elapsed_time = Time.now - start_time\n\n      # Should complete reasonably quickly (allowing some overhead)\n      expect(elapsed_time).to be < 1.0\n      expect(password == 'test').to be(true)\n    end\n\n    it 'calculates memory usage correctly' do\n      cost = SCrypt::Engine.calibrate(max_time: 0.05)\n      memory_usage = SCrypt::Engine.memory_use(cost)\n\n      # Memory usage should be a reasonable number\n      expect(memory_usage).to be > 0\n      expect(memory_usage).to be < 100 * 1024 * 1024 # Less than 100MB\n    end\n  end\nend\n"
  },
  {
    "path": "spec/scrypt/password_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))\n\ndescribe 'Creating a hashed password' do\n  before do\n    @password = SCrypt::Password.create('s3cr3t', max_time: 0.25)\n  end\n\n  it 'returns a SCrypt::Password' do\n    expect(@password).to be_an_instance_of(SCrypt::Password)\n  end\n\n  it 'returns a valid password' do\n    expect { SCrypt::Password.new(@password) }.not_to raise_error\n  end\n\n  it 'behaves normally if the secret is not a string' do\n    expect { SCrypt::Password.create(nil) }.not_to raise_error\n    expect { SCrypt::Password.create(false) }.not_to raise_error\n    expect { SCrypt::Password.create(42) }.not_to raise_error\n  end\n\n  it 'tolerates empty string secrets' do\n    expect { SCrypt::Password.create('') }.not_to raise_error\n    expect { SCrypt::Password.create('', max_time: 0.01) }.not_to raise_error\n    expect(SCrypt::Password.create('')).to be_an_instance_of(SCrypt::Password)\n  end\nend\n\ndescribe 'Reading a hashed password' do\n  before do\n    @secret = 'my secret'\n    @hash = '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07'\n  end\n\n  it 'reads the cost, salt, and hash' do\n    password = SCrypt::Password.new(@hash)\n    expect(password.cost).to eq('400$8$d$')\n    expect(password.salt).to eq('173a8189751c095a29b933789560b73bf17b2e01')\n    expect(password.digest).to eq('9bf66d74bd6f3ebcf99da3b379b689b89db1cb07')\n  end\n\n  it 'raises an InvalidHashError when given an invalid hash' do\n    expect { SCrypt::Password.new('invalid') }.to raise_error(SCrypt::Errors::InvalidHash)\n  end\nend\n\ndescribe 'Comparing a hashed password with a secret' do\n  before do\n    @secret = 's3cr3t'\n    @password = SCrypt::Password.create(@secret, max_time: 0.01)\n  end\n\n  it 'compares successfully to the original secret' do\n    expect(@password == @secret).to be true\n  end\n\n  it 'compares unsuccessfully to anything besides original secret' do\n    expect(@password == 'different').to be false\n  end\nend\n\ndescribe 'non-default salt sizes' do\n  before do\n    @secret = 's3cret'\n  end\n\n  it 'enforces a minimum salt of 8 bytes' do\n    @password = SCrypt::Password.create(@secret, salt_size: 4, max_time: 0.01)\n    expect(@password.salt.length).to eq(16) # 8 bytes * 2 (hex encoding)\n  end\n\n  it 'allows a salt of 32 bytes' do\n    @password = SCrypt::Password.create(@secret, salt_size: 32, max_time: 0.01)\n    expect(@password.salt.length).to eq(64) # 32 bytes * 2 (hex encoding)\n  end\n\n  it 'enforces a maximum salt of 32 bytes' do\n    @password = SCrypt::Password.create(@secret, salt_size: 64, max_time: 0.01)\n    expect(@password.salt.length).to eq(64) # 32 bytes * 2 (hex encoding)\n  end\n\n  it 'pads a 20-byte salt to not look like a 20-byte SHA1' do\n    @password = SCrypt::Password.create(@secret, salt_size: 20)\n    expect(@password.salt.length).to eq(41)\n  end\n\n  it 'properly compares a non-standard salt hash' do\n    @password = SCrypt::Password.create(@secret, salt_size: 16, max_time: 0.01)\n    expect(@password == @secret).to be true\n  end\nend\n\ndescribe 'non-default key lengths' do\n  before do\n    @secret = 's3cret'\n  end\n\n  it 'enforces a minimum keylength of 16 bytes' do\n    @password = SCrypt::Password.create(@secret, key_len: 8, max_time: 0.01)\n    expect(@password.digest.length).to eq(32) # 16 bytes * 2 (hex encoding)\n  end\n\n  it 'allows a keylength of 512 bytes' do\n    @password = SCrypt::Password.create(@secret, key_len: 512, max_time: 0.01)\n    expect(@password.digest.length).to eq(1024) # 512 bytes * 2 (hex encoding)\n  end\n\n  it 'enforces a maximum keylength of 512 bytes' do\n    @password = SCrypt::Password.create(@secret, key_len: 1024, max_time: 0.01)\n    expect(@password.digest.length).to eq(1024) # 512 bytes * 2 (hex encoding)\n  end\n\n  it 'properly compares a non-standard hash' do\n    @password = SCrypt::Password.create(@secret, key_len: 64, max_time: 0.01)\n    expect(@password == @secret).to be true\n  end\nend\n\ndescribe 'Old-style hashes' do\n  before do\n    @secret = 'my secret'\n    @hash = '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07'\n  end\n\n  it 'compares successfully' do\n    expect(SCrypt::Password.new(@hash) == @secret).to be true\n  end\nend\n\ndescribe 'Respecting standard ruby behaviors' do\n  it 'hashes as an integer' do\n    password = SCrypt::Password.create('secret', max_time: 0.01)\n    expect(password.hash).to be_an(Integer)\n  end\nend\n\ndescribe 'Password validation and parsing' do\n  it 'correctly parses hash components' do\n    password = SCrypt::Password.new('400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07')\n\n    expect(password.cost).to eq('400$8$d$')\n    expect(password.salt).to eq('173a8189751c095a29b933789560b73bf17b2e01')\n    expect(password.digest).to eq('9bf66d74bd6f3ebcf99da3b379b689b89db1cb07')\n  end\n\n  it 'validates hash format strictly' do\n    valid_hash = '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$9bf66d74bd6f3ebcf99da3b379b689b89db1cb07'\n\n    expect { SCrypt::Password.new(valid_hash) }.not_to raise_error\n    expect { SCrypt::Password.new('invalid') }.to raise_error(SCrypt::Errors::InvalidHash)\n    expect { SCrypt::Password.new('') }.to raise_error(SCrypt::Errors::InvalidHash)\n    expect { SCrypt::Password.new('400$8$d$') }.to raise_error(SCrypt::Errors::InvalidHash)\n  end\n\n  it 'handles alias method correctly' do\n    password = SCrypt::Password.create('secret', max_time: 0.01)\n\n    expect(password.is_password?('secret')).to be true\n    expect(password.is_password?('wrong')).to be false\n  end\nend\n\ndescribe 'Parameter boundary testing' do\n  it 'enforces minimum and maximum key lengths correctly' do\n    # Test minimum key length (should be clamped to 16)\n    password_min = SCrypt::Password.create('secret', key_len: 8, max_time: 0.01)\n    expect(password_min.digest.length).to eq(32) # 16 bytes * 2 (hex encoding)\n\n    # Test maximum key length (should be clamped to 512)\n    password_max = SCrypt::Password.create('secret', key_len: 1024, max_time: 0.01)\n    expect(password_max.digest.length).to eq(1024) # 512 bytes * 2 (hex encoding)\n  end\n\n  it 'enforces minimum and maximum salt sizes correctly' do\n    # Test minimum salt size (should be clamped to 8)\n    password_min = SCrypt::Password.create('secret', salt_size: 4, max_time: 0.01)\n    expect(password_min.salt.length).to eq(16) # 8 bytes * 2 (hex encoding)\n\n    # Test maximum salt size (should be clamped to 32)\n    password_max = SCrypt::Password.create('secret', salt_size: 64, max_time: 0.01)\n    expect(password_max.salt.length).to eq(64) # 32 bytes * 2 (hex encoding)\n  end\nend\n"
  },
  {
    "path": "spec/scrypt/utils_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))\n\ndescribe 'Security Utils' do\n  describe '.secure_compare' do\n    it 'performs a string comparison correctly' do\n      expect(SCrypt::SecurityUtils.secure_compare('a', 'a')).to equal(true)\n      expect(SCrypt::SecurityUtils.secure_compare('a', 'b')).to equal(false)\n      expect(SCrypt::SecurityUtils.secure_compare('aa', 'aa')).to equal(true)\n      expect(SCrypt::SecurityUtils.secure_compare('aa', 'ab')).to equal(false)\n    end\n\n    it 'returns false for different length strings' do\n      expect(SCrypt::SecurityUtils.secure_compare('aa', 'aaa')).to equal(false)\n      expect(SCrypt::SecurityUtils.secure_compare('aaa', 'aa')).to equal(false)\n      expect(SCrypt::SecurityUtils.secure_compare('', 'a')).to equal(false)\n      expect(SCrypt::SecurityUtils.secure_compare('a', '')).to equal(false)\n    end\n\n    it 'handles empty strings correctly' do\n      expect(SCrypt::SecurityUtils.secure_compare('', '')).to equal(true)\n    end\n\n    it 'handles binary data correctly' do\n      binary1 = \"\\x00\\x01\\x02\\x03\"\n      binary2 = \"\\x00\\x01\\x02\\x03\"\n      binary3 = \"\\x00\\x01\\x02\\x04\"\n\n      expect(SCrypt::SecurityUtils.secure_compare(binary1, binary2)).to equal(true)\n      expect(SCrypt::SecurityUtils.secure_compare(binary1, binary3)).to equal(false)\n    end\n\n    it 'handles unicode strings correctly' do\n      unicode1 = 'héllo'\n      unicode2 = 'héllo'\n      unicode3 = 'hello'\n\n      expect(SCrypt::SecurityUtils.secure_compare(unicode1, unicode2)).to equal(true)\n      expect(SCrypt::SecurityUtils.secure_compare(unicode1, unicode3)).to equal(false)\n    end\n\n    it 'is resistant to timing attacks' do\n      # This test ensures the function takes constant time regardless of where differences occur\n      long_string1 = ('a' * 1000) + 'x'\n      long_string2 = ('a' * 1000) + 'y'\n      long_string3 = 'x' + ('a' * 1000)\n      long_string4 = 'y' + ('a' * 1000)\n\n      # All of these should return false and take similar time\n      expect(SCrypt::SecurityUtils.secure_compare(long_string1, long_string2)).to equal(false)\n      expect(SCrypt::SecurityUtils.secure_compare(long_string3, long_string4)).to equal(false)\n    end\n  end\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "# frozen_string_literal: true\n\n$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))\n\nrequire 'rubygems'\nrequire 'rspec'\nrequire 'yaml'\nrequire 'scrypt'\n\n# Load shared examples\nDir[File.expand_path('support/**/*.rb', __dir__)].each { |f| require f }\n\n# Load test fixtures\nTEST_VECTORS = YAML.load_file(File.expand_path('fixtures/test_vectors.yml', __dir__)).freeze\n\nRSpec.configure do |config|\n  # Use documentation format for better output\n  config.default_formatter = 'doc' if config.files_to_run.one?\n\n  # Run specs in random order to surface order dependencies\n  config.order = :random\n\n  # Seed global randomization in this process using the `--seed` CLI option\n  Kernel.srand config.seed\n\n  # Allow more verbose output when running a single file\n  config.filter_run_when_matching :focus\n\n  # Enable expect syntax (recommended)\n  config.expect_with :rspec do |expectations|\n    expectations.include_chain_clauses_in_custom_matcher_descriptions = true\n    # Disable deprecated should syntax\n    expectations.syntax = :expect\n  end\n\n  # Configure mocks\n  config.mock_with :rspec do |mocks|\n    mocks.verify_partial_doubles = true\n  end\n\n  # Enable shared context metadata behavior\n  config.shared_context_metadata_behavior = :apply_to_host_groups\n\n  # Configure warnings and deprecations\n  config.warnings = true\n  config.raise_errors_for_deprecations!\nend\n"
  },
  {
    "path": "spec/support/shared_examples.rb",
    "content": "# frozen_string_literal: true\n\n# Shared examples for SCrypt tests\nRSpec.shared_examples 'a valid scrypt hash' do\n  it 'has the correct format' do\n    expect(subject).to match(/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$[A-Za-z0-9]+\\$[A-Za-z0-9]+$/)\n  end\n\n  it 'is a string' do\n    expect(subject).to be_a(String)\n  end\nend\n\nRSpec.shared_examples 'a valid cost string' do\n  it 'has the correct format' do\n    expect(subject).to match(/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$$/)\n  end\n\n  it 'is valid according to Engine.valid_cost?' do\n    expect(SCrypt::Engine.valid_cost?(subject)).to be(true)\n  end\nend\n\nRSpec.shared_examples 'a valid salt string' do\n  it 'has the correct format' do\n    expect(subject).to match(/^[0-9a-z]+\\$[0-9a-z]+\\$[0-9a-z]+\\$[A-Za-z0-9]{16,64}$/)\n  end\n\n  it 'is valid according to Engine.valid_salt?' do\n    expect(SCrypt::Engine.valid_salt?(subject)).to be(true)\n  end\nend\n\nRSpec.shared_examples 'proper input validation' do |method, args, error_class, error_message|\n  it \"raises #{error_class} for invalid input\" do\n    expect { subject.send(method, *args) }.to raise_error(error_class, error_message)\n  end\nend\n\nRSpec.shared_examples 'deterministic output' do |method, args|\n  it 'produces the same output for the same input' do\n    result1 = subject.send(method, *args)\n    result2 = subject.send(method, *args)\n    expect(result1).to eq(result2)\n  end\nend\n"
  },
  {
    "path": "spec/support/test_helpers.rb",
    "content": "# frozen_string_literal: true\n\nmodule TestHelpers\n  # Common test data\n  VALID_SECRETS = [\n    'simple_password',\n    'complex_password_123!@#',\n    '',\n    'unicode_tésting',\n    '🔒secure🔑'\n  ].freeze\n\n  INVALID_HASH_FORMATS = [\n    '',\n    'invalid',\n    '400$8$d$invalid',\n    '400$8$d$173a8189751c095a29b933789560b73bf17b2e01',\n    '400$8$d$173a8189751c095a29b933789560b73bf17b2e01$'\n  ].freeze\n\n  INVALID_SALT_FORMATS = [\n    '',\n    'invalid',\n    'nino',\n    '400$8$d$'\n  ].freeze\n\n  # Helper methods\n  def self.generate_test_password(secret = 'test_secret', options = {})\n    default_options = { max_time: 0.05 }\n    SCrypt::Password.create(secret, default_options.merge(options))\n  end\n\n  def self.generate_test_salt(options = {})\n    default_options = { max_time: 0.05 }\n    SCrypt::Engine.generate_salt(default_options.merge(options))\n  end\n\n  def self.reset_calibration\n    SCrypt::Engine.calibrated_cost = nil\n  end\nend\n\n# Include helper methods in RSpec\nRSpec.configure do |config|\n  config.include TestHelpers\nend\n"
  }
]