Skip to content

Commit

Permalink
Return a Ciphertext object
Browse files Browse the repository at this point in the history
This behaves approximately like a string, at least for many operations
that a ciphertext is likely to have performed on it.  It also supports
encoding to any encoding recognised by RbNaCl
  • Loading branch information
namelessjon committed Mar 13, 2013
1 parent 3d068b9 commit 8e38448
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/rbnacl.rb
Expand Up @@ -25,6 +25,7 @@ class LengthError < ArgumentError; end
require "rbnacl/keys/public_key"
require "rbnacl/keys/signing_key"
require "rbnacl/keys/verify_key"
require "rbnacl/ciphertext"
require "rbnacl/box"
require "rbnacl/secret_box"
require "rbnacl/hash"
Expand Down
57 changes: 57 additions & 0 deletions lib/rbnacl/ciphertext.rb
@@ -0,0 +1,57 @@
# encoding: binary
module Crypto
# A Ciphertext returned by the library
#
# Holds the ciphertext returned by the library. This acts like a string in
# many cases, but also supports interrogating for the primitive used and can
# be encoded into a variety of formats.
class Ciphertext
attr_reader :ciphertext, :primitive
attr_accessor :default_encoding
def initialize(ciphertext, primitive, default_encoding = :raw)
@ciphertext = ciphertext
@primitive = primitive
@default_encoding = default_encoding
end

# Returns the ciphertext string
#
# Optionally encodes it too
#
# @param encoding [Symbol] encoding to use
#
# @return [String] ciphertext
def to_str(encoding = default_encoding)
Encoder[encoding].encode(ciphertext)
end

alias to_s to_str


def inspect
"#<#{self.class}:#{primitive}:#{to_str(:hex)[0,16]}>"
end

# size of the ciphertext in bytes
#
# This returns the size in the specified encoding, to avoid confusion
# in the case of a non-raw default encoding.
#
# @param encoding [Symbol] encoding to use
#
# @return [Integer bytesize of encoded ciphertext
def bytesize(encoding = default_encoding)
to_s(encoding).bytesize
end

# Concatenate a string
def +(thing)
to_s + thing.to_s
end

# tests for equality by converting a to string
def ==(thing)
thing.respond_to?(:to_s) ? to_s == thing.to_s : false
end
end
end
3 changes: 2 additions & 1 deletion lib/rbnacl/secret_box/xsalsa20_poly1305.rb
Expand Up @@ -70,7 +70,8 @@ def box(nonce, message)
ct = Util.zeros(msg.bytesize)

NaCl.crypto_secretbox_xsalsa20poly1305(ct, msg, msg.bytesize, nonce, @key) || raise(CryptoError, "Encryption failed")
Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
ct = Util.remove_zeros(NaCl::BOXZEROBYTES, ct)
Ciphertext.new(ct, PRIMITIVE)
end
alias encrypt box

Expand Down
40 changes: 40 additions & 0 deletions spec/rbnacl/ciphertext_spec.rb
@@ -0,0 +1,40 @@
# encoding: binary
require 'spec_helper'

describe Crypto::Ciphertext do
let(:text) { "hello" }
let(:primitive) { :test }
let(:ciphertext) { described_class.new(text, primitive) }
let(:encoded_ciphertext) { described_class.new(text, primitive, :hex) }
it "returns the ciphertext on #to_s" do
ciphertext.to_s.should == text
end

it "returns the primitive" do
ciphertext.primitive.should be primitive
end

it "interpolates correctly" do
"#{ciphertext}".should == text
end

it "packs correctly" do
[ciphertext].pack('a*').should == text
end

it "encodes when asked" do
ciphertext.to_s(:hex).should == Crypto::Encoder[:hex].encode(text)
end

it "behaves like a string for equality" do
ciphertext.should == text
end

it "behaves like a string for addition" do
(ciphertext + text).should == text * 2
end

it "accepts a default encoding" do
encoded_ciphertext.should == Crypto::Encoder[:hex].encode(text)
end
end

0 comments on commit 8e38448

Please sign in to comment.