πŸ’Ž
Ruby
A Ruby implementation of EIP-4361: Sign In With Ethereum.

Getting started

  • The Ruby implementation of Sign-In with Ethereum can be found here:
GitHub - spruceid/siwe-ruby: A ruby implementation of Sign-In with Ethereum
GitHub
Sign-In with Ethereum can be found on RubyGems. For more information and package information, click here​

Installation

Dependencies

Additional packages may be required to install the gem:
macOS
Linux
1
brew install automake openssl libtool pkg-config gmp libffi
Copied!
1
sudo apt-get install build-essential automake pkg-config libtool \
2
libffi-dev libssl-dev libgmp-dev python-dev
Copied!
After installing any required dependencies SIWE can be easily installed with:
1
gem install siwe
Copied!

Usage

SIWE provides a Message class which implements EIP-4361.

Creating a SIWE Message

1
require 'siwe'
2
require 'time'
3
​
4
# Only the mandatory arguments
5
Siwe::Message.new("domain.example", "0x9D85ca56217D2bb651b00f15e694EB7E713637D4", "some.uri", "1")
6
​
7
# Complete SIWE message with default values
8
Siwe::Message.new("domain.example", "0x9D85ca56217D2bb651b00f15e694EB7E713637D4", "some.uri", "1", {
9
issued_at: Time.now.utc.iso8601,
10
statement: "Example statement for SIWE",
11
nonce: Siwe::Util.generate_nonce,
12
chain_id: "1",
13
expiration_time: "",
14
not_before: "",
15
request_id: "",
16
resources: []
17
})
18
​
Copied!

Parsing a SIWE Message

From EIP-4361
From JSON string
To parse from EIP-4361 you have to use Siwe::Message.from_message
1
require 'siwe'
2
​
3
Siwe::Message.from_message "domain.example wants you to sign in with your Ethereum account:\n0x9D85ca56217D2bb651b00f15e694EB7E713637D4\n\nExample statement for SIWE\n\nURI: some.uri\nVersion: 1\nChain ID: 1\nNonce: k1Ne4KWzBHYEFQo8\nIssued At: 2022-02-03T20:06:19Z"
Copied!
Messages can be parsed to and from JSON strings, using Siwe::Message.from_json_string and Siwe::Message.to_json_string respectively:
1
require 'siwe'
2
​
3
Siwe::Message.from_json_string "{\"domain\":\"domain.example\",\"address\":\"0x9D85ca56217D2bb651b00f15e694EB7E713637D4\",\"uri\":\"some.uri\",\"version\":\"1\",\"chain_id\":\"1\",\"nonce\":\"k1Ne4KWzBHYEFQo8\",\"issued_at\":\"2022-02-03T20:06:19Z\",\"statement\":\"Example statement for SIWE\",\"expiration_time\":\"\",\"not_before\":\"\",\"request_id\":\"\",\"resources\":[]}"
4
​
5
Siwe::Message.new("domain.example", "0x9D85ca56217D2bb651b00f15e694EB7E713637D4", "some.uri", "1").to_json_string
Copied!

Verifying and Authenticating a SIWE Message

Verification and authentication is performed via EIP-191, using the address field of the SiweMessage as the expected signer. The validate method checks message structural integrity, signature address validity, and time-based validity attributes.
1
begin
2
message.validate(signature) # returns true if valid throws otherwise
3
rescue Siwe::ExpiredMessage
4
# Used when the message is already expired. (Expires At < Time.now)
5
rescue Siwe::NotValidMessage
6
# Used when the message is not yet valid. (Not Before > Time.now)
7
rescue Siwe::InvalidSignature
8
# Used when the signature doesn't correspond to the address of the message.
9
end
Copied!

Serialization of a SIWE Message

Siwe::Message instances can also be serialized as their EIP-4361 string representations via the Siwe::Message.prepare_message method:
1
require 'siwe'
2
​
3
Siwe::Message.new("domain.example", "0x9D85ca56217D2bb651b00f15e694EB7E713637D4", "some.uri", "1").prepare_message
Copied!

Example

Parsing and verifying a Siwe::Message:
1
require 'siwe'
2
​
3
begin
4
message = Siwe::Message.from_message "https://example.com wants you to sign in with your Ethereum account:\n0xA712a0AFBFA8656581BfA96352c9EdFc519e9cad\n\n\nURI: https://example.com\nVersion: 1\nChain ID: 1\nNonce: 9WrH24z8zpiYOoBQ\nIssued At: 2022-02-04T15:52:03Z"
5
message.validate "aca5e5649a357cee608ecbd1a8455b4143311381636b88a66ec7bcaf64b3a4743ff2c7cc18501a3401e182f79233dc73fc56d01506a6098d5e7e4d881bbb02921c"
6
puts "Congrats, your message is valid"
7
rescue Siwe::ExpiredMessage
8
# Used when the message is already expired. (Expires At < Time.now)
9
rescue Siwe::NotValidMessage
10
# Used when the message is not yet valid. (Not Before > Time.now)
11
rescue Siwe::InvalidSignature
12
# Used when the signature doesn't correspond to the address of the message.
13
end
Copied!
​