Class: Akero
- Inherits:
-
Object
- Object
- Akero
- Defined in:
- lib/akero.rb,
lib/akero.rb,
lib/akero/cli.rb,
lib/akero/version.rb,
lib/akero/benchmark.rb
Overview
Akero
Defined Under Namespace
Constant Summary collapse
- DEFAULT_RSA_BITS =
4096
- DEFAULT_DIGEST =
OpenSSL::Digest::SHA512
- VERSION =
'1.1.1'
Class Method Summary collapse
-
.fingerprint_from_cert(cert) ⇒ String
Extract fingerprint from an Akero public key.
-
.load(private_key) ⇒ Akero
Load an Akero identity.
-
.replate(msg, plates, reverse = false) ⇒ String
Swap the “license plates” on an ascii-armored message.
Instance Method Summary collapse
-
#encrypt(to, plaintext, ascii_armor = true) ⇒ String
Sign->encrypt->sign a message for 1 or more recipients.
-
#id ⇒ String
Unique fingerprint of this Akero keypair.
-
#initialize(rsa_bits = DEFAULT_RSA_BITS, digest = DEFAULT_DIGEST) ⇒ Akero
constructor
Create a new Akero instance.
-
#private_key ⇒ String
Private key (do not share this with anyone!).
-
#public_key ⇒ String
Akero public key.
-
#receive(ciphertext) ⇒ Akero::Message
Receive an Akero message.
-
#sign(plaintext, ascii_armor = true) ⇒ String
Sign a message.
Constructor Details
#initialize(rsa_bits = DEFAULT_RSA_BITS, digest = DEFAULT_DIGEST) ⇒ Akero
Create a new Akero instance.
112 113 114 |
# File 'lib/akero.rb', line 112 def initialize(rsa_bits = DEFAULT_RSA_BITS, digest = DEFAULT_DIGEST) @key, @cert = generate_keypair(rsa_bits, digest) unless rsa_bits.nil? end |
Class Method Details
.fingerprint_from_cert(cert) ⇒ String
Extract fingerprint from an Akero public key.
272 273 274 275 276 277 |
# File 'lib/akero.rb', line 272 def self.fingerprint_from_cert(cert) cert.extensions.map.each do |e| return "AK:#{e.value}" if e.oid == 'subjectKeyIdentifier' end raise ERR_CERT_CORRUPT end |
.load(private_key) ⇒ Akero
Load an Akero identity.
123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/akero.rb', line 123 def self.load(private_key) inner = Base64.decode64(private_key[PKEY_HEADER.length..private_key.length - PKEY_FOOTER.length]) if inner[0..63] != OpenSSL::Digest::SHA512.new(inner[64..-1]).digest raise ERR_PKEY_CORRUPT end cert_len = inner[64..65].unpack('S')[0] akero = Akero.new(nil) akero.instance_variable_set(:@cert, OpenSSL::X509::Certificate.new(inner[66..66 + cert_len])) akero.instance_variable_set(:@key, OpenSSL::PKey::RSA.new(inner[66 + cert_len..-1])) akero end |
.replate(msg, plates, reverse = false) ⇒ String
Swap the “license plates” on an ascii-armored message. This is done for user-friendliness, so stored Akero messages and keys can be easily identified at a glance.
264 265 266 267 |
# File 'lib/akero.rb', line 264 def self.replate(msg, plates, reverse = false) a, b = reverse ? [1, 0] : [0, 1] "-----BEGIN #{plates[b]}-----#{msg.strip[plates[a].length + 16..-(plates[a].length + 15)]}-----END #{plates[b]}-----\n" end |
Instance Method Details
#encrypt(to, plaintext, ascii_armor = true) ⇒ String
Sign->encrypt->sign a message for 1 or more recipients.
Only the listed recipients can decrypt the message-body but anyone can extract the sender’s public key.
197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 |
# File 'lib/akero.rb', line 197 def encrypt(to, plaintext, ascii_armor = true) to = [to] unless to.is_a? Array to = to.map do |e| case e when String begin OpenSSL::X509::Certificate.new(Akero.replate(e, Akero::PLATE_CERT, true)) rescue OpenSSL::X509::CertificateError raise ERR_INVALID_RECIPIENT_CERT end else raise ERR_INVALID_RECIPIENT end end out = _sign(_encrypt(to, _sign(plaintext, false))) ascii_armor ? Akero.replate(out.to_s, PLATE_CRYPTED) : out.to_der end |
#id ⇒ String
Unique fingerprint of this Akero keypair.
94 95 96 |
# File 'lib/akero.rb', line 94 def id Akero.fingerprint_from_cert(@cert) end |
#private_key ⇒ String
Private key (do not share this with anyone!)
156 157 158 159 160 161 162 163 164 165 |
# File 'lib/akero.rb', line 156 def private_key # We do not use PKCS#12 ("PFX") for serialization here # because of http://www.cs.auckland.ac.nz/~pgut001/pubs/pfx.html cert_der = @cert.to_der out = [cert_der.length].pack('S') out << cert_der out << @key.to_der out.insert(0, OpenSSL::Digest::SHA512.new(out).digest) PKEY_HEADER + Base64.encode64(out) + PKEY_FOOTER end |
#public_key ⇒ String
Akero public key.
Share this with other Akero instances that you wish to receive encrypted messages from.
141 142 143 |
# File 'lib/akero.rb', line 141 def public_key Akero.replate(@cert.to_s, Akero::PLATE_CERT) end |
#receive(ciphertext) ⇒ Akero::Message
Receive an Akero message.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 |
# File 'lib/akero.rb', line 219 def receive(ciphertext) if ciphertext.start_with? '-----BEGIN ' ciphertext = Akero.replate(ciphertext, Akero::PLATE_CRYPTED, true) end begin body, signer_cert, body_type = verify(ciphertext, nil) rescue ArgumentError raise ERR_MSG_MALFORMED_ENV end case body_type.ord when 0x00 # public message (signed) return Message.new(body, signer_cert, :signed) when 0x01 # private message (signed, crypted, signed) signed_plaintext = _decrypt(body) plaintext, _verified_cert, _body_type = verify(signed_plaintext, signer_cert) msg = Message.new(plaintext, signer_cert, :encrypted) return msg end raise ERR_MSG_MALFORMED_BODY end |