class Lowdown::Certificate

This class is a wrapper around a certificate/key pair that returns values used by Lowdown.

Constants

DEVELOPMENT_ENV_EXTENSION

images.apple.com/certificateauthority/pdf/Apple_WWDR_CPS_v1.13.pdf

PRODUCTION_ENV_EXTENSION
UNIVERSAL_CERTIFICATE_EXTENSION

Attributes

certificate[R]

@return [OpenSSL::X509::Certificate]

the Apple Push Notification certificate.
key[R]

@return [OpenSSL::PKey::RSA, nil]

the private key that belongs to the certificate.

Public Class Methods

certificate(certificate_or_data) click to toggle source

@param [Certificate, String] certificate_or_data

a configured Certificate or PEM data to construct a Certificate from.

@return [Certificate]

either the originally passed in Certificate or a new Certificate.
# File lib/lowdown/certificate.rb, line 16
def self.certificate(certificate_or_data)
  if certificate_or_data.is_a?(Certificate)
    certificate_or_data
  else
    from_pem_data(certificate_or_data)
  end
end
from_pem_data(data, passphrase = nil) click to toggle source

A convenience method that initializes a Certificate from PEM data.

@param [String] data

the PEM encoded certificate/key pair data.

@param [String] passphrase

a passphrase required to decrypt the PEM data.

@return (see Certificate#initialize)

# File lib/lowdown/certificate.rb, line 34
def self.from_pem_data(data, passphrase = nil)
  key = OpenSSL::PKey::RSA.new(data, passphrase)
  certificate = OpenSSL::X509::Certificate.new(data)
  new(certificate, key)
end
from_ssl_context(context) click to toggle source

A convenience method that initializes a Certificate with the certificate and key from a SSL context object.

@param [OpenSSL::SSL::SSLContext] context

the context from which to initialize a Certificate.

@return (see Certificate#initialize)

# File lib/lowdown/certificate.rb, line 47
def self.from_ssl_context(context)
  new(context.cert, context.key)
end
new(certificate, key = nil) click to toggle source

@param [OpenSSL::X509::Certificate] certificate

the Apple Push Notification certificate.

@param [OpenSSL::PKey::RSA] key

the private key that belongs to the certificate.
# File lib/lowdown/certificate.rb, line 57
def initialize(certificate, key = nil)
  @key, @certificate = key, certificate
end

Public Instance Methods

==(other) click to toggle source

@return [Boolean]

whether or not this Certificate is equal in contents to another Certificate.
# File lib/lowdown/certificate.rb, line 85
def ==(other)
  other.is_a?(Certificate) && other.to_pem == to_pem
end
app_bundle_id() click to toggle source

@return [String]

the App ID / app’s Bundle ID that this certificate is for.
# File lib/lowdown/certificate.rb, line 140
def app_bundle_id
  @certificate.subject.to_a.find { |key, *_| key == "UID" }[1]
end
development?() click to toggle source

@return [Boolean]

whether or not the certificate supports the development (sandbox) environment (for development builds).
# File lib/lowdown/certificate.rb, line 111
def development?
  !extension(DEVELOPMENT_ENV_EXTENSION).nil?
end
production?() click to toggle source

@return [Boolean]

whether or not the certificate supports the production environment (for Testflight & App Store builds).
# File lib/lowdown/certificate.rb, line 118
def production?
  !extension(PRODUCTION_ENV_EXTENSION).nil?
end
ssl_context() click to toggle source

@return [OpenSSL::SSL::SSLContext]

a SSL context, configured with the certificate/key pair, which is used to connect to the APN service.
# File lib/lowdown/certificate.rb, line 92
def ssl_context
  @ssl_context ||= OpenSSL::SSL::SSLContext.new.tap do |context|
    context.key = @key
    context.cert = @certificate
  end
end
to_pem() click to toggle source

@return [String]

the certificate/key pair encoded as PEM data. Only used for testing.
# File lib/lowdown/certificate.rb, line 78
def to_pem
  [@key, @certificate].compact.map(&:to_pem).join("\n")
end
topics() click to toggle source

@return [Array<String>]

a list of ‘topics’ that the certificate supports.

@see developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/APNsProviderAPI.html

# File lib/lowdown/certificate.rb, line 127
def topics
  if universal?
    ext = extension(UNIVERSAL_CERTIFICATE_EXTENSION)
    seq = OpenSSL::ASN1.decode(OpenSSL::ASN1.decode(ext.to_der).value[1].value)
    seq.select.with_index { |_, index| index.even? }.map(&:value)
  else
    [app_bundle_id]
  end
end
universal?() click to toggle source

@return [Boolean]

whether or not the certificate is a Universal Certificate.

@see developer.apple.com/library/ios/documentation/IDEs/Conceptual/AppDistributionGuide/AddingCapabilities/AddingCapabilities.html#//apple_ref/doc/uid/TP40012582-CH26-SW11

# File lib/lowdown/certificate.rb, line 104
def universal?
  !extension(UNIVERSAL_CERTIFICATE_EXTENSION).nil?
end

Private Instance Methods

extension(oid) click to toggle source
# File lib/lowdown/certificate.rb, line 151
def extension(oid)
  @certificate.extensions.find { |ext| ext.oid == oid }
end