Class: SSHPublicKey
- Inherits:
-
Object
- Object
- SSHPublicKey
- Defined in:
- lib/ssh-publickey.rb,
lib/ssh-publickey/version.rb
Overview
Convert SSH public key from/to RFC4716/OpenSSH format
Defined Under Namespace
Classes: PublicKeyError
Constant Summary collapse
- LINE_BREAK =
Maximum text size in a line for PEM format
70- AUTHORIZED_KEY_REGEX =
Regex for authorized key
/^(?: (?<directives>(?:[!-~]|\s(?=.*"))+) \s+ )? # Options (?<type> [a-z0-9_-]+) \s+ # Type (?<key> [A-Za-z0-9+\/]+=*) # Key (?:\s+ (?<comment>.*?) \s* )? # Comments $/x
- PUBKEY_OPENSSH_REGEX =
Regex for OpenSSH public key Same as authorized keys but without directives
/^ (?<type> [a-z0-9_-]+) \s+ # Type (?<key> [A-Za-z0-9+\/]+=*) # Key (?:\s+ (?<comment>.*?) \s* )? # Comments $/x
- PUBKEY_RFC4716_REGEX =
Regex for RFC4716 public key
/^----\sBEGIN\sSSH2\sPUBLIC\sKEY\s----\R (?<tags> (?:[^:\p{Space}\p{Cntrl}]{1,64} # Tags \s*:\s* (?:[^\\\r\n]*\\\R)* [^\\\r\n]+\R)*) (?<key> (?:[A-Za-z0-9+\/]+\R)* # Key [A-Za-z0-9+\/]+=*\R) ----\sEND\sSSH2\sPUBLIC\sKEY\s---- $/xmu
- PUBKEY_RFC4716_HEADERTAG_REGEX =
:nodoc:
/[^:\p{Space}\p{Cntrl}]{1,64} \s*:\s* (?:[^\\\r\n]*\\\R)*[^\\\r\n]+\R/xmu
- VERSION =
Current version
'0.1'
Class Method Summary collapse
-
.is_openssh?(pubkey) ⇒ Boolean
Test if a public key is in OpenSSH format.
-
.is_rfc4716?(pubkey) ⇒ Boolean
Test if a public key is in RFC4716 format.
-
.openssh_to_rfc4716(pubkey) ⇒ String
Convert a public key in OpenSSH format to RFC4716 format.
-
.rfc4716_to_openssh(pubkey) ⇒ String
Convert a public key in RFC4716 format to OpenSSH format.
Class Method Details
.is_openssh?(pubkey) ⇒ Boolean
Test if a public key is in OpenSSH format
117 118 119 |
# File 'lib/ssh-publickey.rb', line 117 def self.is_openssh?(pubkey) PUBKEY_RFC4716_REGEX.match?(pubkey) end |
.is_rfc4716?(pubkey) ⇒ Boolean
Test if a public key is in RFC4716 format
128 129 130 |
# File 'lib/ssh-publickey.rb', line 128 def self.is_rfc4716?(pubkey) PUBKEY_RFC4716_REGEX.match?(pubkey) end |
.openssh_to_rfc4716(pubkey) ⇒ String
Convert a public key in OpenSSH format to RFC4716 format
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 |
# File 'lib/ssh-publickey.rb', line 58 def self.openssh_to_rfc4716(pubkey) unless m = AUTHORIZED_KEY_REGEX.match(pubkey) raise PublicKeyError, "invalid OpenSSH public key" end # Lines are limited to 72 8-bytes char # - limit ourselves to 70 to keep room for \\ and \n # - comment part can be unicode so 1 char can be more that 1 byte linesize = 0 comment = "Comment: #{m[:comment]}" .each_char.slice_before {|c| bytesize = c.bytes.size if linesize + bytesize > LINE_BREAK then linesize = 0 ; true else linesize += bytesize ; false end }.map(&:join).join("\\\n") key = m[:key].scan(/.{1,70}/).join("\n") reskey = [] reskey << "---- BEGIN SSH2 PUBLIC KEY ----" reskey << comment reskey << key reskey << "---- END SSH2 PUBLIC KEY ----" reskey.join("\n") end |
.rfc4716_to_openssh(pubkey) ⇒ String
Convert a public key in RFC4716 format to OpenSSH format
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/ssh-publickey.rb', line 92 def self.rfc4716_to_openssh(pubkey) unless m = PUBKEY_RFC4716_REGEX.match(pubkey) raise PublicKeyError, "invalid RFC4716 public key" end key = m[:key].gsub(/\R/, '') keydata = m[:key].unpack1('m') len = keydata.unpack1('N') type = keydata[4,len] = Hash[m[:tags].scan(PUBKEY_RFC4716_HEADERTAG_REGEX) .map {|tag| tag.gsub(/\\\R/, '').strip } .map {|tag| tag.split(/\s*:\s*/, 2) }] comment = .transform_keys {|k| k.downcase }['comment'] directives = nil [directives, type, key, comment ].compact.join(' ') end |