diff --git a/.gitignore b/.gitignore
index 9f2a42a..5b12b31 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,24 +1,234 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/c,clion,visualstudiocode,ruby
+# Edit at https://www.toptal.com/developers/gitignore?templates=c,clion,visualstudiocode,ruby
+
+### C ###
+# Prerequisites
+*.d
+
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Linker output
+*.ilk
+*.map
+*.exp
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# Debug files
+*.dSYM/
+*.su
+*.idb
+*.pdb
+
+# Kernel Module Compile Results
+*.mod*
+*.cmd
+.tmp_versions/
+modules.order
+Module.symvers
+Mkfile.old
+dkms.conf
+
+### CLion ###
+# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/**/workspace.xml
+.idea/**/tasks.xml
+.idea/**/usage.statistics.xml
+.idea/**/dictionaries
+.idea/**/shelf
+
+# Generated files
+.idea/**/contentModel.xml
+
+# Sensitive or high-churn files
+.idea/**/dataSources/
+.idea/**/dataSources.ids
+.idea/**/dataSources.local.xml
+.idea/**/sqlDataSources.xml
+.idea/**/dynamic.xml
+.idea/**/uiDesigner.xml
+.idea/**/dbnavigator.xml
+
+# Gradle
+.idea/**/gradle.xml
+.idea/**/libraries
+
+# Gradle and Maven with auto-import
+# When using Gradle or Maven with auto-import, you should exclude module files,
+# since they will be recreated, and may cause churn.  Uncomment if using
+# auto-import.
+# .idea/artifacts
+# .idea/compiler.xml
+# .idea/jarRepositories.xml
+# .idea/modules.xml
+# .idea/*.iml
+# .idea/modules
+# *.iml
+# *.ipr
+
+# CMake
+cmake-build-*/
+
+# Mongo Explorer plugin
+.idea/**/mongoSettings.xml
+
+# File-based project format
+*.iws
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Cursive Clojure plugin
+.idea/replstate.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties
+fabric.properties
+
+# Editor-based Rest Client
+.idea/httpRequests
+
+# Android studio 3.1+ serialized cache file
+.idea/caches/build_file_checksums.ser
+
+### CLion Patch ###
+# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
+
+# *.iml
+# modules.xml
+# .idea/misc.xml
+# *.ipr
+
+# Sonarlint plugin
+# https://plugins.jetbrains.com/plugin/7973-sonarlint
+.idea/**/sonarlint/
+
+# SonarQube Plugin
+# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
+.idea/**/sonarIssues.xml
+
+# Markdown Navigator plugin
+# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
+.idea/**/markdown-navigator.xml
+.idea/**/markdown-navigator-enh.xml
+.idea/**/markdown-navigator/
+
+# Cache file creation bug
+# See https://youtrack.jetbrains.com/issue/JBR-2257
+.idea/$CACHE_FILE$
+
+# CodeStream plugin
+# https://plugins.jetbrains.com/plugin/12206-codestream
+.idea/codestream.xml
+
+### Ruby ###
 *.gem
 *.rbc
