Class: SecureConf::OpenSSH::PKey

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

Instance Method Summary collapse

Constructor Details

#initialize(source) ⇒ PKey

Returns a new instance of PKey.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/secure_conf/openssh.rb', line 10

def initialize(source)
  if String===source
    # pem string
    @h = parse_pem(source)

  elsif IO===source || source.respond_to?(:read)
    # pem io
    source = source.read
    @h = parse_pem(source)

  elsif source.respond_to?(:to_der)
    # call to_der method
    der = source.to_der
    @h = parse_der(der)

  else
    # other
    raise ArgumentError, "unsupported argument type: #{source.class.name}"
  end
end

Instance Method Details

#keytypeObject



159
160
161
# File 'lib/secure_conf/openssh.rb', line 159

def keytype
  Keytype.fetch(@h[:privatekey][:keytype])
end

#parse_der(der) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/secure_conf/openssh.rb', line 44

def parse_der(der)
  bio = StringIO.new(der, "rb")
  h = {}

  # header
  h[:header] = bio.read(15)
  if h[:header]!="openssh-key-v1\0"
    raise FormatError, "openssh header not found"
  end

  # ciphername
  length = bio.read(4).unpack("N")[0]
  h[:ciphername] = bio.read(length)
  if h[:ciphername]!="none"
    raise FormatError, "ciphername is not 'none': #{h[:ciphername]}"
  end

  # kdfname
  length = bio.read(4).unpack("N")[0]
  h[:kdfname] = bio.read(length)
  if h[:kdfname]!="none"
    raise FormatError, "kdfname is not 'none': #{h[:kdfname]}"
  end

  # kdf
  length = bio.read(4).unpack("N")[0]
  h[:kdf] = bio.read(length)
  if h[:kdf]!=""
    raise FormatError, "kdf is not empty: #{h[:kdfname]}"
  end

  # number of keys
  h[:keys_num] = bio.read(4).unpack("N")[0]
  if h[:keys_num]!=1
    raise FormatError, "number of keys is not 1: #{h[:keys_num]}"
  end

  # public key
  length = bio.read(4).unpack("N")[0]
  publickey = bio.read(length)
  h[:publickey] = parse_der_publickey(publickey)

  # rnd+prv+comment+pad
  length = bio.read(4).unpack("N")[0]
  privatekey = bio.read(length)
  h[:privatekey] = parse_der_privatekey(privatekey)

  # check eof
  if !bio.eof?
    raise FormatError, "no eof"
  end

  h
end

#parse_der_privatekey(privatekey) ⇒ Object



126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/secure_conf/openssh.rb', line 126

def parse_der_privatekey(privatekey)
  bio = StringIO.new(privatekey, "rb")
  h = {}

  # checksum
  h[:checksum] = bio.read(8).unpack("NN")

  # keytype
  length = bio.read(4).unpack("N")[0]
  h[:keytype] = bio.read(length)

  # content
  kt = Keytype.fetch(h[:keytype])
  if !kt
    raise UnsupportedError, "unsupported keytype: #{h[:keytype]}"
  end
  kt.parse_der_private_key_contents(h, bio)

  # comment
  length = bio.read(4).unpack("N")[0]
  h[:comment] = bio.read(length)

  # padding
  h[:padding] = bio.read

  # check eof
  if !bio.eof?
    raise FormatError, "privatekey no eof"
  end

  h
end

#parse_der_publickey(publickey) ⇒ Object



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/secure_conf/openssh.rb', line 101

def parse_der_publickey(publickey)
  bio = StringIO.new(publickey, "rb")
  h = {}

  # keytype
  length = bio.read(4).unpack("N")[0]
  h[:keytype] = bio.read(length)

  # content
  kt = Keytype.fetch(h[:keytype])
  if !kt
    raise UnsupportedError, "unsupported keytype: #{h[:keytype]}"
  end
  kt.parse_der_public_key_contents(h, bio)

  # check eof
  if !bio.eof?
    raise FormatError, "publickey no eof"
  end

  h
end

#parse_pem(pem) ⇒ Object



31
32
33
34
35
36
37
38
39
40
# File 'lib/secure_conf/openssh.rb', line 31

def parse_pem(pem)
  pem = pem.strip
  if !pem.start_with?("-----BEGIN OPENSSH PRIVATE KEY-----") || !pem.end_with?("-----END OPENSSH PRIVATE KEY-----")
    raise FormatError, "invalid pem string"
  end

  pem = pem.gsub(/-----(?:BEGIN|END) OPENSSH PRIVATE KEY-----/, "").gsub(/[\r\n]/, "")
  der = Base64::strict_decode64(pem)
  parse_der(der)
end

#to_opensslObject



163
164
165
# File 'lib/secure_conf/openssh.rb', line 163

def to_openssl
  keytype.to_openssl(@h)
end

#to_openssl_derObject



171
172
173
# File 'lib/secure_conf/openssh.rb', line 171

def to_openssl_der
  keytype.to_openssl_der(@h)
end

#to_openssl_pemObject



167
168
169
# File 'lib/secure_conf/openssh.rb', line 167

def to_openssl_pem
  keytype.to_openssl_pem(@h)
end