Skip to content

Commit

Permalink
First revision
Browse files Browse the repository at this point in the history
  • Loading branch information
pond committed Aug 7, 2022
0 parents commit 1bf4674
Show file tree
Hide file tree
Showing 20 changed files with 1,157 additions and 0 deletions.
28 changes: 28 additions & 0 deletions .github/workflows/ruby.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Ruby

on:
push:
branches:
- main

pull_request:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest
name: Ruby ${{ matrix.ruby }}
strategy:
matrix:
ruby: ['2.7', '3.0', '3.1']

steps:
- uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Run tests
run: bundle exec rspec
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/.bundle/
/.yardoc
/_yardoc/
/coverage/
/docs/
/pkg/
/spec/reports/
/tmp/
.DS_Store
*.gem

3 changes: 3 additions & 0 deletions .rspec
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
--format documentation
--color
--require spec_helper
13 changes: 13 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
AllCops:
TargetRubyVersion: 2.6

Style/StringLiterals:
Enabled: true
EnforcedStyle: double_quotes

Style/StringLiteralsInInterpolation:
Enabled: true
EnforcedStyle: double_quotes

Layout/LineLength:
Max: 120
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## [0.1.0] - 2022-08-08

- Initial release
10 changes: 10 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# frozen_string_literal: true

source "https://rubygems.org"

# Use a fork version of SDoc; can't use ":git" in ".gemspec" files, so do
# it here instead.
#
gem 'sdoc', git: 'https://github.com/pond/sdoc.git', branch: 'master'

gemspec
124 changes: 124 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
GIT
remote: https://github.com/pond/sdoc.git
revision: 4197420bd974d1d5be9699ac67726297a7acabe7
branch: master
specs:
sdoc (2.3.1)
rdoc (>= 5.0, < 7.0.0)

PATH
remote: .
specs:
ooxml_encryption (0.1.0)
nokogiri (~> 1.13)
openssl (~> 3.0)
simple_cfb (~> 0.1)