-*.rbx
-*.bundle
-*.so
-*.dll
-.config
-coverage
-InstalledFiles
-lib/bundler/man
-pkg
-rdoc
-spec/reports
-test/tmp
-test/version_tmp
-tmp
-
-# YARD artifacts
-.yardoc
-_yardoc
-doc/
-Gemfile.lock
-
-.idea/
+/.config
+/coverage/
+/InstalledFiles
+/pkg/
+/spec/reports/
+/spec/examples.txt
+/test/tmp/
+/test/version_tmp/
+/tmp/
+
+# Used by dotenv library to load environment variables.
+# .env
+
+# Ignore Byebug command history file.
+.byebug_history
+
+## Specific to RubyMotion:
+.dat*
+.repl_history
+build/
+*.bridgesupport
+build-iPhoneOS/
+build-iPhoneSimulator/
+
+## Specific to RubyMotion (use of CocoaPods):
+#
+# We recommend against adding the Pods directory to your .gitignore. However
+# you should judge for yourself, the pros and cons are mentioned at:
+# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
+# vendor/Pods/
+
+## Documentation cache and generated files:
+/.yardoc/
+/_yardoc/
+/doc/
+/rdoc/
+
+## Environment normalization:
+/.bundle/
+/vendor/bundle
+/lib/bundler/man/
+
+# for a library or gem, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# Gemfile.lock
+# .ruby-version
+# .ruby-gemset
+
+# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
+.rvmrc
+
+# Used by RuboCop. Remote config files pulled in from inherit_from directive.
+# .rubocop-https?--*
+
+### Ruby Patch ###
+# Used by RuboCop. Remote config files pulled in from inherit_from directive.
+# .rubocop-https?--*
+
+### VisualStudioCode ###
+.vscode/*
+!.vscode/tasks.json
+!.vscode/launch.json
+*.code-workspace
+
+### VisualStudioCode Patch ###
+# Ignore all local history of files
+.history
+.ionide
+
+# End of https://www.toptal.com/developers/gitignore/api/c,clion,visualstudiocode,ruby
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
index 62556f7..1245bde 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,23 +1,24 @@
-language: ruby
-rvm:
-  - ruby-head
-  - 2.1.0
-  - 2.0.0
-  - 1.9.3
-  - 1.9.2
-  - 1.8.7
-  - rbx-2
-
-gemfile: Gemfile.ci
+arch:
+  - amd64
+  - arm64 
 
 branches:
   only:
     - master
+    - develop
+
+gemfile: Gemfile.ci
+
+language: ruby
 
 os:
   - linux
-  - osx
 
-matrix:
-  allow_failures:
-    - os: osx
+rvm:
+  - ruby-head
+  - 2.7
+  - 2.6
+  - 2.5
+  - 2.4
+  - 2.3
+  - 2.2
diff --git a/Gemfile b/Gemfile
index c80ee36..d65e2a6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,3 +1,3 @@
-source "http://rubygems.org"
+source 'http://rubygems.org'
 
 gemspec
diff --git a/Gemfile.ci b/Gemfile.ci
index e581534..ada0104 100644
--- a/Gemfile.ci
+++ b/Gemfile.ci
@@ -1,14 +1,8 @@
-source "http://rubygems.org"
+source 'http://rubygems.org'
 
 gemspec
 
-gem 'rubygems-tasks'
 gem 'rake'
-gem 'rspec', '~> 3.3'
+gem 'rspec'
+gem 'rubygems-tasks'
 gem 'yard'
-
-platforms :rbx do
-  gem 'racc'
-  gem 'rubysl', '~> 2.0'
-  gem 'psych'
-end
diff --git a/README.md b/README.md
index b741d58..d0ca173 100644
--- a/README.md
+++ b/README.md
@@ -1,17 +1,17 @@
 # sha3  
 
-[![Gem Version](https://badge.fury.io/rb/sha3.svg)](https://badge.fury.io/rb/sha3) [![CI](https://secure.travis-ci.org/johanns/sha3.png)](https://secure.travis-ci.org/johanns/sha3) [![Dependencies](https://gemnasium.com/johanns/sha3.png)](https://gemnasium.com/johanns/sha3) [![CodeClimate](https://codeclimate.com/github/johanns/sha3.png)](https://codeclimate.com/github/johanns/sha3)
+[![Gem Version](https://badge.fury.io/rb/sha3.svg)](https://badge.fury.io/rb/sha3) [![CI](https://secure.travis-ci.org/johanns/sha3.png)](https://secure.travis-ci.org/johanns/sha3) [![CodeClimate](https://codeclimate.com/github/johanns/sha3.png)](https://codeclimate.com/github/johanns/sha3)
 
 **SHA3 for Ruby** is a native (C) binding to SHA3 (Keccak FIPS 202) cryptographic hashing algorithm.
 
-- Home :: [https://github.com/johanns/sha3#readme]()
-- Issues :: [https://github.com/johanns/sha3/issues]()
-- Documentation :: [http://rubydoc.info/gems/sha3/frames]()
+- [Home](https://github.com/johanns/sha3#readme)
+- [Issues](https://github.com/johanns/sha3/issues)
+- [Documentation](http://rubydoc.info/gems/sha3/frames)
 
 ## Warnings
 
-- Version 1.0+ breaks compatibility with previous versions of this gem.
-- Do NOT use SHA3 to hash passwords; use either ```bcrypt``` or ```scrypt``` instead!
+- Please do NOT use SHA3 to hash passwords -- use a slow hashing function instead (e.g.: `pbkdf2`, `argon2`, `bcrypt` or `scrypt`)
+- Version 1.0 introduces new API and is incompatible with previous versions (0.x).
 
 ## Module details
 
@@ -97,7 +97,7 @@ s = SHA3::Digest.file("tests.sh")
 * Native build tools (e.g., GCC, Minigw, etc.)
 * Gems: rubygems-tasks, rake, rspec, yard
 
-### Testing + RSpec
+### Testing
 
 Call ```rake``` to run the included RSpec tests.
 
@@ -107,39 +107,14 @@ Only a small subset of test vectors are included in the source repository; howev
 
 ### Rubies
 
-Tested with Rubies:
+Supported Ruby versions:
 
-  - MRI Ruby-Head
-  - MRI 2.1.0
-  - MRI 2.0.0
-  - MRI 1.9.3
-  - MRI 1.9.2
-  - MRI 1.8.7
-  - Rubinius 2
+  - MRI Ruby 2.4 - 3.0
 
-On:
 
-  - Ubuntu 12.04, 12.10, 13.04, 14.04, 15.04
-  - Windows 7, 8, 8.1, 10
-  - Mac OS X 10.6 - 10.11
-
-## Releases
-
-- *1.0.1* :: FIPS 202 compliance (breaks compatibility with earlier releases)
-- *0.2.6* :: Fixed bug #4
-- *0.2.5* :: Bug fixes. (See ChangeLog.rdoc)
-- *0.2.4* :: Bug fixes. (YANKED)
-- *0.2.3* :: Added documentation file (decoupled form C source); refactored C source.
-- *0.2.2* :: Added sub-class for each SHA3 supported bit-lengths (example: SHA3::Digest::SHA256). Minor bug fix.
-- *0.2.0* :: Production worthy, but breaks API compatibility with 0.1.x. Backward-compatibility will be maintained henceforth.
-- *0.1.x* :: Alpha code, and not suitable for production.
-
-## TO DO
-
-- Add SHAKE128/256 support
 
 ## Copyright
 
-Copyright (c) 2012 - 2015 Johanns Gregorian (https://github.com/johanns)
+Copyright (c) 2012 - 2020 Johanns Gregorian (https://github.com/johanns)
 
 **See LICENSE.txt for details.**
diff --git a/Rakefile b/Rakefile
index cd2a440..6f110cb 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,5 +1,3 @@
-# encoding: utf-8
-
 require 'rubygems'
 require 'rake'
 
@@ -10,34 +8,34 @@ begin
   Gem::Tasks.new
 rescue LoadError => e
   warn e.message
-  warn "Run `gem install rubygems-tasks` to install Gem::Tasks."
+  warn 'Run `gem install rubygems-tasks` to install Gem::Tasks.'
 end
 
 begin
-  gem 'rspec', '~> 3.3'
+  gem 'rspec'
   require 'rspec/core/rake_task'
 
   RSpec::Core::RakeTask.new
-rescue LoadError => e
+rescue LoadError
   task :spec do
-    abort "Please run `gem install rspec` to install RSpec."
+    abort 'Please run `gem install rspec` to install RSpec.'
   end
 end
 
-task :test    => :spec
-task :default => [:compile, :spec]
+task test: :spec
+task default: %i[compile spec]
 
 begin
   gem 'yard'
   require 'yard'
 
   YARD::Rake::YardocTask.new
-rescue LoadError => e
+rescue LoadError
   task :yard do
-    abort "Please run `gem install yard` to install YARD."
+    abort 'Please run `gem install yard` to install YARD.'
   end
 end
-task :doc => :yard
+task doc: :yard
 
 begin
   gem 'rake-compiler'
@@ -47,10 +45,10 @@ begin
     ext.name = 'sha3_n'
     ext.ext_dir = 'ext/sha3'
     ext.tmp_dir = 'tmp'
-    ext.source_pattern = "*.{c}"
+    ext.source_pattern = '*.{c}'
   end
-rescue LoadError => e
+rescue LoadError
   task :compile do
-    abort "Please run `gem install rake-compiler` to install Rake-Compiler."
+    abort 'Please run `gem install rake-compiler` to install Rake-Compiler.'
   end
 end
diff --git a/ext/sha3/digest.c b/ext/sha3/digest.c
index f32a690..1fd85b0 100644
--- a/ext/sha3/digest.c
+++ b/ext/sha3/digest.c
@@ -21,232 +21,250 @@ VALUE eSHA3DigestError;
 
 static void free_allox(MDX *mdx)
 {
-  if (mdx) {
-    if (mdx->state) {
-      free(mdx->state);
+    if (mdx)
+    {
+        if (mdx->state)
+        {
+            free(mdx->state);
+        }
+
+        free(mdx);
     }
 
-    free(mdx);
-  }
-
-  return;
+    return;
 }
 
 static VALUE c_digest_alloc(VALUE klass)
 {
-  MDX *mdx;
-  VALUE obj;
+    MDX *mdx;
+    VALUE obj;
 
-  mdx = (MDX *) malloc(sizeof(MDX));
-  if (!mdx) {
-    rb_raise(eSHA3DigestError, "failed to allocate object memory");
-  }
+    mdx = (MDX *)malloc(sizeof(MDX));
+    if (!mdx)
+    {
+        rb_raise(eSHA3DigestError, "failed to allocate object memory");
+    }
 
-  mdx->state = (Keccak_HashInstance *) malloc(sizeof(Keccak_HashInstance));
-  if (!mdx->state) {
-    free_allox(mdx);
-    rb_raise(eSHA3DigestError, "failed to allocate state memory");
-  }
+    mdx->state = (Keccak_HashInstance *)malloc(sizeof(Keccak_HashInstance));
+    if (!mdx->state)
+    {
+        free_allox(mdx);
+        rb_raise(eSHA3DigestError, "failed to allocate state memory");
+    }
 
-  obj = Data_Wrap_Struct(klass, 0, free_allox, mdx);
+    obj = Data_Wrap_Struct(klass, 0, free_allox, mdx);
 
-  memset(mdx->state, 0, sizeof(Keccak_HashInstance));
-  mdx->hashbitlen = 0;
+    memset(mdx->state, 0, sizeof(Keccak_HashInstance));
+    mdx->hashbitlen = 0;
 
-  return obj;
+    return obj;
 }
 
 static VALUE c_digest_update(VALUE, VALUE);
 
 HashReturn c_keccak_hash_initialize(MDX *mdx)
 {
-  HashReturn r = FAIL;
+    HashReturn r = FAIL;
 
-  switch (mdx->hashbitlen) {
+    switch (mdx->hashbitlen)
+    {
     case 224:
-      r = Keccak_HashInitialize_SHA3_224(mdx->state);
-      break;
+        r = Keccak_HashInitialize_SHA3_224(mdx->state);
+        break;
     case 256:
-      r = Keccak_HashInitialize_SHA3_256(mdx->state);
-      break;
+        r = Keccak_HashInitialize_SHA3_256(mdx->state);
+        break;
     case 384:
-      r = Keccak_HashInitialize_SHA3_384(mdx->state);
-      break;
+        r = Keccak_HashInitialize_SHA3_384(mdx->state);
+        break;
     case 512:
-      r = Keccak_HashInitialize_SHA3_512(mdx->state);
-      break;
+        r = Keccak_HashInitialize_SHA3_512(mdx->state);
+        break;
     }
 
-  return r;
+    return r;
 }
 
 // SHA3::Digest.new(type, [data]) -> self
 static VALUE c_digest_init(int argc, VALUE *argv, VALUE self)
 {
-  MDX *mdx;
-  VALUE hlen, data;
+    MDX *mdx;
+    VALUE hlen, data;
 
-  rb_scan_args(argc, argv, "02", &hlen, &data);
-  GETMDX(self, mdx);
+    rb_scan_args(argc, argv, "02", &hlen, &data);
+    GETMDX(self, mdx);
 
-  if (!NIL_P(hlen)) {
-    mdx->hashbitlen = get_hlen(hlen);
-  } else {
-    mdx->hashbitlen = 256;
-  }
+    if (!NIL_P(hlen))
+    {
+        mdx->hashbitlen = get_hlen(hlen);
+    }
+    else
+    {
+        mdx->hashbitlen = 256;
+    }
 
-  if (c_keccak_hash_initialize(mdx) != SUCCESS) {
-    rb_raise(eSHA3DigestError, "failed to initialize algorithm state");
-  }
+    if (c_keccak_hash_initialize(mdx) != SUCCESS)
+    {
+        rb_raise(eSHA3DigestError, "failed to initialize algorithm state");
+    }
 
-  if (!NIL_P(data)) {
-    return c_digest_update(self, data);
-  }
+    if (!NIL_P(data))
+    {
+        return c_digest_update(self, data);
+    }
 
-  return self;
+    return self;
 }
 
 // SHA3::Digest.update(data) -> self
 static VALUE c_digest_update(VALUE self, VALUE data)
 {
-  MDX *mdx;
-  DataLength dlen;
+    MDX *mdx;
+    DataLength dlen;
 
-  StringValue(data);
-  GETMDX(self, mdx);
+    StringValue(data);
+    GETMDX(self, mdx);
 
-  dlen = (RSTRING_LEN(data) * 8);
+    dlen = (RSTRING_LEN(data) * 8);
 
-  if (Keccak_HashUpdate(mdx->state, (BitSequence *) RSTRING_PTR(data), dlen) != SUCCESS) {
-    rb_raise(eSHA3DigestError, "failed to update hash data");
-  }
+    if (Keccak_HashUpdate(mdx->state, (BitSequence *)RSTRING_PTR(data), dlen) != SUCCESS)
+    {
+        rb_raise(eSHA3DigestError, "failed to update hash data");
+    }
 
-  return self;
+    return self;
 }
 
 // SHA3::Digest.reset() -> self
 static VALUE c_digest_reset(VALUE self)
 {
-  MDX *mdx;
+    MDX *mdx;
 
-  GETMDX(self, mdx);
+    GETMDX(self, mdx);
 
-  memset(mdx->state, 0, sizeof(Keccak_HashInstance));
+    memset(mdx->state, 0, sizeof(Keccak_HashInstance));
 
-  if (c_keccak_hash_initialize(mdx) != SUCCESS) {
-    rb_raise(eSHA3DigestError, "failed to reset internal state");
-  }
+    if (c_keccak_hash_initialize(mdx) != SUCCESS)
+    {
+        rb_raise(eSHA3DigestError, "failed to reset internal state");
+    }
 
-  return self;
+    return self;
 }
 
 static int cmp_states(MDX *mdx1, MDX *mdx2)
 {
     return (
-      (mdx1->hashbitlen == mdx2->hashbitlen) &&
-      (strcmp((const char *) mdx1->state->sponge.state, (const char *)mdx2->state->sponge.state) == 0) &&
-      (mdx1->state->sponge.rate == mdx2->state->sponge.rate) &&
-      (mdx1->state->sponge.byteIOIndex == mdx2->state->sponge.byteIOIndex) &&
-      (mdx1->state->sponge.squeezing == mdx2->state->sponge.squeezing) &&
-      (mdx1->state->fixedOutputLength == mdx2->state->fixedOutputLength) &&
-      (mdx1->state->delimitedSuffix == mdx2->state->delimitedSuffix)
-    );
+        (mdx1->hashbitlen == mdx2->hashbitlen) &&
+        (strcmp((const char *)mdx1->state->sponge.state, (const char *)mdx2->state->sponge.state) == 0) &&
+        (mdx1->state->sponge.rate == mdx2->state->sponge.rate) &&
+        (mdx1->state->sponge.byteIOIndex == mdx2->state->sponge.byteIOIndex) &&
+        (mdx1->state->sponge.squeezing == mdx2->state->sponge.squeezing) &&
+        (mdx1->state->fixedOutputLength == mdx2->state->fixedOutputLength) &&
+        (mdx1->state->delimitedSuffix == mdx2->state->delimitedSuffix));
 }
 
 // SHA3::Digest.copy(obj) -> self
 static VALUE c_digest_copy(VALUE self, VALUE obj)
 {
-  MDX *mdx1, *mdx2;
+    MDX *mdx1, *mdx2;
 
-  rb_check_frozen(self);
-  if (self == obj) {
-    return self;
-  }
+    rb_check_frozen(self);
+    if (self == obj)
+    {
+        return self;
+    }
+
+    GETMDX(self, mdx1);
+    SAFEGETMDX(obj, mdx2);
 
-  GETMDX(self, mdx1);
-  SAFEGETMDX(obj, mdx2);
+    memcpy(mdx1->state, mdx2->state, sizeof(Keccak_HashInstance));
+    mdx1->hashbitlen = mdx2->hashbitlen;
 
-  memcpy(mdx1->state, mdx2->state, sizeof(Keccak_HashInstance));
-  mdx1->hashbitlen = mdx2->hashbitlen;
+    // Fetch the data again to make sure it was copied
+    GETMDX(self, mdx1);
+    SAFEGETMDX(obj, mdx2);
 
-  // Fetch the data again to make sure it was copied
-  GETMDX(self, mdx1);
-  SAFEGETMDX(obj, mdx2);
-  if (!cmp_states(mdx1, mdx2)) {
-    rb_raise(eSHA3DigestError, "failed to copy state");
-  }
+    if (!cmp_states(mdx1, mdx2))
+    {
+        rb_raise(eSHA3DigestError, "failed to copy state");
+    }
 
-  return self;
+    return self;
 }
 
 // SHA3::Digest.digest_length -> Integer
 static VALUE c_digest_length(VALUE self)
 {
-  MDX *mdx;
-  GETMDX(self, mdx);
+    MDX *mdx;
+    GETMDX(self, mdx);
 
-  return ULL2NUM(mdx->hashbitlen / 8);
+    return ULL2NUM(mdx->hashbitlen / 8);
 }
 
 // SHA3::Digest.block_length -> Integer
 static VALUE c_digest_block_length(VALUE self)
 {
-  MDX *mdx;
-  GETMDX(self, mdx);
+    MDX *mdx;
+    GETMDX(self, mdx);
 
-  return ULL2NUM(200 - (2 * (mdx->hashbitlen / 8)));
+    return ULL2NUM(200 - (2 * (mdx->hashbitlen / 8)));
 }
 
 // SHA3::Digest.name -> String
 static VALUE c_digest_name(VALUE self)
 {
-  return rb_str_new2("SHA3");
+    return rb_str_new2("SHA3");
 }
 
 // SHA3::Digest.finish() -> String
 static VALUE c_digest_finish(int argc, VALUE *argv, VALUE self)
 {
-  MDX *mdx;
-  VALUE str;
+    MDX *mdx;
+    VALUE str;
 
-  rb_scan_args(argc, argv, "01", &str);
-  GETMDX(self, mdx);
+    rb_scan_args(argc, argv, "01", &str);
+    GETMDX(self, mdx);
 
-  if (NIL_P(str)) {
-    str = rb_str_new(0, mdx->hashbitlen / 8);
-  } else {
-    StringValue(str);
-    rb_str_resize(str, mdx->hashbitlen / 8);
-  }
+    if (NIL_P(str))
+    {
+        str = rb_str_new(0, mdx->hashbitlen / 8);
+    }
+    else
+    {
+        StringValue(str);
+        rb_str_resize(str, mdx->hashbitlen / 8);
+    }
 
-  if (Keccak_HashFinal(mdx->state, (BitSequence *) RSTRING_PTR(str)) != SUCCESS) {
-    rb_raise(eSHA3DigestError, "failed to finalize digest");
-  }
+    if (Keccak_HashFinal(mdx->state, (BitSequence *)RSTRING_PTR(str)) != SUCCESS)
+    {
+        rb_raise(eSHA3DigestError, "failed to finalize digest");
+    }
 
-  return str;
+    return str;
 }
 
 void Init_sha3_n_digest()
 {
-  rb_require("digest");
-
-  /* SHA3::Digest (class) */
-  cSHA3Digest = rb_define_class_under(mSHA3, "Digest", rb_path2class("Digest::Class"));
-  /* SHA3::Digest::DigestError (class) */
-  eSHA3DigestError = rb_define_class_under(cSHA3Digest, "DigestError", rb_eStandardError);
-
-  // SHA3::Digest (class) methods
-  rb_define_alloc_func(cSHA3Digest, c_digest_alloc);
-  rb_define_method(cSHA3Digest, "initialize", c_digest_init, -1);
-  rb_define_method(cSHA3Digest, "update", c_digest_update, 1);
-  rb_define_method(cSHA3Digest, "reset", c_digest_reset, 0);
-  rb_define_method(cSHA3Digest, "initialize_copy", c_digest_copy, 1);
-  rb_define_method(cSHA3Digest, "digest_length", c_digest_length, 0);
-  rb_define_method(cSHA3Digest, "block_length", c_digest_block_length, 0);
-  rb_define_method(cSHA3Digest, "name", c_digest_name, 0);
-  rb_define_private_method(cSHA3Digest, "finish", c_digest_finish, -1);
-
-  rb_define_alias(cSHA3Digest, "<<", "update");
-
-  return;
+    rb_require("digest");
+
+    /* SHA3::Digest (class) */
+    cSHA3Digest = rb_define_class_under(mSHA3, "Digest", rb_path2class("Digest::Class"));
+    /* SHA3::Digest::DigestError (class) */
+    eSHA3DigestError = rb_define_class_under(cSHA3Digest, "DigestError", rb_eStandardError);
+
+    // SHA3::Digest (class) methods
+    rb_define_alloc_func(cSHA3Digest, c_digest_alloc);
+    rb_define_method(cSHA3Digest, "initialize", c_digest_init, -1);
+    rb_define_method(cSHA3Digest, "update", c_digest_update, 1);
+    rb_define_method(cSHA3Digest, "reset", c_digest_reset, 0);
+    rb_define_method(cSHA3Digest, "initialize_copy", c_digest_copy, 1);
+    rb_define_method(cSHA3Digest, "digest_length", c_digest_length, 0);
+    rb_define_method(cSHA3Digest, "block_length", c_digest_block_length, 0);
+    rb_define_method(cSHA3Digest, "name", c_digest_name, 0);
+    rb_define_private_method(cSHA3Digest, "finish", c_digest_finish, -1);
+
+    rb_define_alias(cSHA3Digest, "<<", "update");
+
+    return;
 }
