Class: SSHData::PublicKey::DSA

Inherits:
Base
  • Object
show all
Defined in:
lib/ssh_data/public_key/dsa.rb

Instance Attribute Summary collapse

Attributes inherited from Base

#algo

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

#fingerprint, #openssh, #sign

Constructor Details

#initialize(algo:, p:, q:, g:, y:) ⇒ DSA

Returns a new instance of DSA.



52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/ssh_data/public_key/dsa.rb', line 52

def initialize(algo:, p:, q:, g:, y:)
  unless algo == ALGO_DSA
    raise DecodeError, "bad algorithm: #{algo.inspect}"
  end

  @p = p
  @q = q
  @g = g
  @y = y

  @openssl = OpenSSL::PKey::DSA.new(asn1.to_der)

  super(algo: algo)
end

Instance Attribute Details

#gObject (readonly)

Returns the value of attribute g.



4
5
6
# File 'lib/ssh_data/public_key/dsa.rb', line 4

def g
  @g
end

#opensslObject (readonly)

Returns the value of attribute openssl.



4
5
6
# File 'lib/ssh_data/public_key/dsa.rb', line 4

def openssl
  @openssl
end

#pObject (readonly)

Returns the value of attribute p.



4
5
6
# File 'lib/ssh_data/public_key/dsa.rb', line 4

def p
  @p
end

#qObject (readonly)

Returns the value of attribute q.



4
5
6
# File 'lib/ssh_data/public_key/dsa.rb', line 4

def q
  @q
end

#yObject (readonly)

Returns the value of attribute y.



4
5
6
# File 'lib/ssh_data/public_key/dsa.rb', line 4

def y
  @y
end

Class Method Details

.openssl_signature(sig) ⇒ Object

Convert an SSH encoded DSA signature to DER encoding for verification with OpenSSL.

sig - A binary String signature from an SSH packet.

Returns a binary String signature, as expected by OpenSSL.



12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/ssh_data/public_key/dsa.rb', line 12

def self.openssl_signature(sig)
  if sig.bytesize != 40
    raise DecodeError, "bad DSA signature size"
  end

  r = OpenSSL::BN.new(sig.byteslice(0, 20), 2)
  s = OpenSSL::BN.new(sig.byteslice(20, 20), 2)

  OpenSSL::ASN1::Sequence.new([
    OpenSSL::ASN1::Integer.new(r),
    OpenSSL::ASN1::Integer.new(s)
  ]).to_der
end

.ssh_signature(sig) ⇒ Object

Convert an DER encoded DSA signature, as generated by OpenSSL to SSH encoding.

sig - A binary String signature, as generated by OpenSSL.

Returns a binary String signature, as found in an SSH packet.



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/ssh_data/public_key/dsa.rb', line 32

def self.ssh_signature(sig)
  a1 = OpenSSL::ASN1.decode(sig)
  if a1.tag_class != :UNIVERSAL || a1.tag != OpenSSL::ASN1::SEQUENCE || a1.value.count != 2
    raise DecodeError, "bad asn1 signature"
  end

  r, s = a1.value
  if r.tag_class != :UNIVERSAL || r.tag != OpenSSL::ASN1::INTEGER || s.tag_class != :UNIVERSAL || s.tag != OpenSSL::ASN1::INTEGER
    raise DecodeError, "bad asn1 signature"
  end

  # left pad big endian representations to 20 bytes and concatenate
  [
    "\x00" * (20 - r.value.num_bytes),
    r.value.to_s(2),
    "\x00" * (20 - s.value.num_bytes),
    s.value.to_s(2)
  ].join
end

Instance Method Details

#==(other) ⇒ Object

Is this public key equal to another public key?

other - Another SSHData::PublicKey::Base instance to compare with.

Returns boolean.



101
102
103
# File 'lib/ssh_data/public_key/dsa.rb', line 101

def ==(other)
  super && other.p == p && other.q == q && other.g == g && other.y == y
end

#rfc4253Object

RFC4253 binary encoding of the public key.

Returns a binary String.



86
87
88
89
90
91
92
93
94
# File 'lib/ssh_data/public_key/dsa.rb', line 86

def rfc4253
  Encoding.encode_fields(
    [:string, algo],
    [:mpint, p],
    [:mpint, q],
    [:mpint, g],
    [:mpint, y],
  )
end

#verify(signed_data, signature) ⇒ Object

Verify an SSH signature.

signed_data - The String message that the signature was calculated over. signature - The binary String signature with SSH encoding.

Returns boolean.



73
74
75
76
77
78
79
80
81
# File 'lib/ssh_data/public_key/dsa.rb', line 73

def verify(signed_data, signature)
  sig_algo, ssh_sig, _ = Encoding.decode_signature(signature)
  if sig_algo != ALGO_DSA
    raise DecodeError, "bad signature algorithm: #{sig_algo.inspect}"
  end

  openssl_sig = self.class.openssl_signature(ssh_sig)
  openssl.verify(OpenSSL::Digest::SHA1.new, openssl_sig, signed_data)
end