GEM
remote: https://rubygems.org/
specs:
actionpack (7.0.3.1)
actionview (= 7.0.3.1)
activesupport (= 7.0.3.1)
rack (~> 2.0, >= 2.2.0)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actionview (7.0.3.1)
activesupport (= 7.0.3.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activesupport (7.0.3.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
builder (3.2.4)
byebug (11.1.3)
concurrent-ruby (1.1.10)
crass (1.0.6)
diff-lcs (1.5.0)
docile (1.4.0)
doggo (1.2.0)
rspec-core (~> 3.10)
erubi (1.11.0)
i18n (1.12.0)
concurrent-ruby (~> 1.0)
loofah (2.18.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
method_source (1.0.0)
minitest (5.16.2)
nokogiri (1.13.8-x86_64-darwin)
racc (~> 1.4)
openssl (3.0.0)
psych (4.0.4)
stringio
racc (1.6.0)
rack (2.2.4)
rack-test (2.0.2)
rack (>= 1.3)
rails-dom-testing (2.0.3)
activesupport (>= 4.2.0)
nokogiri (>= 1.6)
rails-html-sanitizer (1.4.3)
loofah (~> 2.3)
railties (7.0.3.1)
actionpack (= 7.0.3.1)
activesupport (= 7.0.3.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rake (13.0.6)
rdoc (6.4.0)
psych (>= 4.0.0)
rspec-core (3.11.0)
rspec-support (~> 3.11.0)
rspec-expectations (3.11.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
rspec-mocks (3.11.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.11.0)
rspec-rails (5.1.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
railties (>= 5.2)
rspec-core (~> 3.10)
rspec-expectations (~> 3.10)
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-support (3.11.0)
simple_cfb (0.1.0)
activesupport (> 5, < 8)
simplecov (0.21.2)
docile (~> 1.1)
simplecov-html (~> 0.11)
simplecov_json_formatter (~> 0.1)
simplecov-html (0.12.3)
simplecov-rcov (0.3.1)
simplecov (>= 0.4.1)
simplecov_json_formatter (0.1.4)
stringio (3.0.2)
thor (1.2.1)
tzinfo (2.0.5)
concurrent-ruby (~> 1.0)
zeitwerk (2.6.0)

PLATFORMS
x86_64-darwin-21

DEPENDENCIES
byebug (~> 11.1)
doggo (~> 1.2)
ooxml_encryption!
rdoc (~> 6.4)
rspec-rails (~> 5.0)
sdoc!
simplecov-rcov (~> 0.2)

BUNDLED WITH
2.3.13
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2022 RIPA Global

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
106 changes: 106 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# OOXML Encryption
## Overview

OOXML Encryption provides encryption and decryption support for OOXML (Microsoft Excel / `.xlsx` files) via full-spreadsheet password protection using AES encryption with SHA-512 hashes. This is a port of the encryption part of:

* https://github.com/dtjohnson/xlsx-populate

Using an input OOXML file generated by https://github.com/felixbuenemann/xlsxtream, encrypted output was tested on macOS 12.5 in Microsoft Excel 16.63.1, Apple Numbers 12.1 (and QuickLook from the Finder) and LibreOffice Vanilla 7.2.5.2, all of which prompted for a password, handled an incorrect password as expected and correctly opened the decrypted spreadsheet if given the correct password.

For low-level file format details, see:

* https://docs.microsoft.com/en-us/openspecs/office_file_formats/ms-offcrypto
* https://github.com/RIPAGlobal/simple_cfb/



## Installation

Install the gem and add to the application's `Gemfile` by executing:

$ bundle add ooxml_encryption

If bundler is not being used to manage dependencies, install the gem by executing:

$ gem install ooxml_encryption



## Usage
### Encrypting a spreadsheet

If you have read a file containing an unprotected OOXML file into `unprotected_data` as a String using `ASCII-8BIT` encoding, or if you have generated such a string in memory directly, then using a `password` supplied as a String in an encoding of your choice:

```ruby
require 'ooxml_encryption'

encryptor = OoxmlEncryption.new
encrypted_data = encryptor.encrypt(
unencrypted_spreadsheet_data: unprotected_data,
password: password
)
```

...then write `encrypted_data` to a file using binary mode, e.g.:

```ruby
File.open('/path/to/encrypted.xlsx', 'wb') do | file |
file.write(encrypted_data)
end
```

### Decrypting a spreadsheet

If you have read a file containing an encrypted OOXML file into `encrypted_data` as a String using `ASCII-8BIT` encoding and have obtained a `password` from the spreadsheet's owning user as a String in an encoding of your choice, then:

```
require 'ooxml_encryption'
decryptor = OoxmlEncryption.new
decrypted_data = decryptor.decrypt(
encrypted_spreadsheeet_data: encrypted_data,
password: password
)
```

...then write `decrypted_data` to a file using binary mode, e.g.:

```ruby
File.open('/path/to/unprotected.xlsx', 'wb') do | file |
file.write(decrypted_data)
end
```



## Resource overhead

Due to the nature of the underlying file format, which has various tables written at the start of the file that can only be built once the file contents are known, encrypted spreadsheets must be created or decoded in RAM. Streamed output or input is not possible. Attempting to create or read large spreadsheets is therefore not recommended - there could be very large RAM requirements arising.



## Security concerns

The level of security this provides should be assessed relative to your requirements; numerous articles are available online which discuss the pros and cons. The quality of the password will also have a big impact on the overall security of an output file.



## Development

Use `bundle exec rspec` to run tests. Run `bin/console` for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run `bundle exec rake install`. If you have sufficient RubyGems access to release a new version, update the version number and date in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).

Locally generated RDoc HTML seems to contain a more comprehensive and inter-linked set of pages than those available from `rubydoc.info`. You can (re)generate the internal [`rdoc` documentation](https://ruby-doc.org/stdlib-2.4.1/libdoc/rdoc/rdoc/RDoc/Markup.html#label-Supported+Formats) with:

```shell
bundle exec rake rerdoc
```

...yes, that's `rerdoc` - Re-R-Doc - then open `docs/rdoc/index.html`.



## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/RIPAGlobal/ooxml_encryption.
16 changes: 16 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'rake'
require 'rspec/core/rake_task'
require 'rdoc/task'
require 'sdoc'

RSpec::Core::RakeTask.new(:default) do | t |
end

Rake::RDocTask.new do | rd |
rd.rdoc_files.include('README.md', 'lib/**/*.rb')

rd.title = 'OOXML Encryption'
rd.main = 'README.md'
rd.rdoc_dir = 'docs/rdoc'
rd.generator = 'sdoc'
end
15 changes: 15 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env ruby
# frozen_string_literal: true

require "bundler/setup"
require "ooxml_encryption"

# You can add fixtures and/or initialization code here to make experimenting
# with your gem easier. You can also use a different console, if you like.

# (If you use this, don't forget to add pry to your Gemfile!)
# require "pry"
# Pry.start

require "irb"
IRB.start(__FILE__)
8 changes: 8 additions & 0 deletions bin/setup
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
set -vx

bundle install

# Do any other automated setup that you need to do here
Loading

0 comments on commit 1bf4674

Please sign in to comment.