Module: Pray::SshAgent
- Defined in:
- lib/pray/ssh_agent.rb
Class Method Summary collapse
- .parse_ssh_ed25519_public_key(public_key) ⇒ Object
- .parse_ssh_signature_blob(signature_blob) ⇒ Object
- .read_ssh_message(stream) ⇒ Object
- .read_ssh_string!(cursor) ⇒ Object
- .read_ssh_string_bytes(buffer) ⇒ Object
- .sign(public_key, message) ⇒ Object
- .write_ssh_message(stream, message_type, payload) ⇒ Object
- .write_ssh_string(buffer, bytes) ⇒ Object
- .write_u32(buffer, value) ⇒ Object
Class Method Details
.parse_ssh_ed25519_public_key(public_key) ⇒ Object
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 |
# File 'lib/pray/ssh_agent.rb', line 36 def parse_ssh_ed25519_public_key(public_key) fields = public_key.split(/\s+/) algorithm = fields[0] raise Error.unsupported("public key must include an algorithm") unless algorithm unless algorithm == "ssh-ed25519" raise Error.unsupported("unsupported public key algorithm: #{algorithm}") end key_value = fields[1] raise Error.unsupported("public key must include key bytes") unless key_value blob = Base64.decode64(key_value) cursor = blob.b blob_algorithm = read_ssh_string!(cursor) unless blob_algorithm == "ssh-ed25519" raise Error.parse("public key", "ed25519 public key blob must start with ssh-ed25519") end key_bytes = read_ssh_string!(cursor) unless key_bytes.bytesize == 32 raise Error.parse("public key", "ed25519 public key must be 32 bytes") end key_bytes end |
.parse_ssh_signature_blob(signature_blob) ⇒ Object
62 63 64 65 66 67 68 69 70 |
# File 'lib/pray/ssh_agent.rb', line 62 def parse_ssh_signature_blob(signature_blob) cursor = signature_blob.b algorithm = read_ssh_string!(cursor) unless algorithm == "ssh-ed25519" raise Error.unsupported("unsupported ssh signature algorithm: #{algorithm}") end Base64.strict_encode64(read_ssh_string!(cursor)) end |
.read_ssh_message(stream) ⇒ Object
78 79 80 81 82 83 84 85 86 |
# File 'lib/pray/ssh_agent.rb', line 78 def (stream) length = stream.read(4)&.unpack1("N") raise Error.resolution("empty ssh agent response") unless length buffer = stream.read(length) raise Error.resolution("truncated ssh agent response") if buffer.nil? || buffer.bytesize < 1 [buffer.getbyte(0), buffer.byteslice(1, buffer.bytesize - 1).to_s] end |
.read_ssh_string!(cursor) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/pray/ssh_agent.rb', line 98 def read_ssh_string!(cursor) raise Error.resolution("truncated ssh agent response") if cursor.bytesize < 4 length = cursor.byteslice(0, 4).unpack1("N") cursor.slice!(0, 4) raise Error.resolution("truncated ssh agent response") if cursor.bytesize < length value = cursor.byteslice(0, length) cursor.slice!(0, length) value end |
.read_ssh_string_bytes(buffer) ⇒ Object
110 111 112 113 |
# File 'lib/pray/ssh_agent.rb', line 110 def read_ssh_string_bytes(buffer) cursor = buffer.b read_ssh_string!(cursor) end |
.sign(public_key, message) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/pray/ssh_agent.rb', line 10 def sign(public_key, ) agent_socket = ENV["SSH_AUTH_SOCK"] raise Error.unsupported("SSH_AUTH_SOCK is not set") if agent_socket.to_s.empty? raw_key_bytes = parse_ssh_ed25519_public_key(public_key) public_key_blob = +"" write_ssh_string(public_key_blob, "ssh-ed25519") write_ssh_string(public_key_blob, raw_key_bytes) payload = +"" write_ssh_string(payload, public_key_blob) write_ssh_string(payload, ) write_u32(payload, 0) UNIXSocket.open(agent_socket) do |stream| (stream, 13, payload) , response = (stream) unless == 14 raise Error.resolution("ssh agent returned unexpected message type: #{}") end signature_blob = read_ssh_string_bytes(response) parse_ssh_signature_blob(signature_blob) end end |
.write_ssh_message(stream, message_type, payload) ⇒ Object
72 73 74 75 76 |
# File 'lib/pray/ssh_agent.rb', line 72 def (stream, , payload) buffer = .chr + payload stream.write([buffer.bytesize].pack("N")) stream.write(buffer) end |
.write_ssh_string(buffer, bytes) ⇒ Object
88 89 90 91 92 |
# File 'lib/pray/ssh_agent.rb', line 88 def write_ssh_string(buffer, bytes) bytes = bytes.b buffer << [bytes.bytesize].pack("N") buffer << bytes end |
.write_u32(buffer, value) ⇒ Object
94 95 96 |
# File 'lib/pray/ssh_agent.rb', line 94 def write_u32(buffer, value) buffer << [value].pack("N") end |