diff --git a/ext/sha3/digest.h b/ext/sha3/digest.h
index a0e6a7d..d83246f 100644
--- a/ext/sha3/digest.h
+++ b/ext/sha3/digest.h
@@ -3,37 +3,45 @@
 #ifndef _DIGEST_H_
 #define _DIGEST_H_
 
-#ifdef  __cplusplus
-extern "C" {
+#ifdef __cplusplus
+extern "C"
+{
 #endif
 
 // From ruby/ext/openssl/ossl_digest.c
-#define GETMDX(obj, mdx) do {                                    \
-  Data_Get_Struct((obj), MDX, (mdx));                            \
-  if (!(mdx)) {                                                  \
-    rb_raise(rb_eRuntimeError, "Digest data not initialized!");  \
-  }                                                              \
-} while (0)
-
-#define SAFEGETMDX(obj, mdx) do {                                \
-  if (!rb_obj_is_kind_of(obj, cSHA3Digest)) {                        \
-    rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)",\
-             rb_obj_classname(obj), rb_class2name(cSHA3Digest));     \
-  }                                                              \
-  GETMDX(obj, mdx);                                              \
-} while(0)
-
-extern VALUE cSHA3Digest;
-extern VALUE eSHA3DigestError;
-
-typedef struct {
-  Keccak_HashInstance *state;
-  int hashbitlen;
-} MDX;
-
-void Init_sha3_n_digest(void);
-
-#ifdef  __cplusplus
+#define GETMDX(obj, mdx)                                                \
+    do                                                                  \
+    {                                                                   \
+        Data_Get_Struct((obj), MDX, (mdx));                             \
+        if (!(mdx))                                                     \
+        {                                                               \
+            rb_raise(rb_eRuntimeError, "Digest data not initialized!"); \
+        }                                                               \
+    } while (0)
+
+#define SAFEGETMDX(obj, mdx)                                              \
+    do                                                                    \
+    {                                                                     \
+        if (!rb_obj_is_kind_of(obj, cSHA3Digest))                         \
+        {                                                                 \
+            rb_raise(rb_eTypeError, "wrong argument (%s)! (expected %s)", \
+                     rb_obj_classname(obj), rb_class2name(cSHA3Digest));  \
+        }                                                                 \
+        GETMDX(obj, mdx);                                                 \
+    } while (0)
+
+    extern VALUE cSHA3Digest;
+    extern VALUE eSHA3DigestError;
+
+    typedef struct
+    {
+        Keccak_HashInstance *state;
+        int hashbitlen;
+    } MDX;
+
+    void Init_sha3_n_digest(void);
+
+#ifdef __cplusplus
 }
 #endif
 
