Extract event signing into its own class
This commit is contained in:
48
lib/nostr/crypto.rb
Normal file
48
lib/nostr/crypto.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Nostr
|
||||
# Performs cryptographic operations on a +Nostr::Event+.
|
||||
class Crypto
|
||||
# Uses the private key to generate an event id and sign the event
|
||||
#
|
||||
# @api public
|
||||
#
|
||||
# @example Signing an event
|
||||
# crypto = Nostr::Crypto.new
|
||||
# crypto.sign(event, private_key)
|
||||
# event.id # => an id
|
||||
# event.sig # => a signature
|
||||
#
|
||||
# @param event [Event] The event to be signed
|
||||
# @param private_key [String] 32-bytes hex-encoded private key.
|
||||
#
|
||||
# @return [Event] An unsigned event.
|
||||
#
|
||||
def sign_event(event, private_key)
|
||||
event_digest = hash_event(event)
|
||||
|
||||
hex_private_key = Array(private_key).pack('H*')
|
||||
hex_message = Array(event_digest).pack('H*')
|
||||
event_signature = Schnorr.sign(hex_message, hex_private_key).encode.unpack1('H*')
|
||||
|
||||
event.id = event_digest
|
||||
event.sig = event_signature
|
||||
|
||||
event
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Generates a SHA256 hash of a +Nostr::Event+
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# @param event [Event] The event to be hashed
|
||||
#
|
||||
# @return [String] A SHA256 digest of the event
|
||||
#
|
||||
def hash_event(event)
|
||||
Digest::SHA256.hexdigest(JSON.dump(event.serialize))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -70,9 +70,13 @@ module Nostr
|
||||
# @example Getting the event id
|
||||
# event.id # => 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460'
|
||||
#
|
||||
# @example Setting the event id
|
||||
# event.id = 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460'
|
||||
# event.id # => 'ccf9fdf3e1466d7c20969c71ec98defcf5f54aee088513e1b73ccb7bd770d460'
|
||||
#
|
||||
# @return [String|nil]
|
||||
#
|
||||
attr_reader :id
|
||||
attr_accessor :id
|
||||
|
||||
# 64-bytes signature of the sha256 hash of the serialized event data, which is
|
||||
# the same as the "id" field
|
||||
@@ -82,9 +86,13 @@ module Nostr
|
||||
# @example Getting the event signature
|
||||
# event.sig # => ''
|
||||
#
|
||||
# @example Setting the event signature
|
||||
# event.sig = '058613f8d34c053294cc28b7f9e1f8f0e80fd1ac94fb20f2da6ca514e7360b39'
|
||||
# event.sig # => '058613f8d34c053294cc28b7f9e1f8f0e80fd1ac94fb20f2da6ca514e7360b39'
|
||||
#
|
||||
# @return [String|nil]
|
||||
#
|
||||
attr_reader :sig
|
||||
attr_accessor :sig
|
||||
|
||||
# Instantiates a new Event
|
||||
#
|
||||
@@ -130,6 +138,22 @@ module Nostr
|
||||
@content = content
|
||||
end
|
||||
|
||||
# Signs an event with the user's private key
|
||||
#
|
||||
# @api public
|
||||
#
|
||||
# @example Signing an event
|
||||
# event.sign(private_key)
|
||||
#
|
||||
# @param private_key [String] 32-bytes hex-encoded private key.
|
||||
#
|
||||
# @return [Event] A signed event.
|
||||
#
|
||||
def sign(private_key)
|
||||
crypto = Crypto.new
|
||||
crypto.sign_event(self, private_key)
|
||||
end
|
||||
|
||||
# Serializes the event, to obtain a SHA256 digest of it
|
||||
#
|
||||
# @api public
|
||||
|
||||
@@ -57,36 +57,8 @@ module Nostr
|
||||
# @return [Event]
|
||||
#
|
||||
def create_event(event_attributes)
|
||||
event_fragment = EventFragment.new(**event_attributes.merge(pubkey: keypair.public_key))
|
||||
event_sha256 = Digest::SHA256.hexdigest(JSON.dump(event_fragment.serialize))
|
||||
|
||||
signature = sign(event_sha256)
|
||||
|
||||
Event.new(
|
||||
id: event_sha256,
|
||||
pubkey: event_fragment.pubkey,
|
||||
created_at: event_fragment.created_at,
|
||||
kind: event_fragment.kind,
|
||||
tags: event_fragment.tags,
|
||||
content: event_fragment.content,
|
||||
sig: signature
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Signs an event with the user's private key
|
||||
#
|
||||
# @api private
|
||||
#
|
||||
# @param event_sha256 [String] The SHA256 hash of the event.
|
||||
#
|
||||
# @return [String] The signature of the event.
|
||||
#
|
||||
def sign(event_sha256)
|
||||
hex_private_key = Array(keypair.private_key).pack('H*')
|
||||
hex_message = Array(event_sha256).pack('H*')
|
||||
Schnorr.sign(hex_message, hex_private_key).encode.unpack1('H*')
|
||||
event = Event.new(**event_attributes.merge(pubkey: keypair.public_key))
|
||||
event.sign(keypair.private_key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user