Class: Nostr::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/signer.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(private_key:) ⇒ Signer

Returns a new instance of Signer.



7
8
9
10
11
12
# File 'lib/signer.rb', line 7

def initialize(private_key:)
  @private_key = private_key
  unless @public_key
    @public_key = Nostr::Key::get_public_key(@private_key)
  end
end

Instance Attribute Details

#private_keyObject (readonly)

Returns the value of attribute private_key.



4
5
6
# File 'lib/signer.rb', line 4

def private_key
  @private_key
end

#public_keyObject (readonly)

Returns the value of attribute public_key.



5
6
7
# File 'lib/signer.rb', line 5

def public_key
  @public_key
end

Instance Method Details

#decrypt(event) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/signer.rb', line 64

def decrypt(event)
  case event.kind
  when Nostr::Kind::DIRECT_MESSAGE
    data = event.content.split('?iv=')[0]
    iv = event.content.split('?iv=')[1]
    dm_recipient = event.tags.select{|t| t[0] == "p"}.first[1]
    event.content = CryptoTools.aes_256_cbc_decrypt(@private_key, dm_recipient, data, iv)
    event
  else
    raise "Unable to decrypt a kind #{event.kind} event"
  end
end

#generate_delegation_tag(to:, conditions:) ⇒ Object



77
78
79
80
81
82
83
84
85
86
# File 'lib/signer.rb', line 77

def generate_delegation_tag(to:, conditions:)
  delegation_message_sha256 = Digest::SHA256.hexdigest("nostr:delegation:#{to}:#{conditions}")
  signature = Schnorr.sign(Array(delegation_message_sha256).pack('H*'), Array(@private_key).pack('H*')).encode.unpack('H*')[0]
  [
    "delegation",
    @public_key,
    conditions,
    signature
  ]
end

#npubObject



18
19
20
# File 'lib/signer.rb', line 18

def npub
  Nostr::Bech32.encode_npub(@public_key)
end

#nsecObject



14
15
16
# File 'lib/signer.rb', line 14

def nsec
  Nostr::Bech32.encode_nsec(@private_key)
end

#sign(event) ⇒ Object

Raises:

  • (ArgumentError)


22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/signer.rb', line 22

def sign(event)

  raise ArgumentError, "Event is not signable" unless event.signable?

  event.pubkey = @public_key if event.pubkey.nil? || event.pubkey.empty?

  raise ArgumentError, "Pubkey doesn't match the private key" unless event.pubkey == @public_key

  if event.kind == Nostr::Kind::DIRECT_MESSAGE
    dm_recipient = event.tags.select{|t| t[0] == "p"}.first[1]
    event.content = CryptoTools.aes_256_cbc_encrypt(@private_key, dm_recipient, event.content)
  end

  if event.delegation
    event.tags << event.delegation
  end

  event_sha256_digest = nil
  if event.pow
    nonce = 1
    loop do
      nonce_tag = ['nonce', nonce.to_s, event.pow.to_s]
      nonced_serialized_event = event.serialize.clone
      nonced_serialized_event[4] = nonced_serialized_event[4] + [nonce_tag]
      event_sha256_digest = Digest::SHA256.hexdigest(JSON.dump(nonced_serialized_event))
      if Nostr::Event.match_pow_difficulty?(event_sha256_digest, event.pow)
        event.tags << nonce_tag
        break
      end
      nonce += 1
    end
  else
    event_sha256_digest = Digest::SHA256.hexdigest(JSON.dump(event.serialize))
  end

  event.id = event_sha256_digest
  binary_private_key = Array(@private_key).pack('H*')
  binary_message = Array(event.id).pack('H*')
  event.sig = Schnorr.sign(binary_message, binary_private_key).encode.unpack('H*')[0]
  event
end