diff --git a/ext/sha3/extconf.rb b/ext/sha3/extconf.rb
index eeb2a2a..c7c27e6 100644
--- a/ext/sha3/extconf.rb
+++ b/ext/sha3/extconf.rb
@@ -17,5 +17,5 @@ end
 find_header("sha3.h")
 find_header("digest.h")
 
-$CFLAGS = ' -fomit-frame-pointer -O3 -g0 -march=nocona '
+$CFLAGS = ' -fomit-frame-pointer -O3 -g0 -march=native '
 create_makefile 'sha3_n'
diff --git a/ext/sha3/sha3.c b/ext/sha3/sha3.c
index 251d4d4..2e3722f 100644
--- a/ext/sha3/sha3.c
+++ b/ext/sha3/sha3.c
@@ -7,40 +7,56 @@ VALUE eSHA3Error;
 
 int get_hlen(VALUE obj)
 {
-  int hlen;
-
-  if (TYPE(obj) == T_SYMBOL) {
-    ID symid;
-
-    symid = SYM2ID(obj);
-
-    if (rb_intern("sha224") == symid)
-      hlen = 224;
-    else if (rb_intern("sha256") == symid)
-      hlen = 256;
-    else if (rb_intern("sha384") == symid)
-      hlen = 384;
-    else if (rb_intern("sha512") == symid)
-      hlen = 512;
+    int hlen;
+
+    if (TYPE(obj) == T_SYMBOL)
+    {
+        ID symid;
+
+        symid = SYM2ID(obj);
+
+        if (rb_intern("sha224") == symid)
+        {
+            hlen = 224;
+        }
+        else if (rb_intern("sha256") == symid)
+        {
+            hlen = 256;
+        }
+        else if (rb_intern("sha384") == symid)
+        {
+            hlen = 384;
+        }
+        else if (rb_intern("sha512") == symid)
+        {
+            hlen = 512;
+        }
+        else
+        {
+            rb_raise(eSHA3Error, "invalid hash bit symbol (should be: :sha224, :sha256, :sha384, or :sha512");
+        }
+    }
+    else if (TYPE(obj) == T_FIXNUM)
+    {
+        hlen = NUM2INT(obj);
+
+        if ((hlen != 224) && (hlen != 256) && (hlen != 384) && (hlen != 512))
+        {
+            rb_raise(rb_eArgError, "invalid hash bit length (should be: 224, 256, 384, or 512)");
+        }
+    }
     else
-      rb_raise(eSHA3Error, "invalid hash bit symbol (should be: :sha224, :sha256, :sha384, or :sha512");
-  }
-  else if (TYPE(obj) == T_FIXNUM) {
-    hlen = NUM2INT(obj);
-
-    if ((hlen != 224) && (hlen != 256) && (hlen != 384) && (hlen != 512))
-      rb_raise(rb_eArgError, "invalid hash bit length (should be: 224, 256, 384, or 512)");
-  }
-  else
-    rb_raise(eSHA3Error, "unknown type value");
-
-  return hlen;
+    {
+        rb_raise(eSHA3Error, "unknown type value");
+    }
+
+    return hlen;
 }
 
 void Init_sha3_n()
 {
-  mSHA3 = rb_define_module("SHA3");
-  eSHA3Error = rb_define_class_under(mSHA3, "SHA3Error", rb_eStandardError);
+    mSHA3 = rb_define_module("SHA3");
+    eSHA3Error = rb_define_class_under(mSHA3, "SHA3Error", rb_eStandardError);
 
-  Init_sha3_n_digest();
+    Init_sha3_n_digest();
 }
