-
-
Notifications
You must be signed in to change notification settings - Fork 569
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
626140b
commit d985988
Showing
9 changed files
with
161 additions
and
120 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
# frozen_string_literal: true | ||
|
||
module RubySaml | ||
# Formats PEM-encoded X.509 certificates and private keys to | ||
# canonical PEM format with 64-char lines and BEGIN/END headers. | ||
# | ||
# @api private | ||
module PemFormatter | ||
extend self | ||
|
||
# Formats one or many X.509 certificate(s) to canonical | ||
# PEM format with 64-char lines and BEGIN/END headers. | ||
# | ||
# @param cert [String] The original certificate(s) | ||
# @param multi [true|false] Whether to return multiple keys delimited by newline | ||
# @return [String|nil] The formatted certificate(s) | ||
def format_cert(cert, multi: false) | ||
detect_pems(cert, 'CERTIFICATE', multi: multi) do |pem| | ||
format_cert_single(pem) | ||
end | ||
end | ||
|
||
# Formats one or many private key(s) to canonical PEM format | ||
# with 64-char lines and BEGIN/END headers. | ||
# | ||
# @param key [String] The original private key(s) | ||
# @param multi [true|false] Whether to return multiple keys delimited by newline | ||
# @return [String|nil] The formatted private key(s) | ||
def format_private_key(key, multi: false) | ||
detect_pems(key, '(?:RSA|DSA|EC|ECDSA) PRIVATE KEY', multi: multi) do |pem| | ||
format_private_key_single(pem) | ||
end | ||
end | ||
|
||
private | ||
|
||
def detect_pems(str, label, multi: false, &block) | ||
return if str.nil? || str.empty? | ||
return str unless str.ascii_only? | ||
return if str.match?(/\A\s*\z/) | ||
|
||
pems = str.scan(/-{5}\s*BEGIN #{label}\s*-{5}.*?-{5}\s*END #{label}\s*-{5}?/m).map(&block) | ||
|
||
# Try to format the original string if no pems were found | ||
return yield(str) if pems.empty? | ||
|
||
multi ? pems.join("\n") : pems.first | ||
end | ||
|
||
def format_cert_single(cert) | ||
format_pem(cert, 'CERTIFICATE') | ||
end | ||
|
||
def format_private_key_single(key) | ||
algo = key.match(/((?:RSA|ECDSA|EC|DSA) )PRIVATE KEY/)&.[](1) | ||
label = "#{algo}PRIVATE KEY" | ||
format_pem(key, label) | ||
end | ||
|
||
# Strips all whitespace and the BEGIN/END lines, | ||
# then splits the string into 64-character lines, | ||
# and re-applies BEGIN/END labels | ||
def format_pem(str, label) | ||
str = str.gsub(/\s|-{5}\s*(BEGIN|END) [A-Z\d\s]+-{5}/, '').scan(/.{1,64}/).join("\n") | ||
"-----BEGIN #{label}-----\n#{str}\n-----END #{label}-----" | ||
end | ||
end | ||
end |
Oops, something went wrong.