\ No newline at end of file
diff --git a/ext/sha3/sha3.h b/ext/sha3/sha3.h
index 96f4cee..2357ea5 100644
--- a/ext/sha3/sha3.h
+++ b/ext/sha3/sha3.h
@@ -8,17 +8,18 @@
 #include "KeccakHash.h"
 #include "digest.h"
 
-#ifdef  __cplusplus
-extern "C" {
+#ifdef __cplusplus
+extern "C"
+{
 #endif
 
-extern VALUE mSHA3;
-extern VALUE eSHA3Error;
+    extern VALUE mSHA3;
+    extern VALUE eSHA3Error;
 
-int get_hlen(VALUE);
-void Init_sha3_n(void);
+    int get_hlen(VALUE);
+    void Init_sha3_n(void);
 
-#ifdef  __cplusplus
+#ifdef __cplusplus
 }
 #endif
 
diff --git a/lib/sha3/version.rb b/lib/sha3/version.rb
index 8b3e18c..a729dfe 100644
--- a/lib/sha3/version.rb
+++ b/lib/sha3/version.rb
@@ -2,9 +2,8 @@ module SHA3
   extend self
 
   # sha3 release version
-  VERSION = "1.0.1"
+  VERSION = '1.0.2'.freeze
 
   # keccak version number
-  KECCAK_VERSION = "4.0"
+  KECCAK_VERSION = '4.0'.freeze
 end
-
diff --git a/sha3.gemspec b/sha3.gemspec
index f9d72b3..3e9d310 100644
--- a/sha3.gemspec
+++ b/sha3.gemspec
@@ -1,25 +1,23 @@
-# -*- encoding: utf-8 -*-
-
-require File.expand_path('../lib/sha3/version', __FILE__)
+require File.expand_path('lib/sha3/version', __dir__)
 
 Gem::Specification.new do |gem|
-  gem.name          = "sha3"
+  gem.name          = 'sha3'
   gem.version       = SHA3::VERSION
-  gem.summary       = %q{SHA3 for Ruby}
-  gem.description   = %q{SHA3 for Ruby is a native (C) FIPS 202 compliant implementation of SHA3 (Keccak) cryptographic hashing algorithm.}
-  gem.license       = "MIT"
-  gem.authors       = ["Johanns Gregorian"]
-  gem.email         = "io+sha3@jsg.io"
-  gem.homepage      = "https://github.com/johanns/sha3#readme"
+  gem.summary       = 'SHA3 for Ruby'
+  gem.description   = 'SHA3 for Ruby is a native (C) FIPS 202 compliant implementation of SHA3 (Keccak) cryptographic hashing algorithm.'
+  gem.license       = 'MIT'
+  gem.authors       = ['Johanns Gregorian']
+  gem.email         = 'io+sha3@jsg.io'
+  gem.homepage      = 'https://github.com/johanns/sha3#readme'
 
   gem.files         = `git ls-files`.split($/)
-  gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
+  gem.executables   = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
   gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
   gem.require_paths = ['lib']
   gem.extensions    = ['ext/sha3/extconf.rb']
 
-  gem.add_development_dependency "rake-compiler"
+  gem.add_development_dependency 'rake-compiler', '~> 1.1'
   gem.add_development_dependency 'rspec', '~> 3.3'
-  gem.add_development_dependency 'rubygems-tasks'
-  gem.add_development_dependency 'yard'
+  gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
+  gem.add_development_dependency 'yard', '~> 0.9'
 end
diff --git a/spec/generate_tests.rb b/spec/generate_tests.rb
index 23fdfc7..5d393c0 100644
--- a/spec/generate_tests.rb
+++ b/spec/generate_tests.rb
@@ -4,46 +4,47 @@ FILES = [
   ['data/ShortMsgKAT_SHA3-224.txt', 224],
   ['data/ShortMsgKAT_SHA3-256.txt', 256],
   ['data/ShortMsgKAT_SHA3-384.txt', 384],
-  ['data/ShortMsgKAT_SHA3-512.txt', 512],
-]
+  ['data/ShortMsgKAT_SHA3-512.txt', 512]
+].freeze
 
 def gen_digest_byte_tests
   FILES.each do |path, hashlen|
     name = File.basename(path).split('.')[0]
 
-    f = File.new("sha3_digest_#{name}_spec.rb", "w")
+    f = File.new("sha3_digest_#{name}_spec.rb", 'w')
     f.puts(
-%Q{require 'spec_helper'
+      %{require 'spec_helper'
 require 'sha3'
 
 describe "SHA3::Digest.new(#{hashlen})" do
   it "should match byte-length test vectors (#{name})." do
-})
+}
+    )
     contents = File.read(path).split('Len = ')
     contents.each do |test|
       lines = test.split("\n")
-      if !lines.empty? && lines[0] !~ /^#/
-        length = lines[0].to_i
-        if length % 8 == 0 && length != 0
-          msg_raw = [lines[1].split(' = ').last].pack("H*")
-          md = lines[2].split(' = ').last.downcase
-          f.puts(
-%Q{   expect(SHA3::Digest.new(#{hashlen}, #{msg_raw.inspect}).hexdigest).to eq("#{md}")
-})
-        end
-      end
+      next unless !lines.empty? && lines[0] !~ /^#/
+
+      length = lines[0].to_i
+      next unless (length % 8).zero? && length != 0
+
+      msg_raw = [lines[1].split(' = ').last].pack('H*')
+      md = lines[2].split(' = ').last.downcase
+      f.puts(
+        %{   expect(SHA3::Digest.new(#{hashlen}, #{msg_raw.inspect}).hexdigest).to eq("#{md}")
+                    }
+      )
     end
     f.puts(
-%Q{ end
+      %( end
 end
-})
+)
+    )
     f.close
   end
 end
 
-def setup
-
-end
+def setup; end
 
 gen_digest_byte_tests
 gen_compute_bit_tests
diff --git a/tests.sh b/tests.sh
index f7dbe6c..3a90206 100755
--- a/tests.sh
+++ b/tests.sh
@@ -5,22 +5,22 @@ rm -fv spec/sha3_digest*.rb
 
 if [ -d "spec/data" ]
 then
-  rm -rfv spec/data/*
+    rm -rfv spec/data/*
 else
-  mkdir "spec/data"
+    mkdir "spec/data"
 fi
 
 pushd "spec/data"
 
 if [ -f "*.txt" ]
 then
-  rm -v *.txt
+    rm -v *.txt
 fi
 
-wget "https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-224.txt"
-wget "https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-256.txt"
-wget "https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-384.txt"
-wget "https://raw.githubusercontent.com/gvanas/KeccakCodePackage/master/TestVectors/ShortMsgKAT_SHA3-512.txt"
+wget "https://raw.githubusercontent.com/XKCP/XKCP/master/tests/TestVectors/ShortMsgKAT_SHA3-224.txt"
+wget "https://raw.githubusercontent.com/XKCP/XKCP/master/tests/TestVectors/ShortMsgKAT_SHA3-256.txt"
+wget "https://raw.githubusercontent.com/XKCP/XKCP/master/tests/TestVectors/ShortMsgKAT_SHA3-384.txt"
+wget "https://raw.githubusercontent.com/XKCP/XKCP/master/tests/TestVectors/ShortMsgKAT_SHA3-512.txt"
 
 cd ".."