diff --git a/build.xml b/build.xml index 361739f2571..b5ba2627a69 100644 --- a/build.xml +++ b/build.xml @@ -378,6 +378,12 @@ + + + + + + @@ -484,7 +490,13 @@ - + + + + + + + @@ -643,7 +655,13 @@ - + + + + + + + diff --git a/build_lib/bcmail-jdk15-146.jar b/build_lib/bcmail-jdk15-146.jar new file mode 100644 index 00000000000..de560b5157b Binary files /dev/null and b/build_lib/bcmail-jdk15-146.jar differ diff --git a/build_lib/bcprov-jdk15-146.jar b/build_lib/bcprov-jdk15-146.jar new file mode 100644 index 00000000000..daa0b54cc0f Binary files /dev/null and b/build_lib/bcprov-jdk15-146.jar differ diff --git a/lib/ruby/1.8/openssl.rb b/lib/ruby/1.8/openssl.rb new file mode 100644 index 00000000000..7e8aa20e4da --- /dev/null +++ b/lib/ruby/1.8/openssl.rb @@ -0,0 +1,25 @@ +=begin += $RCSfile$ -- Loader for all OpenSSL C-space and Ruby-space definitions + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: openssl.rb 12496 2007-06-08 15:02:04Z technorama $ +=end + +require 'jopenssl' +require 'openssl/bn' +require 'openssl/cipher' +require 'openssl/config' +require 'openssl/digest' +require 'openssl/pkcs7' +require 'openssl/ssl' +require 'openssl/x509' + diff --git a/lib/ruby/1.8/openssl/bn.rb b/lib/ruby/1.8/openssl/bn.rb new file mode 100644 index 00000000000..cf44a0943c4 --- /dev/null +++ b/lib/ruby/1.8/openssl/bn.rb @@ -0,0 +1,35 @@ +=begin += $RCSfile$ -- Ruby-space definitions that completes C-space funcs for BN + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: bn.rb 11708 2007-02-12 23:01:19Z shyouhei $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + class BN + include Comparable + end # BN +end # OpenSSL + +## +# Add double dispatch to Integer +# +class Integer + def to_bn + OpenSSL::BN::new(self) + end +end # Integer + diff --git a/lib/ruby/1.8/openssl/buffering.rb b/lib/ruby/1.8/openssl/buffering.rb new file mode 100644 index 00000000000..42c047c7312 --- /dev/null +++ b/lib/ruby/1.8/openssl/buffering.rb @@ -0,0 +1,239 @@ +=begin += $RCSfile$ -- Buffering mix-in module. + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2001 GOTOU YUUZOU + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: buffering.rb 13706 2007-10-15 08:29:08Z usa $ +=end + +module Buffering + include Enumerable + attr_accessor :sync + BLOCK_SIZE = 1024*16 + + def initialize(*args) + @eof = false + @rbuffer = "" + @sync = @io.sync + end + + # + # for reading. + # + private + + def fill_rbuff + begin + @rbuffer << self.sysread(BLOCK_SIZE) + rescue Errno::EAGAIN + retry + rescue EOFError + @eof = true + end + end + + def consume_rbuff(size=nil) + if @rbuffer.empty? + nil + else + size = @rbuffer.size unless size + ret = @rbuffer[0, size] + @rbuffer[0, size] = "" + ret + end + end + + public + + def read(size=nil, buf=nil) + if size == 0 + if buf + buf.clear + else + buf = "" + end + return @eof ? nil : buf + end + until @eof + break if size && size <= @rbuffer.size + fill_rbuff + end + ret = consume_rbuff(size) || "" + if buf + buf.replace(ret) + ret = buf + end + (size && ret.empty?) ? nil : ret + end + + def readpartial(maxlen, buf=nil) + if maxlen == 0 + if buf + buf.clear + else + buf = "" + end + return @eof ? nil : buf + end + if @rbuffer.empty? + begin + return sysread(maxlen, buf) + rescue Errno::EAGAIN + retry + end + end + ret = consume_rbuff(maxlen) + if buf + buf.replace(ret) + ret = buf + end + raise EOFError if ret.empty? + ret + end + + def gets(eol=$/) + idx = @rbuffer.index(eol) + until @eof + break if idx + fill_rbuff + idx = @rbuffer.index(eol) + end + if eol.is_a?(Regexp) + size = idx ? idx+$&.size : nil + else + size = idx ? idx+eol.size : nil + end + consume_rbuff(size) + end + + def each(eol=$/) + while line = self.gets(eol) + yield line + end + end + alias each_line each + + def readlines(eol=$/) + ary = [] + while line = self.gets(eol) + ary << line + end + ary + end + + def readline(eol=$/) + raise EOFError if eof? + gets(eol) + end + + def getc + c = read(1) + c ? c[0] : nil + end + + def each_byte + while c = getc + yield(c) + end + end + + def readchar + raise EOFError if eof? + getc + end + + def ungetc(c) + @rbuffer[0,0] = c.chr + end + + def eof? + fill_rbuff if !@eof && @rbuffer.empty? + @eof && @rbuffer.empty? + end + alias eof eof? + + # + # for writing. + # + private + + def do_write(s) + @wbuffer = "" unless defined? @wbuffer + @wbuffer << s + @sync ||= false + if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) + remain = idx ? idx + $/.size : @wbuffer.length + nwritten = 0 + while remain > 0 + str = @wbuffer[nwritten,remain] + begin + nwrote = syswrite(str) + rescue Errno::EAGAIN + retry + end + remain -= nwrote + nwritten += nwrote + end + @wbuffer[0,nwritten] = "" + end + end + + public + + def write(s) + do_write(s) + s.length + end + + def << (s) + do_write(s) + self + end + + def puts(*args) + s = "" + if args.empty? + s << "\n" + end + args.each{|arg| + s << arg.to_s + if $/ && /\n\z/ !~ s + s << "\n" + end + } + do_write(s) + nil + end + + def print(*args) + s = "" + args.each{ |arg| s << arg.to_s } + do_write(s) + nil + end + + def printf(s, *args) + do_write(s % args) + nil + end + + def flush + osync = @sync + @sync = true + do_write "" + @sync = osync + end + + def close + flush rescue nil + sysclose + end +end diff --git a/lib/ruby/1.8/openssl/cipher.rb b/lib/ruby/1.8/openssl/cipher.rb new file mode 100644 index 00000000000..5fbfcd4005f --- /dev/null +++ b/lib/ruby/1.8/openssl/cipher.rb @@ -0,0 +1,65 @@ +=begin += $RCSfile$ -- Ruby-space predefined Cipher subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: cipher.rb 12496 2007-06-08 15:02:04Z technorama $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + class Cipher + %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name| + klass = Class.new(Cipher){ + define_method(:initialize){|*args| + cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" } + super(cipher_name) + } + } + const_set(name, klass) + } + + %w(128 192 256).each{|keylen| + klass = Class.new(Cipher){ + define_method(:initialize){|mode| + mode ||= "CBC" + cipher_name = "AES-#{keylen}-#{mode}" + super(cipher_name) + } + } + const_set("AES#{keylen}", klass) + } + + # Generate, set, and return a random key. + # You must call cipher.encrypt or cipher.decrypt before calling this method. + def random_key + str = OpenSSL::Random.random_bytes(self.key_len) + self.key = str + return str + end + + # Generate, set, and return a random iv. + # You must call cipher.encrypt or cipher.decrypt before calling this method. + def random_iv + str = OpenSSL::Random.random_bytes(self.iv_len) + self.iv = str + return str + end + + # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future. + class Cipher < Cipher + # add warning + end + end # Cipher +end # OpenSSL diff --git a/lib/ruby/1.8/openssl/config.rb b/lib/ruby/1.8/openssl/config.rb new file mode 100644 index 00000000000..9fc42c623a8 --- /dev/null +++ b/lib/ruby/1.8/openssl/config.rb @@ -0,0 +1,316 @@ +=begin += Ruby-space definitions that completes C-space funcs for Config + += Info + Copyright (C) 2010 Hiroshi Nakamura + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' +require 'stringio' + +module OpenSSL + class Config + include Enumerable + + class << self + def parse(str) + c = new() + parse_config(StringIO.new(str)).each do |section, hash| + c[section] = hash + end + c + end + + alias load new + + def parse_config(io) + begin + parse_config_lines(io) + rescue ConfigError => e + e.message.replace("error in line #{io.lineno}: " + e.message) + raise + end + end + + def get_key_string(data, section, key) # :nodoc: + if v = data[section] && data[section][key] + return v + elsif section == 'ENV' + if v = ENV[key] + return v + end + end + if v = data['default'] && data['default'][key] + return v + end + end + + private + + def parse_config_lines(io) + section = 'default' + data = {section => {}} + while definition = get_definition(io) + definition = clear_comments(definition) + next if definition.empty? + if definition[0] == ?[ + if /\[([^\]]*)\]/ =~ definition + section = $1.strip + data[section] ||= {} + else + raise ConfigError, "missing close square bracket" + end + else + if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition + if $2 + section = $1 + key = $2 + else + key = $1 + end + value = unescape_value(data, section, $3) + (data[section] ||= {})[key] = value.strip + else + raise ConfigError, "missing equal sign" + end + end + end + data + end + + # escape with backslash + QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ + # escape with backslash and doubled dq + QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ + # escaped char map + ESCAPE_MAP = { + "r" => "\r", + "n" => "\n", + "b" => "\b", + "t" => "\t", + } + + def unescape_value(data, section, value) + scanned = [] + while m = value.match(/['"\\$]/) + scanned << m.pre_match + c = m[0] + value = m.post_match + case c + when "'" + if m = value.match(QUOTE_REGEXP_SQ) + scanned << m[1].gsub(/\\(.)/, '\\1') + value = m.post_match + else + break + end + when '"' + if m = value.match(QUOTE_REGEXP_DQ) + scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') + value = m.post_match + else + break + end + when "\\" + c = value.slice!(0, 1) + scanned << (ESCAPE_MAP[c] || c) + when "$" + ref, value = extract_reference(value) + refsec = section + if ref.index('::') + refsec, ref = ref.split('::', 2) + end + if v = get_key_string(data, refsec, ref) + scanned << v + else + raise ConfigError, "variable has no value" + end + else + raise 'must not reaced' + end + end + scanned << value + scanned.join + end + + def extract_reference(value) + rest = '' + if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) + value = m[1] || m[2] + rest = m.post_match + elsif [?(, ?{].include?(value[0]) + raise ConfigError, "no close brace" + end + if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) + return m[0], m.post_match + rest + else + raise + end + end + + def clear_comments(line) + # FCOMMENT + if m = line.match(/\A([\t\n\f ]*);.*\z/) + return m[1] + end + # COMMENT + scanned = [] + while m = line.match(/[#'"\\]/) + scanned << m.pre_match + c = m[0] + line = m.post_match + case c + when '#' + line = nil + break + when "'", '"' + regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ + scanned << c + if m = line.match(regexp) + scanned << m[0] + line = m.post_match + else + scanned << line + line = nil + break + end + when "\\" + scanned << c + scanned << line.slice!(0, 1) + else + raise 'must not reaced' + end + end + scanned << line + scanned.join + end + + def get_definition(io) + if line = get_line(io) + while /[^\\]\\\z/ =~ line + if extra = get_line(io) + line += extra + else + break + end + end + return line.strip + end + end + + def get_line(io) + if line = io.gets + line.gsub(/[\r\n]*/, '') + end + end + end + + def initialize(filename = nil) + @data = {} + if filename + File.open(filename.to_s) do |file| + Config.parse_config(file).each do |section, hash| + self[section] = hash + end + end + end + end + + def get_value(section, key) + if section.nil? + raise TypeError.new('nil not allowed') + end + section = 'default' if section.empty? + get_key_string(section, key) + end + + def value(arg1, arg2 = nil) + warn('Config#value is deprecated; use Config#get_value') + if arg2.nil? + section, key = 'default', arg1 + else + section, key = arg1, arg2 + end + section ||= 'default' + section = 'default' if section.empty? + get_key_string(section, key) + end + + def add_value(section, key, value) + check_modify + (@data[section] ||= {})[key] = value + end + + def [](section) + @data[section] || {} + end + + def section(name) + warn('Config#section is deprecated; use Config#[]') + @data[name] || {} + end + + def []=(section, pairs) + check_modify + @data[section] ||= {} + pairs.each do |key, value| + self.add_value(section, key, value) + end + end + + def sections + @data.keys + end + + def to_s + ary = [] + @data.keys.sort.each do |section| + ary << "[ #{section} ]\n" + @data[section].keys.each do |key| + ary << "#{key}=#{@data[section][key]}\n" + end + ary << "\n" + end + ary.join + end + + def each + @data.each do |section, hash| + hash.each do |key, value| + yield [section, key, value] + end + end + end + + def inspect + "#<#{self.class.name} sections=#{sections.inspect}>" + end + + protected + + def data + @data + end + + private + + def initialize_copy(other) + @data = other.data.dup + end + + def check_modify + raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? + end + + def get_key_string(section, key) + Config.get_key_string(@data, section, key) + end + end +end diff --git a/lib/ruby/1.8/openssl/digest.rb b/lib/ruby/1.8/openssl/digest.rb new file mode 100644 index 00000000000..e64b0cfd373 --- /dev/null +++ b/lib/ruby/1.8/openssl/digest.rb @@ -0,0 +1,61 @@ +=begin += $RCSfile$ -- Ruby-space predefined Digest subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: digest.rb 15600 2008-02-25 08:48:57Z technorama $ +=end + +## +# Should we care what if somebody require this file directly? +#require 'openssl' + +module OpenSSL + class Digest + + alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) + if OPENSSL_VERSION_NUMBER > 0x00908000 + alg += %w(SHA224 SHA256 SHA384 SHA512) + end + + def self.digest(name, data) + super(data, name) + end + + alg.each{|name| + klass = Class.new(Digest){ + define_method(:initialize){|*data| + if data.length > 1 + raise ArgumentError, + "wrong number of arguments (#{data.length} for 1)" + end + super(name, data.first) + } + } + singleton = (class < + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: ssl.rb 16193 2008-04-25 06:51:21Z knu $ +=end + +require "openssl" +require "openssl/buffering" +require "fcntl" + +module OpenSSL + module SSL + class SSLContext + DEFAULT_PARAMS = { + :ssl_version => "SSLv23", + :verify_mode => OpenSSL::SSL::VERIFY_PEER, + :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", + :options => OpenSSL::SSL::OP_ALL, + } + + DEFAULT_CERT_STORE = OpenSSL::X509::Store.new + DEFAULT_CERT_STORE.set_default_paths + if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL) + DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + end + + def set_params(params={}) + params = DEFAULT_PARAMS.merge(params) + self.ssl_version = params.delete(:ssl_version) + params.each{|name, value| self.__send__("#{name}=", value) } + if self.verify_mode != OpenSSL::SSL::VERIFY_NONE + unless self.ca_file or self.ca_path or self.cert_store + self.cert_store = DEFAULT_CERT_STORE + end + end + return params + end + end + + module SocketForwarder + def addr + to_io.addr + end + + def peeraddr + to_io.peeraddr + end + + def setsockopt(level, optname, optval) + to_io.setsockopt(level, optname, optval) + end + + def getsockopt(level, optname) + to_io.getsockopt(level, optname) + end + + def fcntl(*args) + to_io.fcntl(*args) + end + + def closed? + to_io.closed? + end + + def do_not_reverse_lookup=(flag) + to_io.do_not_reverse_lookup = flag + end + end + + module Nonblock + def initialize(*args) + flag = File::NONBLOCK + flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL) + @io.fcntl(Fcntl::F_SETFL, flag) + super + end + end + + def verify_certificate_identity(cert, hostname) + should_verify_common_name = true + cert.extensions.each{|ext| + next if ext.oid != "subjectAltName" + ext.value.split(/,\s+/).each{|general_name| + if /\ADNS:(.*)/ =~ general_name + should_verify_common_name = false + reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + elsif /\AIP Address:(.*)/ =~ general_name + should_verify_common_name = false + return true if $1 == hostname + end + } + } + if should_verify_common_name + cert.subject.to_a.each{|oid, value| + if oid == "CN" + reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + end + } + end + return false + end + module_function :verify_certificate_identity + + class SSLSocket + include Buffering + include SocketForwarder + include Nonblock + + def post_connection_check(hostname) + unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) + raise SSLError, "hostname was not match with the server certificate" + end + return true + end + + def session + SSL::Session.new(self) + rescue SSL::Session::SessionError + nil + end + end + + class SSLServer + include SocketForwarder + attr_accessor :start_immediately + + def initialize(svr, ctx) + @svr = svr + @ctx = ctx + unless ctx.session_id_context + session_id = OpenSSL::Digest::MD5.hexdigest($0) + @ctx.session_id_context = session_id + end + @start_immediately = true + end + + def to_io + @svr + end + + def listen(backlog=5) + @svr.listen(backlog) + end + + def shutdown(how=Socket::SHUT_RDWR) + @svr.shutdown(how) + end + + def accept + sock = @svr.accept + begin + ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx) + ssl.sync_close = true + ssl.accept if @start_immediately + ssl + rescue SSLError => ex + sock.close + raise ex + end + end + + def close + @svr.close + end + end + end +end diff --git a/lib/ruby/1.8/openssl/x509.rb b/lib/ruby/1.8/openssl/x509.rb new file mode 100644 index 00000000000..99f239ce372 --- /dev/null +++ b/lib/ruby/1.8/openssl/x509.rb @@ -0,0 +1,154 @@ +=begin += $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: x509.rb 11708 2007-02-12 23:01:19Z shyouhei $ +=end + +require "openssl" + +module OpenSSL + module X509 + class ExtensionFactory + def create_extension(*arg) + if arg.size > 1 + create_ext(*arg) + else + send("create_ext_from_"+arg[0].class.name.downcase, arg[0]) + end + end + + def create_ext_from_array(ary) + raise ExtensionError, "unexpected array form" if ary.size > 3 + create_ext(ary[0], ary[1], ary[2]) + end + + def create_ext_from_string(str) # "oid = critical, value" + oid, value = str.split(/=/, 2) + oid.strip! + value.strip! + create_ext(oid, value) + end + + def create_ext_from_hash(hash) + create_ext(hash["oid"], hash["value"], hash["critical"]) + end + end + + class Extension + def to_s # "oid = critical, value" + str = self.oid + str << " = " + str << "critical, " if self.critical? + str << self.value.gsub(/\n/, ", ") + end + + def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} + {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?} + end + + def to_a + [ self.oid, self.value, self.critical? ] + end + end + + class Name + module RFC2253DN + Special = ',=+<>#;' + HexChar = /[0-9a-fA-F]/ + HexPair = /#{HexChar}#{HexChar}/ + HexString = /#{HexPair}+/ + Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/ + StringChar = /[^#{Special}\\"]/ + QuoteChar = /[^\\"]/ + AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/ + AttributeValue = / + (?!["#])((?:#{StringChar}|#{Pair})*)| + \#(#{HexString})| + "((?:#{QuoteChar}|#{Pair})*)" + /x + TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/ + + module_function + + def expand_pair(str) + return nil unless str + return str.gsub(Pair){|pair| + case pair.size + when 2 then pair[1,1] + when 3 then Integer("0x#{pair[1,2]}").chr + else raise OpenSSL::X509::NameError, "invalid pair: #{str}" + end + } + end + + def expand_hexstring(str) + return nil unless str + der = str.gsub(HexPair){|hex| Integer("0x#{hex}").chr } + a1 = OpenSSL::ASN1.decode(der) + return a1.value, a1.tag + end + + def expand_value(str1, str2, str3) + value = expand_pair(str1) + value, tag = expand_hexstring(str2) unless value + value = expand_pair(str3) unless value + return value, tag + end + + def scan(dn) + str = dn + ary = [] + while true + if md = TypeAndValue.match(str) + matched = md.to_s + remain = md.post_match + type = md[1] + value, tag = expand_value(md[2], md[3], md[4]) rescue nil + if value + type_and_value = [type, value] + type_and_value.push(tag) if tag + ary.unshift(type_and_value) + if remain.length > 2 && remain[0] == ?, + str = remain[1..-1] + next + elsif remain.length > 2 && remain[0] == ?+ + raise OpenSSL::X509::NameError, + "multi-valued RDN is not supported: #{dn}" + elsif remain.empty? + break + end + end + end + msg_dn = dn[0, dn.length - str.length] + " =>" + str + raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}" + end + return ary + end + end + + class <= 0 + size = [size, limit].min + end + consume_rbuff(size) + end + + ## + # Executes the block for every line in the stream where lines are separated + # by +eol+. + # + # See also #gets + + def each(eol=$/) + while line = self.gets(eol) + yield line + end + end + alias each_line each + + ## + # Reads lines from the stream which are separated by +eol+. + # + # See also #gets + + def readlines(eol=$/) + ary = [] + while line = self.gets(eol) + ary << line + end + ary + end + + ## + # Reads a line from the stream which is separated by +eol+. + # + # Raises EOFError if at end of file. + + def readline(eol=$/) + raise EOFError if eof? + gets(eol) + end + + ## + # Reads one character from the stream. Returns nil if called at end of + # file. + + def getc + read(1) + end + + ## + # Calls the given block once for each byte in the stream. + + def each_byte # :yields: byte + while c = getc + yield(c.ord) + end + end + + ## + # Reads a one-character string from the stream. Raises an EOFError at end + # of file. + + def readchar + raise EOFError if eof? + getc + end + + ## + # Pushes character +c+ back onto the stream such that a subsequent buffered + # character read will return it. + # + # Unlike IO#getc multiple bytes may be pushed back onto the stream. + # + # Has no effect on unbuffered reads (such as #sysread). + + def ungetc(c) + @rbuffer[0,0] = c.chr + end + + ## + # Returns true if the stream is at file which means there is no more data to + # be read. + + def eof? + fill_rbuff if !@eof && @rbuffer.empty? + @eof && @rbuffer.empty? + end + alias eof eof? + + # + # for writing. + # + private + + ## + # Writes +s+ to the buffer. When the buffer is full or #sync is true the + # buffer is flushed to the underlying socket. + + def do_write(s) + @wbuffer = "" unless defined? @wbuffer + @wbuffer << s + @sync ||= false + if @sync or @wbuffer.size > BLOCK_SIZE or idx = @wbuffer.rindex($/) + remain = idx ? idx + $/.size : @wbuffer.length + nwritten = 0 + while remain > 0 + str = @wbuffer[nwritten,remain] + begin + nwrote = syswrite(str) + rescue Errno::EAGAIN + retry + end + remain -= nwrote + nwritten += nwrote + end + @wbuffer[0,nwritten] = "" + end + end + + public + + ## + # Writes +s+ to the stream. If the argument is not a string it will be + # converted using String#to_s. Returns the number of bytes written. + + def write(s) + do_write(s) + s.length + end + + ## + # Writes +str+ in the non-blocking manner. + # + # If there is buffered data, it is flushed first. This may block. + # + # write_nonblock returns number of bytes written to the SSL connection. + # + # When no data can be written without blocking it raises + # OpenSSL::SSL::SSLError extended by IO::WaitReadable or IO::WaitWritable. + # + # IO::WaitReadable means SSL needs to read internally so write_nonblock + # should be called again after the underlying IO is readable. + # + # IO::WaitWritable means SSL needs to write internally so write_nonblock + # should be called again after underlying IO is writable. + # + # So OpenSSL::Buffering#write_nonblock needs two rescue clause as follows. + # + # # emulates blocking write. + # begin + # result = ssl.write_nonblock(str) + # rescue IO::WaitReadable + # IO.select([io]) + # retry + # rescue IO::WaitWritable + # IO.select(nil, [io]) + # retry + # end + # + # Note that one reason that write_nonblock reads from the underlying IO + # is when the peer requests a new TLS/SSL handshake. See the openssl FAQ + # for more details. http://www.openssl.org/support/faq.html + + def write_nonblock(s) + flush + syswrite_nonblock(s) + end + + ## + # Writes +s+ to the stream. +s+ will be converted to a String using + # String#to_s. + + def << (s) + do_write(s) + self + end + + ## + # Writes +args+ to the stream along with a record separator. + # + # See IO#puts for full details. + + def puts(*args) + s = "" + if args.empty? + s << "\n" + end + args.each{|arg| + s << arg.to_s + if $/ && /\n\z/ !~ s + s << "\n" + end + } + do_write(s) + nil + end + + ## + # Writes +args+ to the stream. + # + # See IO#print for full details. + + def print(*args) + s = "" + args.each{ |arg| s << arg.to_s } + do_write(s) + nil + end + + ## + # Formats and writes to the stream converting parameters under control of + # the format string. + # + # See Kernel#sprintf for format string details. + + def printf(s, *args) + do_write(s % args) + nil + end + + ## + # Flushes buffered data to the SSLSocket. + + def flush + osync = @sync + @sync = true + do_write "" + return self + ensure + @sync = osync + end + + ## + # Closes the SSLSocket and flushes any unwritten data. + + def close + flush rescue nil + sysclose + end +end diff --git a/lib/ruby/1.9/openssl/cipher.rb b/lib/ruby/1.9/openssl/cipher.rb new file mode 100644 index 00000000000..f36547771f2 --- /dev/null +++ b/lib/ruby/1.9/openssl/cipher.rb @@ -0,0 +1,65 @@ +#-- +# +# $RCSfile$ +# +# = Ruby-space predefined Cipher subclasses +# +# = Info +# 'OpenSSL for Ruby 2' project +# Copyright (C) 2002 Michal Rokos +# All rights reserved. +# +# = Licence +# This program is licenced under the same licence as Ruby. +# (See the file 'LICENCE'.) +# +# = Version +# $Id: cipher.rb 33067 2011-08-25 00:52:10Z drbrain $ +# +#++ + +module OpenSSL + class Cipher + %w(AES CAST5 BF DES IDEA RC2 RC4 RC5).each{|name| + klass = Class.new(Cipher){ + define_method(:initialize){|*args| + cipher_name = args.inject(name){|n, arg| "#{n}-#{arg}" } + super(cipher_name) + } + } + const_set(name, klass) + } + + %w(128 192 256).each{|keylen| + klass = Class.new(Cipher){ + define_method(:initialize){|mode| + mode ||= "CBC" + cipher_name = "AES-#{keylen}-#{mode}" + super(cipher_name) + } + } + const_set("AES#{keylen}", klass) + } + + # Generate, set, and return a random key. + # You must call cipher.encrypt or cipher.decrypt before calling this method. + def random_key + str = OpenSSL::Random.random_bytes(self.key_len) + self.key = str + return str + end + + # Generate, set, and return a random iv. + # You must call cipher.encrypt or cipher.decrypt before calling this method. + def random_iv + str = OpenSSL::Random.random_bytes(self.iv_len) + self.iv = str + return str + end + + # This class is only provided for backwards compatibility. Use OpenSSL::Cipher in the future. + class Cipher < Cipher + # add warning + end + end # Cipher +end # OpenSSL diff --git a/lib/ruby/1.9/openssl/config.rb b/lib/ruby/1.9/openssl/config.rb new file mode 100644 index 00000000000..24a54c91eca --- /dev/null +++ b/lib/ruby/1.9/openssl/config.rb @@ -0,0 +1,313 @@ +=begin += Ruby-space definitions that completes C-space funcs for Config + += Info + Copyright (C) 2010 Hiroshi Nakamura + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + +=end + +require 'stringio' + +module OpenSSL + class Config + include Enumerable + + class << self + def parse(str) + c = new() + parse_config(StringIO.new(str)).each do |section, hash| + c[section] = hash + end + c + end + + alias load new + + def parse_config(io) + begin + parse_config_lines(io) + rescue ConfigError => e + e.message.replace("error in line #{io.lineno}: " + e.message) + raise + end + end + + def get_key_string(data, section, key) # :nodoc: + if v = data[section] && data[section][key] + return v + elsif section == 'ENV' + if v = ENV[key] + return v + end + end + if v = data['default'] && data['default'][key] + return v + end + end + + private + + def parse_config_lines(io) + section = 'default' + data = {section => {}} + while definition = get_definition(io) + definition = clear_comments(definition) + next if definition.empty? + if definition[0] == ?[ + if /\[([^\]]*)\]/ =~ definition + section = $1.strip + data[section] ||= {} + else + raise ConfigError, "missing close square bracket" + end + else + if /\A([^:\s]*)(?:::([^:\s]*))?\s*=(.*)\z/ =~ definition + if $2 + section = $1 + key = $2 + else + key = $1 + end + value = unescape_value(data, section, $3) + (data[section] ||= {})[key] = value.strip + else + raise ConfigError, "missing equal sign" + end + end + end + data + end + + # escape with backslash + QUOTE_REGEXP_SQ = /\A([^'\\]*(?:\\.[^'\\]*)*)'/ + # escape with backslash and doubled dq + QUOTE_REGEXP_DQ = /\A([^"\\]*(?:""[^"\\]*|\\.[^"\\]*)*)"/ + # escaped char map + ESCAPE_MAP = { + "r" => "\r", + "n" => "\n", + "b" => "\b", + "t" => "\t", + } + + def unescape_value(data, section, value) + scanned = [] + while m = value.match(/['"\\$]/) + scanned << m.pre_match + c = m[0] + value = m.post_match + case c + when "'" + if m = value.match(QUOTE_REGEXP_SQ) + scanned << m[1].gsub(/\\(.)/, '\\1') + value = m.post_match + else + break + end + when '"' + if m = value.match(QUOTE_REGEXP_DQ) + scanned << m[1].gsub(/""/, '').gsub(/\\(.)/, '\\1') + value = m.post_match + else + break + end + when "\\" + c = value.slice!(0, 1) + scanned << (ESCAPE_MAP[c] || c) + when "$" + ref, value = extract_reference(value) + refsec = section + if ref.index('::') + refsec, ref = ref.split('::', 2) + end + if v = get_key_string(data, refsec, ref) + scanned << v + else + raise ConfigError, "variable has no value" + end + else + raise 'must not reaced' + end + end + scanned << value + scanned.join + end + + def extract_reference(value) + rest = '' + if m = value.match(/\(([^)]*)\)|\{([^}]*)\}/) + value = m[1] || m[2] + rest = m.post_match + elsif [?(, ?{].include?(value[0]) + raise ConfigError, "no close brace" + end + if m = value.match(/[a-zA-Z0-9_]*(?:::[a-zA-Z0-9_]*)?/) + return m[0], m.post_match + rest + else + raise + end + end + + def clear_comments(line) + # FCOMMENT + if m = line.match(/\A([\t\n\f ]*);.*\z/) + return m[1] + end + # COMMENT + scanned = [] + while m = line.match(/[#'"\\]/) + scanned << m.pre_match + c = m[0] + line = m.post_match + case c + when '#' + line = nil + break + when "'", '"' + regexp = (c == "'") ? QUOTE_REGEXP_SQ : QUOTE_REGEXP_DQ + scanned << c + if m = line.match(regexp) + scanned << m[0] + line = m.post_match + else + scanned << line + line = nil + break + end + when "\\" + scanned << c + scanned << line.slice!(0, 1) + else + raise 'must not reaced' + end + end + scanned << line + scanned.join + end + + def get_definition(io) + if line = get_line(io) + while /[^\\]\\\z/ =~ line + if extra = get_line(io) + line += extra + else + break + end + end + return line.strip + end + end + + def get_line(io) + if line = io.gets + line.gsub(/[\r\n]*/, '') + end + end + end + + def initialize(filename = nil) + @data = {} + if filename + File.open(filename.to_s) do |file| + Config.parse_config(file).each do |section, hash| + self[section] = hash + end + end + end + end + + def get_value(section, key) + if section.nil? + raise TypeError.new('nil not allowed') + end + section = 'default' if section.empty? + get_key_string(section, key) + end + + def value(arg1, arg2 = nil) + warn('Config#value is deprecated; use Config#get_value') + if arg2.nil? + section, key = 'default', arg1 + else + section, key = arg1, arg2 + end + section ||= 'default' + section = 'default' if section.empty? + get_key_string(section, key) + end + + def add_value(section, key, value) + check_modify + (@data[section] ||= {})[key] = value + end + + def [](section) + @data[section] || {} + end + + def section(name) + warn('Config#section is deprecated; use Config#[]') + @data[name] || {} + end + + def []=(section, pairs) + check_modify + @data[section] ||= {} + pairs.each do |key, value| + self.add_value(section, key, value) + end + end + + def sections + @data.keys + end + + def to_s + ary = [] + @data.keys.sort.each do |section| + ary << "[ #{section} ]\n" + @data[section].keys.each do |key| + ary << "#{key}=#{@data[section][key]}\n" + end + ary << "\n" + end + ary.join + end + + def each + @data.each do |section, hash| + hash.each do |key, value| + yield [section, key, value] + end + end + end + + def inspect + "#<#{self.class.name} sections=#{sections.inspect}>" + end + + protected + + def data + @data + end + + private + + def initialize_copy(other) + @data = other.data.dup + end + + def check_modify + raise TypeError.new("Insecure: can't modify OpenSSL config") if frozen? + end + + def get_key_string(section, key) + Config.get_key_string(@data, section, key) + end + end +end diff --git a/lib/ruby/1.9/openssl/digest.rb b/lib/ruby/1.9/openssl/digest.rb new file mode 100644 index 00000000000..09bd8588986 --- /dev/null +++ b/lib/ruby/1.9/openssl/digest.rb @@ -0,0 +1,72 @@ +#-- +# +# $RCSfile$ +# +# = Ruby-space predefined Digest subclasses +# +# = Info +# 'OpenSSL for Ruby 2' project +# Copyright (C) 2002 Michal Rokos +# All rights reserved. +# +# = Licence +# This program is licenced under the same licence as Ruby. +# (See the file 'LICENCE'.) +# +# = Version +# $Id: digest.rb 33067 2011-08-25 00:52:10Z drbrain $ +# +#++ + +module OpenSSL + class Digest + + alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) + if OPENSSL_VERSION_NUMBER > 0x00908000 + alg += %w(SHA224 SHA256 SHA384 SHA512) + end + + # Return the +data+ hash computed with +name+ Digest. +name+ is either the + # long name or short name of a supported digest algorithm. + # + # === Examples + # + # OpenSSL::Digest.digest("SHA256, "abc") + # + # which is equivalent to: + # + # OpenSSL::Digest::SHA256.digest("abc") + + def self.digest(name, data) + super(data, name) + end + + alg.each{|name| + klass = Class.new(Digest){ + define_method(:initialize){|*data| + if data.length > 1 + raise ArgumentError, + "wrong number of arguments (#{data.length} for 1)" + end + super(name, data.first) + } + } + singleton = (class << klass; self; end) + singleton.class_eval{ + define_method(:digest){|data| Digest.digest(name, data) } + define_method(:hexdigest){|data| Digest.hexdigest(name, data) } + } + const_set(name, klass) + } + + # This class is only provided for backwards compatibility. Use OpenSSL::Digest in the future. + class Digest < Digest + def initialize(*args) + # add warning + super(*args) + end + end + + end # Digest +end # OpenSSL + diff --git a/lib/ruby/1.9/openssl/ssl-internal.rb b/lib/ruby/1.9/openssl/ssl-internal.rb new file mode 100644 index 00000000000..9c0320c6d29 --- /dev/null +++ b/lib/ruby/1.9/openssl/ssl-internal.rb @@ -0,0 +1,177 @@ +=begin += $RCSfile$ -- Ruby-space definitions that completes C-space funcs for SSL + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2001 GOTOU YUUZOU + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: ssl-internal.rb 29189 2010-09-06 01:53:00Z nahi $ +=end + +require "openssl/buffering" +require "fcntl" + +module OpenSSL + module SSL + class SSLContext + DEFAULT_PARAMS = { + :ssl_version => "SSLv23", + :verify_mode => OpenSSL::SSL::VERIFY_PEER, + :ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW", + :options => OpenSSL::SSL::OP_ALL, + } + + DEFAULT_CERT_STORE = OpenSSL::X509::Store.new + DEFAULT_CERT_STORE.set_default_paths + if defined?(OpenSSL::X509::V_FLAG_CRL_CHECK_ALL) + DEFAULT_CERT_STORE.flags = OpenSSL::X509::V_FLAG_CRL_CHECK_ALL + end + + def set_params(params={}) + params = DEFAULT_PARAMS.merge(params) + params.each{|name, value| self.__send__("#{name}=", value) } + if self.verify_mode != OpenSSL::SSL::VERIFY_NONE + unless self.ca_file or self.ca_path or self.cert_store + self.cert_store = DEFAULT_CERT_STORE + end + end + return params + end + end + + module SocketForwarder + def addr + to_io.addr + end + + def peeraddr + to_io.peeraddr + end + + def setsockopt(level, optname, optval) + to_io.setsockopt(level, optname, optval) + end + + def getsockopt(level, optname) + to_io.getsockopt(level, optname) + end + + def fcntl(*args) + to_io.fcntl(*args) + end + + def closed? + to_io.closed? + end + + def do_not_reverse_lookup=(flag) + to_io.do_not_reverse_lookup = flag + end + end + + module Nonblock + def initialize(*args) + flag = File::NONBLOCK + flag |= @io.fcntl(Fcntl::F_GETFL) if defined?(Fcntl::F_GETFL) + @io.fcntl(Fcntl::F_SETFL, flag) + super + end + end + + def verify_certificate_identity(cert, hostname) + should_verify_common_name = true + cert.extensions.each{|ext| + next if ext.oid != "subjectAltName" + ext.value.split(/,\s+/).each{|general_name| + if /\ADNS:(.*)/ =~ general_name + should_verify_common_name = false + reg = Regexp.escape($1).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + elsif /\AIP Address:(.*)/ =~ general_name + should_verify_common_name = false + return true if $1 == hostname + end + } + } + if should_verify_common_name + cert.subject.to_a.each{|oid, value| + if oid == "CN" + reg = Regexp.escape(value).gsub(/\\\*/, "[^.]+") + return true if /\A#{reg}\z/i =~ hostname + end + } + end + return false + end + module_function :verify_certificate_identity + + class SSLSocket + include Buffering + include SocketForwarder + include Nonblock + + def post_connection_check(hostname) + unless OpenSSL::SSL.verify_certificate_identity(peer_cert, hostname) + raise SSLError, "hostname does not match the server certificate" + end + return true + end + + def session + SSL::Session.new(self) + rescue SSL::Session::SessionError + nil + end + end + + class SSLServer + include SocketForwarder + attr_accessor :start_immediately + + def initialize(svr, ctx) + @svr = svr + @ctx = ctx + unless ctx.session_id_context + session_id = OpenSSL::Digest::MD5.hexdigest($0) + @ctx.session_id_context = session_id + end + @start_immediately = true + end + + def to_io + @svr + end + + def listen(backlog=5) + @svr.listen(backlog) + end + + def shutdown(how=Socket::SHUT_RDWR) + @svr.shutdown(how) + end + + def accept + sock = @svr.accept + begin + ssl = OpenSSL::SSL::SSLSocket.new(sock, @ctx) + ssl.sync_close = true + ssl.accept if @start_immediately + ssl + rescue SSLError => ex + sock.close + raise ex + end + end + + def close + @svr.close + end + end + end +end diff --git a/lib/ruby/1.9/openssl/ssl.rb b/lib/ruby/1.9/openssl/ssl.rb new file mode 100644 index 00000000000..15f42d60918 --- /dev/null +++ b/lib/ruby/1.9/openssl/ssl.rb @@ -0,0 +1,2 @@ +warn 'deprecated openssl/ssl use: require "openssl" instead of "openssl/ssl"' +require 'openssl' diff --git a/lib/ruby/1.9/openssl/x509-internal.rb b/lib/ruby/1.9/openssl/x509-internal.rb new file mode 100644 index 00000000000..d92d5d9721b --- /dev/null +++ b/lib/ruby/1.9/openssl/x509-internal.rb @@ -0,0 +1,158 @@ +=begin += $RCSfile$ -- Ruby-space definitions that completes C-space funcs for X509 and subclasses + += Info + 'OpenSSL for Ruby 2' project + Copyright (C) 2002 Michal Rokos + All rights reserved. + += Licence + This program is licenced under the same licence as Ruby. + (See the file 'LICENCE'.) + += Version + $Id: x509-internal.rb 32663 2011-07-25 04:51:26Z nahi $ +=end + +module OpenSSL + module X509 + class ExtensionFactory + def create_extension(*arg) + if arg.size > 1 + create_ext(*arg) + else + send("create_ext_from_"+arg[0].class.name.downcase, arg[0]) + end + end + + def create_ext_from_array(ary) + raise ExtensionError, "unexpected array form" if ary.size > 3 + create_ext(ary[0], ary[1], ary[2]) + end + + def create_ext_from_string(str) # "oid = critical, value" + oid, value = str.split(/=/, 2) + oid.strip! + value.strip! + create_ext(oid, value) + end + + def create_ext_from_hash(hash) + create_ext(hash["oid"], hash["value"], hash["critical"]) + end + end + + class Extension + def to_s # "oid = critical, value" + str = self.oid + str << " = " + str << "critical, " if self.critical? + str << self.value.gsub(/\n/, ", ") + end + + def to_h # {"oid"=>sn|ln, "value"=>value, "critical"=>true|false} + {"oid"=>self.oid,"value"=>self.value,"critical"=>self.critical?} + end + + def to_a + [ self.oid, self.value, self.critical? ] + end + end + + class Name + module RFC2253DN + Special = ',=+<>#;' + HexChar = /[0-9a-fA-F]/ + HexPair = /#{HexChar}#{HexChar}/ + HexString = /#{HexPair}+/ + Pair = /\\(?:[#{Special}]|\\|"|#{HexPair})/ + StringChar = /[^#{Special}\\"]/ + QuoteChar = /[^\\"]/ + AttributeType = /[a-zA-Z][0-9a-zA-Z]*|[0-9]+(?:\.[0-9]+)*/ + AttributeValue = / + (?!["#])((?:#{StringChar}|#{Pair})*)| + \#(#{HexString})| + "((?:#{QuoteChar}|#{Pair})*)" + /x + TypeAndValue = /\A(#{AttributeType})=#{AttributeValue}/ + + module_function + + def expand_pair(str) + return nil unless str + return str.gsub(Pair){ + pair = $& + case pair.size + when 2 then pair[1,1] + when 3 then Integer("0x#{pair[1,2]}").chr + else raise OpenSSL::X509::NameError, "invalid pair: #{str}" + end + } + end + + def expand_hexstring(str) + return nil unless str + der = str.gsub(HexPair){$&.to_i(16).chr } + a1 = OpenSSL::ASN1.decode(der) + return a1.value, a1.tag + end + + def expand_value(str1, str2, str3) + value = expand_pair(str1) + value, tag = expand_hexstring(str2) unless value + value = expand_pair(str3) unless value + return value, tag + end + + def scan(dn) + str = dn + ary = [] + while true + if md = TypeAndValue.match(str) + remain = md.post_match + type = md[1] + value, tag = expand_value(md[2], md[3], md[4]) rescue nil + if value + type_and_value = [type, value] + type_and_value.push(tag) if tag + ary.unshift(type_and_value) + if remain.length > 2 && remain[0] == ?, + str = remain[1..-1] + next + elsif remain.length > 2 && remain[0] == ?+ + raise OpenSSL::X509::NameError, + "multi-valued RDN is not supported: #{dn}" + elsif remain.empty? + break + end + end + end + msg_dn = dn[0, dn.length - str.length] + " =>" + str + raise OpenSSL::X509::NameError, "malformed RDN: #{msg_dn}" + end + return ary + end + end + + class << self + def parse_rfc2253(str, template=OBJECT_TYPE_TEMPLATE) + ary = OpenSSL::X509::Name::RFC2253DN.scan(str) + self.new(ary, template) + end + + def parse_openssl(str, template=OBJECT_TYPE_TEMPLATE) + ary = str.scan(/\s*([^\/,]+)\s*/).collect{|i| i[0].split("=", 2) } + self.new(ary, template) + end + + alias parse parse_openssl + end + end + + class StoreContext + def cleanup + warn "(#{caller.first}) OpenSSL::X509::StoreContext#cleanup is deprecated with no replacement" if $VERBOSE + end + end + end +end diff --git a/lib/ruby/1.9/openssl/x509.rb b/lib/ruby/1.9/openssl/x509.rb new file mode 100644 index 00000000000..f1777cdf061 --- /dev/null +++ b/lib/ruby/1.9/openssl/x509.rb @@ -0,0 +1,2 @@ +warn 'deprecated openssl/x509 use: require "openssl" instead of "openssl/x509"' +require 'openssl' diff --git a/lib/ruby/shared/jopenssl/version.rb b/lib/ruby/shared/jopenssl/version.rb new file mode 100644 index 00000000000..ea579b0fa78 --- /dev/null +++ b/lib/ruby/shared/jopenssl/version.rb @@ -0,0 +1,5 @@ +module Jopenssl + module Version + VERSION = "0.7.5.dev" + end +end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/asn1.rb b/lib/ruby/shared/jruby/openssl/autoloads/asn1.rb deleted file mode 100644 index 5dacf185e42..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/asn1.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::ASN1 requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/bn.rb b/lib/ruby/shared/jruby/openssl/autoloads/bn.rb deleted file mode 100644 index 314f944a257..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/bn.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::BN requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/cipher.rb b/lib/ruby/shared/jruby/openssl/autoloads/cipher.rb deleted file mode 100644 index b4b4a6b5f36..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/cipher.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::Cipher requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/config.rb b/lib/ruby/shared/jruby/openssl/autoloads/config.rb deleted file mode 100644 index 4f259f0fc72..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/config.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::Config requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/netscape.rb b/lib/ruby/shared/jruby/openssl/autoloads/netscape.rb deleted file mode 100644 index 6d9e6d3f23c..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/netscape.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::Netscape requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/pkcs7.rb b/lib/ruby/shared/jruby/openssl/autoloads/pkcs7.rb deleted file mode 100644 index cbc1d93a9a8..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/pkcs7.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::PKCS7 requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/pkey.rb b/lib/ruby/shared/jruby/openssl/autoloads/pkey.rb deleted file mode 100644 index 6d2a8114776..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/pkey.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::PKey requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/random.rb b/lib/ruby/shared/jruby/openssl/autoloads/random.rb deleted file mode 100644 index 26980dc4b7a..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/random.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::Random requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/ssl.rb b/lib/ruby/shared/jruby/openssl/autoloads/ssl.rb deleted file mode 100644 index b8e2d7c5c4c..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/ssl.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::SSL requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/autoloads/x509.rb b/lib/ruby/shared/jruby/openssl/autoloads/x509.rb deleted file mode 100644 index 7e419b8da00..00000000000 --- a/lib/ruby/shared/jruby/openssl/autoloads/x509.rb +++ /dev/null @@ -1,9 +0,0 @@ -require 'rubygems' - -# try to activate jruby-openssl gem for OpenSSL::SSL, raising error if gem not present -begin - gem 'jruby-openssl' - require 'openssl.rb' -rescue Gem::LoadError => e - raise LoadError.new("OpenSSL::X509 requires the jruby-openssl gem") -end diff --git a/lib/ruby/shared/jruby/openssl/builtin.rb b/lib/ruby/shared/jruby/openssl/builtin.rb deleted file mode 100644 index 65ade65f2e4..00000000000 --- a/lib/ruby/shared/jruby/openssl/builtin.rb +++ /dev/null @@ -1,196 +0,0 @@ -# this will load the gem and library only if it's available -require 'jruby/openssl/gem' - -unless defined?(OpenSSL) - module OpenSSL - VERSION = "1.0.0" - OPENSSL_VERSION = "OpenSSL 0.9.8b 04 May 2006 (JRuby fake)" - OPENSSL_DUMMY = true - - class OpenSSLError < StandardError; end - # These require the gem, so we present an error if they're accessed - %w[ - ASN1 - BN - Cipher - Config - Netscape - PKCS7 - PKey - Random - SSL - X509 - ].each {|c| autoload c, "jruby/openssl/autoloads/#{c.downcase}"} - - def self.determine_version - require 'java' - java.security.MessageDigest.getInstance("SHA224", PROVIDER); - 9469999 - rescue Exception - 9469952 - end - OPENSSL_VERSION_NUMBER = determine_version - - require 'java' - class HMACError < OpenSSLError; end - class DigestError < OpenSSLError; end - - class Digest - class << self - def digest(name, data) - self.new(name, data).digest - end - def hexdigest(name, data) - self.new(name, data).hexdigest - end - end - - attr_reader :algorithm, :name, :data - - def initialize(name, data = nil) - @name = name - @data = "" - create_digest - update(data) if data - end - - def initialize_copy(dig) - initialize(dig.name, dig.data) - end - - def update(d) - @data << d - @md.update(d.to_java_bytes) - self - end - alias_method :<<, :update - - def digest - @md.reset - String.from_java_bytes @md.digest(@data.to_java_bytes) - end - - def hexdigest - digest.unpack("H*")[0] - end - alias_method :to_s, :hexdigest - alias_method :inspect, :hexdigest - - def ==(oth) - return false unless oth.kind_of? OpenSSL::Digest - self.algorithm == oth.algorithm && self.digest == oth.digest - end - - def reset - @md.reset - @data = "" - end - - def size - @md.getDigestLength - end - - private - def create_digest - @algorithm = case @name - when "DSS" - "SHA" - when "DSS1" - "SHA1" - else - @name - end - @md = java.security.MessageDigest.getInstance(@algorithm) - end - - begin - old_verbose, $VERBOSE = $VERBOSE, nil # silence warnings - # from openssl/digest.rb -- define the concrete digest classes - alg = %w(DSS DSS1 MD2 MD4 MD5 MDC2 RIPEMD160 SHA SHA1) - if ::OpenSSL::OPENSSL_VERSION_NUMBER > 0x00908000 - alg += %w(SHA224 SHA256 SHA384 SHA512) - end - alg.each{|name| - klass = Class.new(Digest){ - define_method(:initialize){|*data| - if data.length > 1 - raise ArgumentError, - "wrong number of arguments (#{data.length} for 1)" - end - super(name, data.first) - } - } - singleton = (class << klass; self; end) - singleton.class_eval{ - define_method(:digest){|data| Digest.digest(name, data) } - define_method(:hexdigest){|data| Digest.hexdigest(name, data) } - } - const_set(name, klass) - } - ensure - $VERBOSE = old_verbose - end - - class Digest < Digest - def initialize(*args) - # add warning - super(*args) - end - end - end - - class HMAC - class << self - def digest(dig, key, data) - self.new(key, dig).update(data).digest - end - - def hexdigest(dig, key, data) - self.new(key, dig).update(data).hexdigest - end - end - - attr_reader :name, :key, :data - - def initialize(key, dig) - @name = "HMAC" + dig.algorithm - @key = key - @data = "" - create_mac - end - - def initialize_copy(hmac) - @name = hmac.name - @key = hmac.key - @data = hmac.data - create_mac - end - - def update(d) - @data << d - self - end - alias_method :<<, :update - - def digest - @mac.reset - String.from_java_bytes @mac.doFinal(@data.to_java_bytes) - end - - def hexdigest - digest.unpack("H*")[0] - end - - alias_method :inspect, :hexdigest - alias_method :to_s, :hexdigest - - private - def create_mac - @mac = javax.crypto.Mac.getInstance(@name) - @mac.init(javax.crypto.spec.SecretKeySpec.new(@key.to_java_bytes, @name)) - end - end - warn %{JRuby limited openssl loaded. http://jruby.org/openssl -gem install jruby-openssl for full support.} - end -end diff --git a/lib/ruby/shared/jruby/openssl/gem.rb b/lib/ruby/shared/jruby/openssl/gem.rb deleted file mode 100644 index c7010eb6e78..00000000000 --- a/lib/ruby/shared/jruby/openssl/gem.rb +++ /dev/null @@ -1,15 +0,0 @@ -# try to activate jruby-openssl gem, and only require from the gem if it's there -tried_gem = false -begin - require 'openssl.rb' -rescue LoadError - unless tried_gem - require 'rubygems' - begin - gem 'jruby-openssl' - rescue LoadError - end - tried_gem = true - retry - end -end diff --git a/lib/ruby/shared/jruby/openssl/gem_only.rb b/lib/ruby/shared/jruby/openssl/gem_only.rb deleted file mode 100644 index 464c88014c4..00000000000 --- a/lib/ruby/shared/jruby/openssl/gem_only.rb +++ /dev/null @@ -1,5 +0,0 @@ -module JRuby - module OpenSSL - GEM_ONLY = true - end -end \ No newline at end of file diff --git a/lib/ruby/shared/jruby/openssl/stub.rb b/lib/ruby/shared/jruby/openssl/stub.rb deleted file mode 100644 index 34affb4bb8b..00000000000 --- a/lib/ruby/shared/jruby/openssl/stub.rb +++ /dev/null @@ -1,11 +0,0 @@ -module JRuby - module OpenSSL - GEM_ONLY = false unless defined?(GEM_ONLY) - end -end - -if JRuby::OpenSSL::GEM_ONLY - require 'jruby/openssl/gem' -else - require "jruby/openssl/builtin" -end \ No newline at end of file diff --git a/src/org/jruby/Ruby.java b/src/org/jruby/Ruby.java index 37c991e51c4..4775eb14e52 100644 --- a/src/org/jruby/Ruby.java +++ b/src/org/jruby/Ruby.java @@ -1583,6 +1583,7 @@ private void initBuiltins() { addLazyBuiltin("fcntl.rb", "fcntl", "org.jruby.ext.fcntl.FcntlLibrary"); addLazyBuiltin("rubinius.jar", "rubinius", "org.jruby.ext.rubinius.RubiniusLibrary"); addLazyBuiltin("yecht.jar", "yecht", "YechtService"); + addLazyBuiltin("jopenssl.jar", "jopenssl", "org.jruby.ext.openssl.OSSLLibrary"); if (is1_9()) { addLazyBuiltin("mathn/complex.jar", "mathn/complex", "org.jruby.ext.mathn.Complex"); @@ -1606,12 +1607,6 @@ public void load(Ruby runtime, boolean wrap) throws IOException { if(RubyInstanceConfig.NATIVE_NET_PROTOCOL) { addLazyBuiltin("net/protocol.rb", "net/protocol", "org.jruby.ext.net.protocol.NetProtocolBufferedIOLibrary"); } - - addBuiltinIfAllowed("openssl.jar", new Library() { - public void load(Ruby runtime, boolean wrap) throws IOException { - runtime.getLoadService().require("jruby/openssl/stub"); - } - }); addBuiltinIfAllowed("win32ole.jar", new Library() { public void load(Ruby runtime, boolean wrap) throws IOException { diff --git a/src/org/jruby/RubyModule.java b/src/org/jruby/RubyModule.java index 8caac9af667..824df641029 100644 --- a/src/org/jruby/RubyModule.java +++ b/src/org/jruby/RubyModule.java @@ -1971,7 +1971,8 @@ public IRubyObject attr_accessor(IRubyObject[] args) { } /** rb_mod_attr_accessor - * + * Note: this method should not be called from Java in most cases, since + * it depends on Ruby frame state for visibility. Use add[Read/Write]Attribute instead. */ @JRubyMethod(name = "attr_accessor", rest = true, visibility = PRIVATE, reads = VISIBILITY) public IRubyObject attr_accessor(ThreadContext context, IRubyObject[] args) { diff --git a/src/org/jruby/ext/openssl/ASN1.java b/src/org/jruby/ext/openssl/ASN1.java new file mode 100644 index 00000000000..3cfa66200da --- /dev/null +++ b/src/org/jruby/ext/openssl/ASN1.java @@ -0,0 +1,938 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.math.BigInteger; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Date; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.io.IOException; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERBoolean; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERString; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.DERUTCTime; +import org.bouncycastle.asn1.DERUTF8String; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyBignum; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.RubySymbol; +import org.jruby.RubyTime; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class ASN1 { + private static Map> SYM_TO_OID = new IdentityHashMap>(); + private static Map> OID_TO_SYM = new IdentityHashMap>(); + private static Map> OID_TO_NID = new IdentityHashMap>(); + private static Map> NID_TO_OID = new IdentityHashMap>(); + private static Map> NID_TO_SN = new IdentityHashMap>(); + private static Map> NID_TO_LN = new IdentityHashMap>(); + + + static void addObject(Ruby runtime, int nid, String sn, String ln, String oid) { + Map s2o = SYM_TO_OID.get(runtime); + Map o2s = OID_TO_SYM.get(runtime); + Map o2n = OID_TO_NID.get(runtime); + Map n2o = NID_TO_OID.get(runtime); + Map n2s = NID_TO_SN.get(runtime); + Map n2l = NID_TO_LN.get(runtime); + if(null != oid && (null != sn || null != ln)) { + DERObjectIdentifier ident = new DERObjectIdentifier(oid); + if(sn != null) { + s2o.put(sn.toLowerCase(),ident); + } + if(ln != null) { + s2o.put(ln.toLowerCase(),ident); + } + o2s.put(ident,sn == null ? ln : sn); + o2n.put(ident,nid); + n2o.put(nid,ident); + n2s.put(nid,sn); + n2l.put(nid,ln); + } + } + + @SuppressWarnings("unchecked") + private synchronized static void initMaps(Ruby runtime) { + Map val = new HashMap(org.bouncycastle.asn1.x509.X509Name.DefaultLookUp); + Map val2 = new HashMap(org.bouncycastle.asn1.x509.X509Name.DefaultSymbols); + SYM_TO_OID.put(runtime,val); + OID_TO_SYM.put(runtime,val2); + OID_TO_NID.put(runtime,new HashMap()); + NID_TO_OID.put(runtime,new HashMap()); + NID_TO_SN.put(runtime,new HashMap()); + NID_TO_LN.put(runtime,new HashMap()); + OpenSSLImpl.defaultObjects(runtime); + } + + synchronized static Integer obj2nid(Ruby runtime, String oid) { + return obj2nid(runtime, new DERObjectIdentifier(oid)); + } + + synchronized static String ln2oid(Ruby runtime, String ln) { + Map val = SYM_TO_OID.get(runtime); + if(null == val) { + initMaps(runtime); + val = SYM_TO_OID.get(runtime); + } + return val.get(ln).getId(); + } + + synchronized static Integer obj2nid(Ruby runtime, DERObjectIdentifier oid) { + Map o2n = OID_TO_NID.get(runtime); + if(null == o2n) { + initMaps(runtime); + o2n = OID_TO_NID.get(runtime); + } + return o2n.get(oid); + } + + synchronized static String o2a(Ruby runtime, DERObjectIdentifier obj) { + Integer nid = obj2nid(runtime,obj); + Map n2l = NID_TO_LN.get(runtime); + Map n2s = NID_TO_SN.get(runtime); + String one = n2l.get(nid); + if(one == null) { + one = n2s.get(nid); + } + return one; + } + + synchronized static String nid2ln(Ruby runtime, int nid) { + return nid2ln(runtime, new Integer(nid)); + } + + synchronized static String nid2ln(Ruby runtime, Integer nid) { + Map n2l = NID_TO_LN.get(runtime); + if(null == n2l) { + initMaps(runtime); + n2l = NID_TO_LN.get(runtime); + } + return n2l.get(nid); + } + + synchronized static Map getOIDLookup(Ruby runtime) { + Map val = SYM_TO_OID.get(runtime); + if(null == val) { + initMaps(runtime); + val = SYM_TO_OID.get(runtime); + } + return val; + } + + synchronized static Map getSymLookup(Ruby runtime) { + Map val = OID_TO_SYM.get(runtime); + if(null == val) { + initMaps(runtime); + val = OID_TO_SYM.get(runtime); + } + return val; + } + + private final static Object[][] ASN1_INFO = { + {"EOC", null, null }, + {"BOOLEAN", org.bouncycastle.asn1.DERBoolean.class, "Boolean" }, + {"INTEGER", org.bouncycastle.asn1.DERInteger.class, "Integer" }, + {"BIT_STRING", org.bouncycastle.asn1.DERBitString.class, "BitString" }, + {"OCTET_STRING", org.bouncycastle.asn1.DEROctetString.class, "OctetString" }, + {"NULL", org.bouncycastle.asn1.DERNull.class, "Null" }, + {"OBJECT", org.bouncycastle.asn1.DERObjectIdentifier.class, "ObjectId" }, + {"OBJECT_DESCRIPTOR", null, null }, + {"EXTERNAL", null, null }, + {"REAL", null, null }, + {"ENUMERATED", org.bouncycastle.asn1.DEREnumerated.class, "Enumerated" }, + {"EMBEDDED_PDV", null, null }, + {"UTF8STRING", org.bouncycastle.asn1.DERUTF8String.class, "UTF8String" }, + {"RELATIVE_OID", null, null }, + {"[UNIVERSAL 14]", null, null }, + {"[UNIVERSAL 15]", null, null }, + {"SEQUENCE", org.bouncycastle.asn1.DERSequence.class, "Sequence" }, + {"SET", org.bouncycastle.asn1.DERSet.class, "Set" }, + {"NUMERICSTRING", org.bouncycastle.asn1.DERNumericString.class, "NumericString" }, + {"PRINTABLESTRING", org.bouncycastle.asn1.DERPrintableString.class, "PrintableString" }, + {"T61STRING", org.bouncycastle.asn1.DERT61String.class, "T61String" }, + {"VIDEOTEXSTRING", null, null }, + {"IA5STRING", org.bouncycastle.asn1.DERIA5String.class, "IA5String" }, + {"UTCTIME", org.bouncycastle.asn1.DERUTCTime.class, "UTCTime" }, + {"GENERALIZEDTIME", org.bouncycastle.asn1.DERGeneralizedTime.class, "GeneralizedTime" }, + {"GRAPHICSTRING", null, null }, + {"ISO64STRING", null, null }, + {"GENERALSTRING", org.bouncycastle.asn1.DERGeneralString.class, "GeneralString" }, + {"UNIVERSALSTRING", org.bouncycastle.asn1.DERUniversalString.class, "UniversalString" }, + {"CHARACTER_STRING", null, null }, + {"BMPSTRING", org.bouncycastle.asn1.DERBMPString.class, "BMPString" }}; + + private final static Map CLASS_TO_ID = new HashMap(); + private final static Map RUBYNAME_TO_ID = new HashMap(); + + static { + for(int i=0;i classForId(int id) { + @SuppressWarnings("unchecked") + Class result = (Class)(ASN1_INFO[id][1]); + return result; + } + + public static void createASN1(Ruby runtime, RubyModule ossl) { + ThreadContext context = runtime.getCurrentContext(); + RubyModule mASN1 = ossl.defineModuleUnder("ASN1"); + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + mASN1.defineClassUnder("ASN1Error",openSSLError, openSSLError.getAllocator()); + + mASN1.defineAnnotatedMethods(ASN1.class); + + List ary = new ArrayList(); + mASN1.setConstant("UNIVERSAL_TAG_NAME",runtime.newArray(ary)); + for(int i=0;i em = getOIDLookup(runtime); + String name = null; + for(Iterator iter = em.keySet().iterator();iter.hasNext();) { + String key = iter.next(); + if(oid.equals(em.get(key))) { + if(name == null || key.length() < name.length()) { + name = key; + } + } + } + return name; + } + + private static String getLongNameFor(Ruby runtime, String nameOrOid) { + DERObjectIdentifier oid = getObjectIdentifier(runtime,nameOrOid); + Map em = getOIDLookup(runtime); + String name = null; + for(Iterator iter = em.keySet().iterator();iter.hasNext();) { + String key = iter.next(); + if(oid.equals(em.get(key))) { + if(name == null || key.length() > name.length()) { + name = key; + } + } + } + return name; + } + + private static DERObjectIdentifier getObjectIdentifier(Ruby runtime, String nameOrOid) { + Object val1 = ASN1.getOIDLookup(runtime).get(nameOrOid.toLowerCase()); + if(null != val1) { + return (DERObjectIdentifier)val1; + } + DERObjectIdentifier val2 = new DERObjectIdentifier(nameOrOid); + return val2; + } + + @JRubyMethod(name="Boolean", module=true, rest=true) + public static IRubyObject fact_Boolean(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Boolean").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="Integer", module=true, rest=true) + public static IRubyObject fact_Integer(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Integer").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="Enumerated", module=true, rest=true) + public static IRubyObject fact_Enumerated(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Enumerated").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="BitString", module=true, rest=true) + public static IRubyObject fact_BitString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("BitString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="OctetString", module=true, rest=true) + public static IRubyObject fact_OctetString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("OctetString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="UTF8String", module=true, rest=true) + public static IRubyObject fact_UTF8String(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("UTF8String").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="NumericString", module=true, rest=true) + public static IRubyObject fact_NumericString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("NumericString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="PrintableString", module=true, rest=true) + public static IRubyObject fact_PrintableString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("PrintableString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="T61String", module=true, rest=true) + public static IRubyObject fact_T61String(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("T61String").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="VideotexString", module=true, rest=true) + public static IRubyObject fact_VideotexString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("VideotexString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="IA5String", module=true, rest=true) + public static IRubyObject fact_IA5String(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("IA5String").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="GraphicString", module=true, rest=true) + public static IRubyObject fact_GraphicString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("GraphicString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="ISO64String", module=true, rest=true) + public static IRubyObject fact_ISO64String(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("ISO64String").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="GeneralString", module=true, rest=true) + public static IRubyObject fact_GeneralString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("GeneralString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="UniversalString", module=true, rest=true) + public static IRubyObject fact_UniversalString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("UniversalString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="BMPString", module=true, rest=true) + public static IRubyObject fact_BMPString(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("BMPString").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="Nul", module=true, rest=true) + public static IRubyObject fact_Null(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Null").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="ObjectId", module=true, rest=true) + public static IRubyObject fact_ObjectId(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("ObjectId").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="UTCTime", module=true, rest=true) + public static IRubyObject fact_UTCTime(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("UTCTime").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="GeneralizedTime", module=true, rest=true) + public static IRubyObject fact_GeneralizedTime(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("GeneralizedTime").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="Sequence", module=true, rest=true) + public static IRubyObject fact_Sequence(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Sequence").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(name="Set", module=true, rest=true) + public static IRubyObject fact_Set(IRubyObject recv, IRubyObject[] args) { + return ((RubyModule)recv).getClass("Set").callMethod(recv.getRuntime().getCurrentContext(),"new",args); + } + + @JRubyMethod(meta=true, required=1) + public static IRubyObject traverse(IRubyObject recv, IRubyObject a) { + System.err.println("WARNING: unimplemented method called: traverse"); + return null; + } + + public static class ObjectId { + @JRubyMethod(meta=true, rest=true) + public static IRubyObject register(IRubyObject recv, IRubyObject[] args) { + DERObjectIdentifier deroi = new DERObjectIdentifier(args[0].toString()); + getOIDLookup(recv.getRuntime()).put(args[1].toString().toLowerCase(),deroi); + getOIDLookup(recv.getRuntime()).put(args[2].toString().toLowerCase(),deroi); + getSymLookup(recv.getRuntime()).put(deroi,args[1].toString()); + return recv.getRuntime().getTrue(); + } + + @JRubyMethod(name={"sn","short_name"}) + public static IRubyObject sn(IRubyObject self) { + return self.getRuntime().newString(getShortNameFor(self.getRuntime(),self.callMethod(self.getRuntime().getCurrentContext(),"value").toString())); + } + + @JRubyMethod(name={"ln","long_name"}) + public static IRubyObject ln(IRubyObject self) { + return self.getRuntime().newString(getLongNameFor(self.getRuntime(),self.callMethod(self.getRuntime().getCurrentContext(),"value").toString())); + } + + @JRubyMethod + public static IRubyObject oid(IRubyObject self) { + return self.getRuntime().newString(getObjectIdentifier(self.getRuntime(),self.callMethod(self.getRuntime().getCurrentContext(),"value").toString()).getId()); + } + } + + private final static DateFormat dateF = new SimpleDateFormat("yyyyMMddHHmmssz"); + private static IRubyObject decodeObj(RubyModule asnM,Object v) throws IOException, java.text.ParseException { + int ix = idForClass(v.getClass()); + String v_name = ix == -1 ? null : (String)(ASN1_INFO[ix][2]); + ThreadContext tc = asnM.getRuntime().getCurrentContext(); + if(null != v_name) { + RubyClass c = asnM.getClass(v_name); + if(v instanceof DERBitString) { + ByteList bl = new ByteList(((DERBitString)v).getBytes(), false); + IRubyObject bString = c.callMethod(tc,"new",asnM.getRuntime().newString(bl)); + bString.callMethod(tc,"unused_bits=",asnM.getRuntime().newFixnum(((DERBitString)v).getPadBits())); + return bString; + } else if(v instanceof DERString) { + ByteList val; + if (v instanceof DERUTF8String) { + val = new ByteList(((DERUTF8String) v).getString().getBytes("UTF-8")); + } else { + val = ByteList.create(((DERString)v).getString()); + } + return c.callMethod(tc,"new",asnM.getRuntime().newString(val)); + } else if(v instanceof ASN1Sequence) { + List l = new ArrayList(); + for(Enumeration enm = ((ASN1Sequence)v).getObjects(); enm.hasMoreElements(); ) { + l.add(decodeObj(asnM,enm.nextElement())); + } + return c.callMethod(tc,"new",asnM.getRuntime().newArray(l)); + } else if(v instanceof DERSet) { + List l = new ArrayList(); + for(Enumeration enm = ((DERSet)v).getObjects(); enm.hasMoreElements(); ) { + l.add(decodeObj(asnM,enm.nextElement())); + } + return c.callMethod(tc,"new",asnM.getRuntime().newArray(l)); + } else if(v instanceof DERNull) { + return c.callMethod(tc,"new",asnM.getRuntime().getNil()); + } else if(v instanceof DERInteger) { + return c.callMethod(tc,"new",RubyNumeric.str2inum(asnM.getRuntime(),asnM.getRuntime().newString(((DERInteger)v).getValue().toString()),10)); + } else if(v instanceof DERUTCTime) { + Date d = dateF.parse(((DERUTCTime)v).getAdjustedTime()); + Calendar cal = Calendar.getInstance(); + cal.setTime(d); + IRubyObject[] argv = new IRubyObject[6]; + argv[0] = asnM.getRuntime().newFixnum(cal.get(Calendar.YEAR)); + argv[1] = asnM.getRuntime().newFixnum(cal.get(Calendar.MONTH)+1); + argv[2] = asnM.getRuntime().newFixnum(cal.get(Calendar.DAY_OF_MONTH)); + argv[3] = asnM.getRuntime().newFixnum(cal.get(Calendar.HOUR_OF_DAY)); + argv[4] = asnM.getRuntime().newFixnum(cal.get(Calendar.MINUTE)); + argv[5] = asnM.getRuntime().newFixnum(cal.get(Calendar.SECOND)); + return c.callMethod(tc,"new",asnM.getRuntime().getClass("Time").callMethod(tc,"local",argv)); + } else if(v instanceof DERObjectIdentifier) { + String av = ((DERObjectIdentifier)v).getId(); + return c.callMethod(tc,"new",asnM.getRuntime().newString(av)); + } else if(v instanceof DEROctetString) { + ByteList bl = new ByteList(((DEROctetString)v).getOctets(), false); + return c.callMethod(tc,"new",asnM.getRuntime().newString(bl)); + } else if(v instanceof DERBoolean) { + return c.callMethod(tc,"new",((DERBoolean)v).isTrue() ? asnM.getRuntime().getTrue() : asnM.getRuntime().getFalse()); + } else { + System.out.println("Should handle: " + v.getClass().getName()); + } + } else if(v instanceof DERTaggedObject) { + RubyClass c = asnM.getClass("ASN1Data"); + IRubyObject val = decodeObj(asnM, ((DERTaggedObject)v).getObject()); + IRubyObject tag = asnM.getRuntime().newFixnum(((DERTaggedObject)v).getTagNo()); + IRubyObject tag_class = asnM.getRuntime().newSymbol("CONTEXT_SPECIFIC"); + return c.callMethod(tc,"new",new IRubyObject[]{asnM.getRuntime().newArray(val),tag,tag_class}); + } + + // System.err.println("v: " + v + "[" + v.getClass().getName() + "]"); + return null; + } + + @JRubyMethod(meta = true) + public static IRubyObject decode(IRubyObject recv, IRubyObject obj) { + try { + IRubyObject obj2 = OpenSSLImpl.to_der_if_possible(obj); + RubyModule asnM = (RubyModule)recv; + ASN1InputStream asis = new ASN1InputStream(obj2.convertToString().getBytes()); + IRubyObject ret = decodeObj(asnM, asis.readObject()); + return ret; + } catch(IOException e) { + throw recv.getRuntime().newIOErrorFromException(e); + } catch(Exception e) { + throw recv.getRuntime().newArgumentError(e.getMessage()); + } + } + + @JRubyMethod(meta=true, required=1) + public static IRubyObject decode_all(IRubyObject recv, IRubyObject a) { + System.err.println("WARNING: unimplemented method called: decode_all"); + return null; + } + + public static class ASN1Data extends RubyObject { + private static final long serialVersionUID = 6117598347932209839L; + + public static ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new ASN1Data(runtime, klass); + } + }; + public ASN1Data(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + protected void asn1Error() { + asn1Error(null); + } + + protected void asn1Error(String msg) { + throw Utils.newError(getRuntime(), "OpenSSL::ASN1::ASN1Error", msg); + } + + @JRubyMethod + public IRubyObject initialize(IRubyObject value, IRubyObject tag, IRubyObject tag_class) { + if(!(tag_class instanceof RubySymbol)) { + asn1Error("invalid tag class"); + } + if(tag_class.toString().equals(":UNIVERSAL") && RubyNumeric.fix2int(tag) > 31) { + asn1Error("tag number for Universal too large"); + } + ThreadContext tc = getRuntime().getCurrentContext(); + this.callMethod(tc,"tag=", tag); + this.callMethod(tc,"value=", value); + this.callMethod(tc,"tag_class=", tag_class); + + return this; + } + + ASN1Encodable toASN1() { + ThreadContext tc = getRuntime().getCurrentContext(); + int tag = RubyNumeric.fix2int(callMethod(tc,"tag")); + IRubyObject val = callMethod(tc,"value"); + if(val instanceof RubyArray) { + RubyArray arr = (RubyArray)callMethod(tc,"value"); + if(arr.size() > 1) { + ASN1EncodableVector vec = new ASN1EncodableVector(); + for (IRubyObject obj : arr.toJavaArray()) { + vec.add(((ASN1Data)obj).toASN1()); + } + return new DERTaggedObject(tag, new DERSequence(vec)); + } else { + return new DERTaggedObject(tag,((ASN1Data)(arr.getList().get(0))).toASN1()); + } + } else { + return new DERTaggedObject(tag, ((ASN1Data)val).toASN1()); + } + } + + @JRubyMethod + public IRubyObject to_der() { + return getRuntime().newString(new ByteList(toASN1().getDEREncoded(),false)); + } + + protected IRubyObject defaultTag() { + int i = idForRubyName(getMetaClass().getRealClass().getBaseName()); + if(i != -1) { + return getRuntime().newFixnum(i); + } else { + return getRuntime().getNil(); + } + } + + protected void print() { + print(0); + } + + protected void printIndent(int indent) { + for(int i=0;i1) { + tag = args[1]; + if(args.length>2) { + tagging = args[2]; + if(args.length>3) { + tag_class = args[3]; + } + } + if(tag.isNil()) { + asn1Error("must specify tag number"); + } + if(tagging.isNil()) { + tagging = getRuntime().newSymbol("EXPLICIT"); + } + if(!(tagging instanceof RubySymbol)) { + asn1Error("invalid tag default"); + } + if(tag_class.isNil()) { + tag_class = getRuntime().newSymbol("CONTEXT_SPECIFIC"); + } + if(!(tag_class instanceof RubySymbol)) { + asn1Error("invalid tag class"); + } + if(tagging.toString().equals(":IMPLICIT") && RubyNumeric.fix2int(tag) > 31) { + asn1Error("tag number for Universal too large"); + } + } else { + tag = defaultTag(); + tagging = getRuntime().getNil(); + tag_class = getRuntime().newSymbol("UNIVERSAL"); + } + if("ObjectId".equals(getMetaClass().getRealClass().getBaseName())) { + String v = getSymLookup(getRuntime()).get(getObjectIdentifier(value.toString())); + if(v != null) { + value = getRuntime().newString(v); + } + } + ThreadContext tc = getRuntime().getCurrentContext(); + this.callMethod(tc,"tag=",tag); + this.callMethod(tc,"value=",value); + this.callMethod(tc,"tagging=",tagging); + this.callMethod(tc,"tag_class=",tag_class); + + return this; + } + + private DERObjectIdentifier getObjectIdentifier(String nameOrOid) { + Object val1 = ASN1.getOIDLookup(getRuntime()).get(nameOrOid.toLowerCase()); + if(null != val1) { + return (DERObjectIdentifier)val1; + } + DERObjectIdentifier val2 = new DERObjectIdentifier(nameOrOid); + return val2; + } + + ASN1Encodable toASN1() { + // System.err.println(getMetaClass().getRealClass().getBaseName()+"#toASN1"); + int tag = idForRubyName(getMetaClass().getRealClass().getBaseName()); + @SuppressWarnings("unchecked") Class imp = (Class)ASN1_INFO[tag][1]; + IRubyObject val = callMethod(getRuntime().getCurrentContext(),"value"); + if(imp == DERObjectIdentifier.class) { + return getObjectIdentifier(val.toString()); + } else if(imp == DERNull.class) { + return new DERNull(); + } else if(imp == DERBoolean.class) { + return new DERBoolean(val.isTrue()); + } else if(imp == DERUTCTime.class) { + return new DERUTCTime(((RubyTime)val).getJavaDate()); + } else if(imp == DERInteger.class && val instanceof RubyBignum) { + return new DERInteger(((RubyBignum)val).getValue()); + } else if(imp == DERInteger.class) { + return new DERInteger(new BigInteger(val.toString())); + } else if(imp == DEROctetString.class) { + return new DEROctetString(val.convertToString().getBytes()); + } else if(imp == DERBitString.class) { + byte[] bs = val.convertToString().getBytes(); + int unused = 0; + for(int i = (bs.length-1); i>-1; i--) { + if(bs[i] == 0) { + unused += 8; + } else { + byte v2 = bs[i]; + int x = 8; + while(v2 != 0) { + v2 <<= 1; + x--; + } + unused += x; + break; + } + } + return new DERBitString(bs,unused); + } else if(val instanceof RubyString) { + try { + return imp.getConstructor(String.class).newInstance(val.toString()); + } catch (Exception ex) { + throw RaiseException.createNativeRaiseException(getRuntime(), ex); + } + } + + System.err.println("object with tag: " + tag + " and value: " + val + " and val.class: " + val.getClass().getName() + " and impl: " + imp.getName()); + System.err.println("WARNING: unimplemented method called: asn1data#toASN1"); + return null; + } + + protected void print(int indent) { + printIndent(indent); + System.out.println(getMetaClass().getRealClass().getBaseName() + ": " + callMethod(getRuntime().getCurrentContext(),"value").callMethod(getRuntime().getCurrentContext(),"inspect").toString()); + } + } + + public static class ASN1Constructive extends ASN1Data { + private static final long serialVersionUID = -7166662655104776828L; + + public static ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new ASN1Constructive(runtime, klass); + } + }; + public ASN1Constructive(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + @JRubyMethod + public IRubyObject to_der() { + return super.to_der(); + } + + @JRubyMethod(required=1, optional=3) + public IRubyObject initialize(IRubyObject[] args) { + IRubyObject value = args[0]; + IRubyObject tag = getRuntime().getNil(); + IRubyObject tagging = getRuntime().getNil(); + IRubyObject tag_class = getRuntime().getNil(); + if(args.length>1) { + tag = args[1]; + if(args.length>2) { + tagging = args[2]; + if(args.length>3) { + tag_class = args[3]; + } + } + if(tag.isNil()) { + asn1Error("must specify tag number"); + } + if(tagging.isNil()) { + tagging = getRuntime().newSymbol("EXPLICIT"); + } + if(!(tagging instanceof RubySymbol)) { + asn1Error("invalid tag default"); + } + if(tag_class.isNil()) { + tag_class = getRuntime().newSymbol("CONTEXT_SPECIFIC"); + } + if(!(tag_class instanceof RubySymbol)) { + asn1Error("invalid tag class"); + } + if(tagging.toString().equals(":IMPLICIT") && RubyNumeric.fix2int(tag) > 31) { + asn1Error("tag number for Universal too large"); + } + } else { + tag = defaultTag(); + tagging = getRuntime().getNil(); + tag_class = getRuntime().newSymbol("UNIVERSAL"); + } + ThreadContext tc = getRuntime().getCurrentContext(); + this.callMethod(tc,"tag=",tag); + this.callMethod(tc,"value=",value); + this.callMethod(tc,"tagging=",tagging); + this.callMethod(tc,"tag_class=",tag_class); + + return this; + } + + ASN1Encodable toASN1() { + // System.err.println(getMetaClass().getRealClass().getBaseName()+"#toASN1"); + int id = idForRubyName(getMetaClass().getRealClass().getBaseName()); + if(id != -1) { + ASN1EncodableVector vec = new ASN1EncodableVector(); + RubyArray arr = (RubyArray)callMethod(getRuntime().getCurrentContext(),"value"); + for (IRubyObject obj : arr.toJavaArray()) { + if(obj instanceof ASN1Data) { + vec.add(((ASN1Data)obj).toASN1()); + } else { + vec.add(((ASN1Data) ASN1.decode(getRuntime().getClassFromPath("OpenSSL::ASN1"), OpenSSLImpl.to_der_if_possible(obj))).toASN1()); + } + } + try { + @SuppressWarnings("unchecked") + ASN1Encodable result = ((Class) (ASN1_INFO[id][1])).getConstructor(new Class[] { ASN1EncodableVector.class }) + .newInstance(new Object[] { vec }); + return result; + } catch (Exception e) { + // TODO: deprecated + throw RaiseException.createNativeRaiseException(getRuntime(), e); + } + } + return null; + } + + @JRubyMethod(frame=true) + public IRubyObject each(Block block) { + RubyArray arr = (RubyArray) callMethod(getRuntime().getCurrentContext(), "value"); + for (IRubyObject obj : arr.toJavaArray()) { + block.yield(getRuntime().getCurrentContext(), obj); + } + return getRuntime().getNil(); + } + + protected void print(int indent) { + printIndent(indent); + System.out.println(getMetaClass().getRealClass().getBaseName() + ": "); + RubyArray arr = (RubyArray)callMethod(getRuntime().getCurrentContext(),"value"); + for (IRubyObject obj : arr.toJavaArray()) { + ((ASN1Data)obj).print(indent+1); + } + } + } +}// ASN1 diff --git a/src/org/jruby/ext/openssl/Attribute.java b/src/org/jruby/ext/openssl/Attribute.java new file mode 100644 index 00000000000..e915f50b4b6 --- /dev/null +++ b/src/org/jruby/ext/openssl/Attribute.java @@ -0,0 +1,133 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class Attribute extends RubyObject { + private static final long serialVersionUID = 5569940260019783275L; + + private static ObjectAllocator ATTRIBUTE_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new Attribute(runtime, klass); + } + }; + + public static void createAttribute(Ruby runtime, RubyModule mX509) { + RubyClass cAttribute = mX509.defineClassUnder("Attribute",runtime.getObject(), ATTRIBUTE_ALLOCATOR); + + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("AttributeError",openSSLError, openSSLError.getAllocator()); + + cAttribute.defineAnnotatedMethods(Attribute.class); + } + + public Attribute(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private IRubyObject oid; + private IRubyObject value; + + private DERObjectIdentifier getObjectIdentifier(String nameOrOid) { + Object val1 = ASN1.getOIDLookup(getRuntime()).get(nameOrOid.toLowerCase()); + if(null != val1) { + return (DERObjectIdentifier)val1; + } + DERObjectIdentifier val2 = new DERObjectIdentifier(nameOrOid); + return val2; + } + + DERObject toASN1() { + ASN1EncodableVector v1 = new ASN1EncodableVector(); + v1.add(getObjectIdentifier(oid.toString())); + if(value instanceof ASN1.ASN1Constructive) { + v1.add(((ASN1.ASN1Constructive)value).toASN1()); + } else { + ASN1EncodableVector v2 = new ASN1EncodableVector(); + v2.add(((ASN1.ASN1Data)value).toASN1()); + v1.add(new DERSet(v2)); + } + return new DERSequence(v1); + } + + @JRubyMethod(name="initialize", required=1, optional=1) + public IRubyObject _initialize(IRubyObject[] str) { + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),str,1,2) == 1) { + IRubyObject _oid = OpenSSLImpl.to_der_if_possible(str[0]); + set_oid(_oid); + return this; + } + set_oid(str[0]); + set_value(str[1]); + return this; + } + + @JRubyMethod + public IRubyObject to_der() { + System.err.println("WARNING: unimplemented method called: attr#to_der"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject oid() { + return oid; + } + + @JRubyMethod(name="oid=") + public IRubyObject set_oid(IRubyObject val) { + this.oid = val; + return val; + } + + @JRubyMethod + public IRubyObject value() { + return value; + } + + @JRubyMethod(name="value=") + public IRubyObject set_value(IRubyObject val) { + IRubyObject tmp = OpenSSLImpl.to_der_if_possible(val); + this.value = ASN1.decode(getRuntime().getClassFromPath("OpenSSL::ASN1"), tmp); + return val; + } +}// Attribute diff --git a/src/org/jruby/ext/openssl/BN.java b/src/org/jruby/ext/openssl/BN.java new file mode 100644 index 00000000000..18a77e35e9e --- /dev/null +++ b/src/org/jruby/ext/openssl/BN.java @@ -0,0 +1,766 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2007 William N Dortch + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Random; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.runtime.Arity; +import org.jruby.runtime.ClassIndex; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * OpenSSL::BN implementation. Wraps java.math.BigInteger, which provides + * most functionality directly; the rest is easily derived. + * + * Beware that BN's are mutable -- I don't agree with this approach, but + * must conform for compatibility with MRI's implementation. The offending methods + * are set_bit!, clear_bit!, mask_bits! and copy.

+ * + * I've included a few operations (& | ^ ~) that aren't defined by MRI/OpenSSL. + * These are non-portable (i.e., won't work in C-Ruby), so use at your own risk.

+ * + * @author Bill Dortch + */ +public class BN extends RubyObject { + private static final long serialVersionUID = -5660938062191525498L; + + private static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE); + private static final BigInteger TWO = BigInteger.valueOf(2); + private static final int DEFAULT_CERTAINTY = 100; + private static Random _random; + private static SecureRandom _secureRandom; + + private static ObjectAllocator BN_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new BN(runtime, klass, BigInteger.ZERO); + } + }; + + public static BN newBN(Ruby runtime, BigInteger value) { + return new BN(runtime, value != null ? value : BigInteger.ZERO); + } + + public static void createBN(Ruby runtime, RubyModule ossl) { + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + ossl.defineClassUnder("BNError", openSSLError, openSSLError.getAllocator()); + + RubyClass bn = ossl.defineClassUnder("BN", runtime.getObject(), BN_ALLOCATOR); + + bn.defineAnnotatedMethods(BN.class); + } + + private volatile BigInteger value; + + private BN(Ruby runtime, RubyClass clazz, BigInteger value) { + super(runtime, clazz); + this.value = value; + } + + private BN(Ruby runtime, BigInteger value) { + super(runtime, runtime.getModule("OpenSSL").getClass("BN")); + this.value = value; + } + + public BigInteger getValue() { + return value; + } + + // TODO: check whether this is really needed for JRuby 1.0x (not used in 1.1x) + public IRubyObject doClone() { + return newBN(getRuntime(), this.value); + } + + public IRubyObject initialize_copy(IRubyObject original) { + super.initialize_copy(original); + if (this != original) { + this.value = ((BN)original).value; + } + return this; + } + + @JRubyMethod(name="initialize", required=1, optional=1) + public synchronized IRubyObject bn_initialize(IRubyObject[] args) { + Ruby runtime = getRuntime(); + if (this.value != BigInteger.ZERO) { // already initialized + throw newBNError(runtime, "illegal initialization"); + } + int argc = Arity.checkArgumentCount(runtime, args, 1, 2); + int base = argc == 2 ? RubyNumeric.num2int(args[1]) : 10; + RubyString str = RubyString.stringValue(args[0]); + switch (base) { + case 2: + // this seems wrong to me, but is the behavior of the + // MRI implementation. rather than interpreting the string + // as ASCII-encoded binary digits, the raw binary value of + // the string is used instead. the value is always interpreted + // as positive, hence the use of the signum version of the BI + // constructor here: + this.value = new BigInteger(1, str.getBytes()); + break; + case 10: + case 16: + // here, the ASCII-encoded decimal or hex string is used + try { + this.value = new BigInteger(str.toString(), base); + break; + } catch (NumberFormatException e) { + throw runtime.newArgumentError("value " + str + " is not legal for radix " + base); + } + case 0: // FIXME: not currently supporting BN_mpi2bn + throw runtime.newArgumentError("unsupported radix: " + base); + default: + throw runtime.newArgumentError("illegal radix: " + base); + } + return this; + } + + @JRubyMethod(name="copy") + public synchronized IRubyObject bn_copy(IRubyObject other) { + if (this != other) { + this.value = getBigInteger(other); + } + return this; + } + + @JRubyMethod(name="to_s", rest=true) + public IRubyObject bn_to_s(IRubyObject[] args) { + Ruby runtime = getRuntime(); + int argc = Arity.checkArgumentCount(runtime, args, 0, 1); + int base = argc == 1 ? RubyNumeric.num2int(args[0]) : 10; + switch (base) { + case 2: + // again, following MRI implementation, wherein base 2 deals + // with strings as byte arrays rather than ASCII-encoded binary + // digits. note that negative values are returned as though positive: + + byte[] bytes = this.value.abs().toByteArray(); + + // suppress leading 0 byte to conform to MRI behavior + if (bytes[0] == 0) { + return runtime.newString(new ByteList(bytes, 1, bytes.length - 1)); + } + return runtime.newString(new ByteList(bytes, false)); + case 10: + case 16: + return runtime.newString(value.toString(base).toUpperCase()); + case 0: // FIXME: not currently supporting BN_mpi2bn + throw runtime.newArgumentError("unsupported radix: " + base); + default: + throw runtime.newArgumentError("illegal radix: " + base); + } + } + + @JRubyMethod(name="to_i") + public IRubyObject bn_to_i() { + Ruby runtime = getRuntime(); + // FIXME: s/b faster way to convert than going through RubyString + return RubyNumeric.str2inum(runtime, runtime.newString(value.toString()), 10, true); + } + + @JRubyMethod(name="to_bn") + public IRubyObject bn_to_bn() { + return this; + } + + @JRubyMethod(name="coerce") + // FIXME: is this right? don't see how it would be useful... + public IRubyObject bn_coerce(IRubyObject other) { + Ruby runtime = getRuntime(); + IRubyObject self; + switch (other.getMetaClass().index) { + case ClassIndex.STRING: + self = runtime.newString(value.toString()); + break; + case ClassIndex.FIXNUM: + case ClassIndex.BIGNUM: + // FIXME: s/b faster way to convert than going through RubyString + self = RubyNumeric.str2inum(runtime, runtime.newString(value.toString()), 10, true); + break; + default: + if (other instanceof BN) { + self = this; + } else { + throw runtime.newTypeError("Don't know how to coerce"); + } + } + return runtime.newArray(other, self); + } + + @JRubyMethod(name="zero?") + public IRubyObject bn_is_zero() { + return getRuntime().newBoolean(value.equals(BigInteger.ZERO)); + } + + @JRubyMethod(name="one?") + public IRubyObject bn_is_one() { + return getRuntime().newBoolean(value.equals(BigInteger.ONE)); + } + + @JRubyMethod(name="odd?") + public IRubyObject bn_is_odd() { + return getRuntime().newBoolean(value.testBit(0)); + } + + @JRubyMethod(name={"cmp", "<=>"}) + public IRubyObject bn_cmp(IRubyObject other) { + return getRuntime().newFixnum(value.compareTo(getBigInteger(other))); + } + + @JRubyMethod(name="ucmp") + public IRubyObject bn_ucmp(IRubyObject other) { + return getRuntime().newFixnum(value.abs().compareTo(getBigInteger(other).abs())); + } + + @JRubyMethod(name={"eql?", "==", "==="}) + public IRubyObject bn_eql(IRubyObject other) { + return getRuntime().newBoolean(value.equals(getBigInteger(other))); + } + + @JRubyMethod(name="sqr") + public IRubyObject bn_sqr() { + // TODO: check whether mult n * n is faster + return newBN(getRuntime(), value.pow(2)); + } + + @JRubyMethod(name="~") + public IRubyObject bn_not() { + return newBN(getRuntime(), value.not()); + } + + @JRubyMethod(name="+") + public IRubyObject bn_add(IRubyObject other) { + return newBN(getRuntime(), value.add(getBigInteger(other))); + } + + @JRubyMethod(name="-") + public IRubyObject bn_sub(IRubyObject other) { + return newBN(getRuntime(), value.subtract(getBigInteger(other))); + } + + @JRubyMethod(name="*") + public IRubyObject bn_mul(IRubyObject other) { + return newBN(getRuntime(), value.multiply(getBigInteger(other))); + } + + @JRubyMethod(name="%") + public IRubyObject bn_mod(IRubyObject other) { + try { + return newBN(getRuntime(), value.mod(getBigInteger(other))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="/") + public IRubyObject bn_div(IRubyObject other) { + Ruby runtime = getRuntime(); + try { + BigInteger[] result = value.divideAndRemainder(getBigInteger(other)); + return runtime.newArray(newBN(runtime, result[0]), newBN(runtime, result[1])); + } catch (ArithmeticException e) { + throw runtime.newZeroDivisionError(); + } + } + + @JRubyMethod(name="&") + public IRubyObject bn_and(IRubyObject other) { + return newBN(getRuntime(), value.and(getBigInteger(other))); + } + + @JRubyMethod(name="|") + public IRubyObject bn_or(IRubyObject other) { + return newBN(getRuntime(), value.or(getBigInteger(other))); + } + + @JRubyMethod(name="^") + public IRubyObject bn_xor(IRubyObject other) { + return newBN(getRuntime(), value.xor(getBigInteger(other))); + } + + @JRubyMethod(name="**") + public IRubyObject bn_exp(IRubyObject other) { + // somewhat strangely, BigInteger takes int rather than BigInteger + // as the argument to pow. so we'll have to narrow the value, and + // raise an exception if data would be lost. (on the other hand, an + // exponent even approaching Integer.MAX_VALUE would be silly big, and + // the value would take a very, very long time to calculate.) + // we'll check for values < 0 (illegal) while we're at it + int exp; + switch(other.getMetaClass().index) { + case ClassIndex.FIXNUM: { + long val = ((RubyFixnum)other).getLongValue(); + if (val >= 0 && val <= Integer.MAX_VALUE) { + exp = (int)val; + break; + } + } + case ClassIndex.BIGNUM: + // Bignum is inherently too big + throw newBNError(getRuntime(), "invalid exponent"); + default: { + if (!(other instanceof BN)) { + throw getRuntime().newTypeError("Cannot convert into OpenSSL::BN"); + } + BigInteger val = ((BN)other).value; + if (val.compareTo(BigInteger.ZERO) < 0 || val.compareTo(MAX_INT) > 0) { + throw newBNError(getRuntime(), "invalid exponent"); + } + exp = val.intValue(); + break; + } + } + try { + return newBN(getRuntime(), value.pow(exp)); + } catch (ArithmeticException e) { + // shouldn't happen, we've already checked for < 0 + throw newBNError(getRuntime(), "invalid exponent"); + } + } + + @JRubyMethod(name="gcd") + public IRubyObject bn_gcd(IRubyObject other) { + return newBN(getRuntime(), value.gcd(getBigInteger(other))); + } + + @JRubyMethod(name="mod_sqr") + public IRubyObject bn_mod_sqr(IRubyObject other) { + try { + return newBN(getRuntime(), value.modPow(TWO, getBigInteger(other))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="mod_inverse") + public IRubyObject bn_mod_inverse(IRubyObject other) { + try { + return newBN(getRuntime(), value.modInverse(getBigInteger(other))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="mod_add") + public IRubyObject bn_mod_add(IRubyObject other, IRubyObject mod) { + try { + return newBN(getRuntime(), value.add(getBigInteger(other)).mod(getBigInteger(mod))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="mod_sub") + public IRubyObject bn_mod_sub(IRubyObject other, IRubyObject mod) { + try { + return newBN(getRuntime(), value.subtract(getBigInteger(other)).mod(getBigInteger(mod))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="mod_mul") + public IRubyObject bn_mod_mul(IRubyObject other, IRubyObject mod) { + try { + return newBN(getRuntime(), value.multiply(getBigInteger(other)).mod(getBigInteger(mod))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="mod_exp") + public IRubyObject bn_mod_exp(IRubyObject other, IRubyObject mod) { + try { + return newBN(getRuntime(), value.modPow(getBigInteger(other), getBigInteger(mod))); + } catch (ArithmeticException e) { + throw getRuntime().newZeroDivisionError(); + } + } + + @JRubyMethod(name="set_bit!") + public synchronized IRubyObject bn_set_bit(IRubyObject n) { + // evil mutable BN + int pos = RubyNumeric.num2int(n); + BigInteger oldValue = this.value; + // FIXME? in MRI/OSSL-BIGNUM, the original sign of a BN is remembered, so if + // you set the value of an (originally) negative number to zero (through some + // combination of clear_bit! and/or mask_bits! calls), and later call set_bit!, + // the resulting value will be negative. this seems unintuitive and, frankly, + // wrong, not to mention expensive to carry the extra sign field. + // I'm not duplicating this behavior here at this time. -BD + try { + if (oldValue.signum() >= 0) { + this.value = oldValue.setBit(pos); + } else { + this.value = oldValue.abs().setBit(pos).negate(); + } + } catch (ArithmeticException e) { + throw newBNError(getRuntime(), "invalid pos"); + } + return this; + } + + @JRubyMethod(name="clear_bit!") + public synchronized IRubyObject bn_clear_bit(IRubyObject n) { + // evil mutable BN + int pos = RubyNumeric.num2int(n); + BigInteger oldValue = this.value; + try { + if (oldValue.signum() >= 0) { + this.value = oldValue.clearBit(pos); + } else { + this.value = oldValue.abs().clearBit(pos).negate(); + } + } catch (ArithmeticException e) { + throw newBNError(getRuntime(), "invalid pos"); + } + return this; + } + + /** + * Truncates value to n bits + */ + @JRubyMethod(name="mask_bits!") + public synchronized IRubyObject bn_mask_bits(IRubyObject n) { + // evil mutable BN + + int pos = RubyNumeric.num2int(n); + if (pos < 0) throw newBNError(getRuntime(), "invalid pos"); + + BigInteger oldValue = this.value; + + // TODO: cache 2 ** n values? + if (oldValue.signum() >= 0) { + if (oldValue.bitLength() < pos) throw newBNError(getRuntime(), "invalid pos"); + this.value = oldValue.mod(TWO.pow(pos)); + } else { + BigInteger absValue = oldValue.abs(); + if (absValue.bitLength() < pos) throw newBNError(getRuntime(), "invalid pos"); + this.value = absValue.mod(TWO.pow(pos)).negate(); + } + + return this; + } + + @JRubyMethod(name="bit_set?") + public IRubyObject bn_is_bit_set(IRubyObject n) { + int pos = RubyNumeric.num2int(n); + BigInteger val = this.value; + try { + if (val.signum() >= 0) { + return getRuntime().newBoolean(val.testBit(pos)); + } else { + return getRuntime().newBoolean(val.abs().testBit(pos)); + } + } catch (ArithmeticException e) { + throw newBNError(getRuntime(), "invalid pos"); + } + } + + @JRubyMethod(name="<<") + public IRubyObject bn_lshift(IRubyObject n) { + int nbits = RubyNumeric.num2int(n); + BigInteger val = this.value; + if (val.signum() >= 0) { + return newBN(getRuntime(), val.shiftLeft(nbits)); + } else { + return newBN(getRuntime(), val.abs().shiftLeft(nbits).negate()); + } + } + + @JRubyMethod(name=">>") + public IRubyObject bn_rshift(IRubyObject n) { + int nbits = RubyNumeric.num2int(n); + BigInteger val = this.value; + if (val.signum() >= 0) { + return newBN(getRuntime(), val.shiftRight(nbits)); + } else { + return newBN(getRuntime(), val.abs().shiftRight(nbits).negate()); + } + } + + @JRubyMethod(name="num_bits") + public IRubyObject bn_num_bits() { + return getRuntime().newFixnum(this.value.abs().bitLength()); + } + + @JRubyMethod(name="num_bytes") + public IRubyObject bn_num_bytes() { + return getRuntime().newFixnum((this.value.abs().bitLength() + 7) / 8); + } + + @JRubyMethod(name="num_bits_set") + public IRubyObject bn_num_bits_set() { + return getRuntime().newFixnum(this.value.abs().bitCount()); + } + + // note that there is a bug in the MRI version, in argument handling, + // so apparently no one ever calls this... + @JRubyMethod(name="prime?", rest=true) + public IRubyObject bn_is_prime(IRubyObject[] args) { + Ruby runtime = getRuntime(); + int argc = Arity.checkArgumentCount(runtime, args, 0, 1); + // BigInteger#isProbablePrime will actually limit checks to a maximum of 50, + // depending on bit count. + int certainty = argc == 0 ? DEFAULT_CERTAINTY : RubyNumeric.fix2int(args[0]); + return runtime.newBoolean(this.value.isProbablePrime(certainty)); + } + + // FIXME? BigInteger doesn't supply this, so right now this is (essentially) + // the same as bn_is_prime + @JRubyMethod(name="prime_fasttest?", rest=true) + public IRubyObject bn_is_prime_fasttest(IRubyObject[] args) { + Ruby runtime = getRuntime(); + int argc = Arity.checkArgumentCount(runtime, args, 0, 2); + // BigInteger#isProbablePrime will actually limit checks to a maximum of 50, + // depending on bit count. + int certainty = argc == 0 ? DEFAULT_CERTAINTY : RubyNumeric.fix2int(args[0]); + return runtime.newBoolean(this.value.isProbablePrime(certainty)); + } + + @JRubyMethod(name="generate_prime", meta=true, rest=true) + public static IRubyObject bn_generate_prime(IRubyObject recv, IRubyObject[] args) { + Ruby runtime = recv.getRuntime(); + int argc = Arity.checkArgumentCount(runtime, args, 1, 4); + int bits = RubyNumeric.num2int(args[0]); + boolean safe = argc > 1 ? args[1] != runtime.getFalse() : true; + BigInteger add = argc > 2 ? getBigInteger(args[2]) : null; + BigInteger rem = argc > 3 ? getBigInteger(args[3]) : null; + if (bits < 3) { + if (safe) throw runtime.newArgumentError("bits < 3"); + if (bits < 2) throw runtime.newArgumentError("bits < 2"); + } + return newBN(runtime, generatePrime(bits, safe, add, rem)); + } + + public static BigInteger generatePrime(int bits, boolean safe, BigInteger add, BigInteger rem) { + // From OpenSSL man page BN_generate_prime(3): + // + // "If add is not NULL, the prime will fulfill the condition p % add == rem + // (p % add == 1 if rem == NULL) in order to suit a given generator." + // + // "If safe is true, it will be a safe prime (i.e. a prime p so that + // (p-1)/2 is also prime)." + // + // see [ossl]/crypto/bn/bn_prime.c #BN_generate_prime_ex + // + + if (add != null && rem == null) { + rem = BigInteger.ONE; + } + + // borrowing technique from org.bouncycastle.crypto.generators.DHParametersHelper + // (unfortunately the code has package visibility), wherein for safe primes, + // we'll use the lowest useful certainty (2) for generation of q, then if + // p ( = 2q + 1) is prime to our required certainty (100), we'll verify that q + // is as well. + // + // for typical bit lengths ( >= 1024), this should speed things up by reducing + // initial Miller-Rabin iterations from 2 to 1 for candidate values of q. + // + // it's still painfully slow... + // + BigInteger p, q; + int qbits = bits - 1; + SecureRandom secureRandom = getSecureRandom(); + do { + if (safe) { + do { + q = new BigInteger(qbits, 2, secureRandom); + p = q.shiftLeft(1).setBit(0); + } while (!(p.isProbablePrime(DEFAULT_CERTAINTY) && q.isProbablePrime(DEFAULT_CERTAINTY))); + } else { + p = BigInteger.probablePrime(bits, secureRandom); + } + } while (add != null && !p.mod(add).equals(rem)); + return p; + } + + public static BigInteger generatePrime(int bits, boolean safe) { + return generatePrime(bits, safe, null, null); + } + + @JRubyMethod(name="rand", meta=true, rest=true) + public static IRubyObject bn_rand(IRubyObject recv, IRubyObject[] args) { + return getRandomBN(recv.getRuntime(), args, getSecureRandom()); + } + + @JRubyMethod(name="pseudo_rand", meta=true, rest=true) + public static IRubyObject bn_pseudo_rand(IRubyObject recv, IRubyObject[] args) { + return getRandomBN(recv.getRuntime(), args, getRandom()); + } + + public static BN getRandomBN(Ruby runtime, IRubyObject[] args, Random random) { + int argc = Arity.checkArgumentCount(runtime, args, 1, 3); + int bits = RubyNumeric.num2int(args[0]); + int top; + boolean bottom; + if (argc > 1) { + top = RubyNumeric.fix2int(args[1]); + bottom = argc == 3 ? args[2].isTrue() : false; + } else { + top = 0; + bottom = false; + } + + BigInteger value; + try { + value = getRandomBI(bits, top, bottom, random); + } catch (IllegalArgumentException e) { + throw runtime.newArgumentError(e.getMessage()); + } + return newBN(runtime, value); + } + + public static BigInteger getRandomBI(int bits, int top, boolean bottom, Random random) { + // From OpenSSL man page BN_rand(3): + // + // "If top is -1, the most significant bit of the random number can be zero. + // If top is 0, it is set to 1, and if top is 1, the two most significant bits + // of the number will be set to 1, so that the product of two such random numbers + // will always have 2*bits length." + // + // "If bottom is true, the number will be odd." + // + if (bits <= 0) { + if (bits == 0) return BigInteger.ZERO; + throw new IllegalArgumentException("Illegal bit length"); + } + if (top < -1 || top > 1) { + throw new IllegalArgumentException("Illegal top value"); + } + + // top/bottom handling adapted from OpenSSL's crypto/bn/bn_rand.c + int bytes = (bits + 7) / 8; + int bit = (bits - 1) % 8; + int mask = 0xff << (bit + 1); + + byte[] buf; + random.nextBytes(buf = new byte[bytes]); + if (top >= 0) { + if (top == 0) { + buf[0] |= (1 << bit); + } else { + if (bit == 0) { + buf[0] = 1; + buf[1] |= 0x80; + } + else { + buf[0] |= (3 << (bit - 1)); + } + } + } + buf[0] &= ~mask; + if (bottom) { + buf[bytes-1] |= 1; + } + + // treating result as unsigned + return new BigInteger(1, buf); + } + + @JRubyMethod(name="rand_range", meta=true) + public static IRubyObject bn_rand_range(IRubyObject recv, IRubyObject arg) { + return getRandomBNInRange(recv.getRuntime(), getBigInteger(arg), getSecureRandom()); + } + + @JRubyMethod(name="pseudo_rand_range", meta=true) + public static IRubyObject bn_pseudo_rand_range(IRubyObject recv, IRubyObject arg) { + return getRandomBNInRange(recv.getRuntime(), getBigInteger(arg), getRandom()); + } + + private static BN getRandomBNInRange(Ruby runtime, BigInteger limit, Random random) { + BigInteger value; + try { + value = getRandomBIInRange(limit, random); + } catch (IllegalArgumentException e) { + throw newBNError(runtime, "illegal range"); + } + return newBN(runtime, value); + } + + public static BigInteger getRandomBIInRange(BigInteger limit, Random random) { + if (limit.signum() < 0) { + throw new IllegalArgumentException("illegal range"); + } + int bits = limit.bitLength(); + BigInteger value; + do { + value = new BigInteger(bits, random); + } while (value.compareTo(limit) >= 0); + return value; + } + + private static Random getRandom() { + Random rand; + if ((rand = _random) != null) { + return rand; + } + return _random = new Random(); + } + + private static SecureRandom getSecureRandom() { + SecureRandom rand; + if ((rand = _secureRandom) != null) { + return rand; + } + // FIXME: do we want a particular algorithm / provider? BC? + return _secureRandom = new SecureRandom(); + } + + public static RaiseException newBNError(Ruby runtime, String message) { + return new RaiseException(runtime, runtime.getModule("OpenSSL").getClass("BNError"), message, true); + } + + public static BigInteger getBigInteger(IRubyObject arg) { + if (arg.isNil()) return null; + switch(arg.getMetaClass().index) { + case ClassIndex.FIXNUM: + case ClassIndex.BIGNUM: + return new BigInteger(arg.toString()); + default: + if (arg instanceof BN) { + return ((BN)arg).value; + } + throw arg.getRuntime().newTypeError("Cannot convert into OpenSSL::BN"); + } + } + +} diff --git a/src/org/jruby/ext/openssl/BouncyCastlePEMHandler.java b/src/org/jruby/ext/openssl/BouncyCastlePEMHandler.java new file mode 100644 index 00000000000..0babf5e84b6 --- /dev/null +++ b/src/org/jruby/ext/openssl/BouncyCastlePEMHandler.java @@ -0,0 +1,69 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.Reader; +import java.io.Writer; + +import org.bouncycastle.openssl.PEMReader; +import org.bouncycastle.openssl.PEMWriter; +import org.bouncycastle.openssl.PasswordFinder; + +/** + * @author Ola Bini + */ +public class BouncyCastlePEMHandler implements PEMHandler { + public Object readPEM(Reader read, String password) throws Exception { + return new PEMReader(read,new BasicPasswordFinder(password)).readObject(); + } + + public void writePEM(Writer writ, Object obj, String algorithm, char[] password) throws Exception { + PEMWriter p = new PEMWriter(writ); + p.writeObject(obj,algorithm,password,null); + p.flush(); + } + + public void writePEM(Writer writ, Object obj) throws Exception { + PEMWriter p = new PEMWriter(writ); + p.writeObject(obj); + p.flush(); + } + + private static class BasicPasswordFinder implements PasswordFinder { + private char[] pwd; + BasicPasswordFinder(String pwd) { + if(pwd != null) { + this.pwd = pwd.toCharArray(); + } + } + + public char[] getPassword() { + return pwd; + } + } +}// BouncyCastlePEMHandler diff --git a/src/org/jruby/ext/openssl/Cipher.java b/src/org/jruby/ext/openssl/Cipher.java new file mode 100644 index 00000000000..68761630a6b --- /dev/null +++ b/src/org/jruby/ext/openssl/Cipher.java @@ -0,0 +1,756 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.crypto.spec.IvParameterSpec; + +import javax.crypto.spec.RC2ParameterSpec; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.common.IRubyWarnings; +import org.jruby.common.IRubyWarnings.ID; +import org.jruby.anno.JRubyMethod; +import org.jruby.anno.JRubyModule; +import org.jruby.exceptions.RaiseException; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class Cipher extends RubyObject { + private static final long serialVersionUID = 7727377435222646536L; + + // set to enable debug output + private static final boolean DEBUG = false; + private static ObjectAllocator CIPHER_ALLOCATOR = new ObjectAllocator() { + + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new Cipher(runtime, klass); + } + }; + + public static void createCipher(Ruby runtime, RubyModule mOSSL) { + RubyClass cCipher = mOSSL.defineClassUnder("Cipher", runtime.getObject(), CIPHER_ALLOCATOR); + cCipher.defineAnnotatedMethods(Cipher.class); + cCipher.defineAnnotatedMethods(CipherModule.class); + RubyClass openSSLError = mOSSL.getClass("OpenSSLError"); + cCipher.defineClassUnder("CipherError", openSSLError, openSSLError.getAllocator()); + } + + @JRubyModule(name = "OpenSSL::Cipher") + public static class CipherModule { + + @JRubyMethod(meta = true) + public static IRubyObject ciphers(IRubyObject recv) { + initializeCiphers(); + List result = new ArrayList(); + for (String cipher : CIPHERS) { + result.add(recv.getRuntime().newString(cipher)); + result.add(recv.getRuntime().newString(cipher.toLowerCase())); + } + return recv.getRuntime().newArray(result); + } + + static boolean isSupportedCipher(String name) { + initializeCiphers(); + return CIPHERS.indexOf(name.toUpperCase()) != -1; + } + private static boolean initialized = false; + private static final List CIPHERS = new ArrayList(); + + private static void initializeCiphers() { + synchronized (CIPHERS) { + if (initialized) { + return; + } + String[] other = {"AES128", "AES192", "AES256", "BLOWFISH", "RC2-40-CBC", "RC2-64-CBC", "RC4", "RC4-40", "CAST", "CAST-CBC"}; + String[] bases = {"AES-128", "AES-192", "AES-256", "BF", "DES", "DES-EDE", "DES-EDE3", "RC2", "CAST5"}; + String[] suffixes = {"", "-CBC", "-CFB", "-CFB1", "-CFB8", "-ECB", "-OFB"}; + for (int i = 0, j = bases.length; i < j; i++) { + for (int k = 0, l = suffixes.length; k < l; k++) { + String val = bases[i] + suffixes[k]; + if (tryCipher(val)) { + CIPHERS.add(val.toUpperCase()); + } + } + } + for (int i = 0, j = other.length; i < j; i++) { + if (tryCipher(other[i])) { + CIPHERS.add(other[i].toUpperCase()); + } + } + initialized = true; + } + } + } + + public static class Algorithm { + + private static final Set BLOCK_MODES; + + static { + BLOCK_MODES = new HashSet(); + + BLOCK_MODES.add("CBC"); + BLOCK_MODES.add("CFB"); + BLOCK_MODES.add("CFB1"); + BLOCK_MODES.add("CFB8"); + BLOCK_MODES.add("ECB"); + BLOCK_MODES.add("OFB"); + } + + public static String jsseToOssl(String inName, int keyLen) { + String cryptoBase = null; + String cryptoVersion = null; + String cryptoMode = null; + String[] parts = inName.split("/"); + if (parts.length != 1 && parts.length != 3) { + return null; + } + cryptoBase = parts[0]; + if (parts.length > 2) { + cryptoMode = parts[1]; + // padding: parts[2] is not used + } + if (!BLOCK_MODES.contains(cryptoMode)) { + cryptoVersion = cryptoMode; + cryptoMode = "CBC"; + } + if (cryptoMode == null) { + cryptoMode = "CBC"; + } + if (cryptoBase.equals("DESede")) { + cryptoBase = "DES"; + cryptoVersion = "EDE3"; + } else if (cryptoBase.equals("Blowfish")) { + cryptoBase = "BF"; + } + if (cryptoVersion == null) { + cryptoVersion = String.valueOf(keyLen); + } + return cryptoBase + "-" + cryptoVersion + "-" + cryptoMode; + } + + public static String[] osslToJsse(String inName) { + // assume PKCS5Padding + return osslToJsse(inName, null); + } + + public static String[] osslToJsse(String inName, String padding) { + String[] split = inName.split("-"); + String cryptoBase = split[0]; + String cryptoVersion = null; + String cryptoMode = null; + String realName = null; + + String paddingType; + if (padding == null || padding.equalsIgnoreCase("PKCS5Padding")) { + paddingType = "PKCS5Padding"; + } else if (padding.equals("0") || padding.equalsIgnoreCase("NoPadding")) { + paddingType = "NoPadding"; + } else if (padding.equalsIgnoreCase("ISO10126Padding")) { + paddingType = "ISO10126Padding"; + } else { + paddingType = "PKCS5Padding"; + } + + if ("bf".equalsIgnoreCase(cryptoBase)) { + cryptoBase = "Blowfish"; + } + + if (split.length == 3) { + cryptoVersion = split[1]; + cryptoMode = split[2]; + } else if (split.length == 2) { + cryptoMode = split[1]; + } else { + cryptoMode = "CBC"; + } + + if (cryptoBase.equalsIgnoreCase("CAST")) { + realName = "CAST5"; + } else if (cryptoBase.equalsIgnoreCase("DES") && "EDE3".equalsIgnoreCase(cryptoVersion)) { + realName = "DESede"; + } else { + realName = cryptoBase; + } + + if (!BLOCK_MODES.contains(cryptoMode.toUpperCase())) { + cryptoVersion = cryptoMode; + cryptoMode = "CBC"; + } else if (cryptoMode.equalsIgnoreCase("CFB1")) { + // uglish SunJCE cryptoMode normalization. + cryptoMode = "CFB"; + } + + if (realName.equalsIgnoreCase("RC4")) { + realName = "RC4"; + cryptoMode = "NONE"; + paddingType = "NoPadding"; + } else { + realName = realName + "/" + cryptoMode + "/" + paddingType; + } + + return new String[]{cryptoBase, cryptoVersion, cryptoMode, realName, paddingType}; + } + } + + private static boolean tryCipher(final String rubyName) { + String cryptoMode = Algorithm.osslToJsse(rubyName, null)[3]; + try { + javax.crypto.Cipher.getInstance(cryptoMode); + return true; + } catch (NoSuchAlgorithmException nsae) { + try { + OpenSSLReal.getCipherBC(cryptoMode); + return true; + } catch (GeneralSecurityException gse) { + return false; + } + } catch (Exception e) { + return false; + } + } + + public Cipher(Ruby runtime, RubyClass type) { + super(runtime, type); + } + + private javax.crypto.Cipher ciph; + private String name; + private String cryptoBase; + private String cryptoVersion; + private String cryptoMode; + private String padding_type; + private String realName; + private int keyLen = -1; + private int generateKeyLen = -1; + private int ivLen = -1; + private boolean encryptMode = true; + //private IRubyObject[] modeParams; + private boolean ciphInited = false; + private byte[] key; + private byte[] realIV; + private byte[] orgIV; + private String padding; + + void dumpVars() { + System.out.println("***** Cipher instance vars ****"); + System.out.println("name = " + name); + System.out.println("cryptoBase = " + cryptoBase); + System.out.println("cryptoVersion = " + cryptoVersion); + System.out.println("cryptoMode = " + cryptoMode); + System.out.println("padding_type = " + padding_type); + System.out.println("realName = " + realName); + System.out.println("keyLen = " + keyLen); + System.out.println("ivLen = " + ivLen); + System.out.println("ciph block size = " + ciph.getBlockSize()); + System.out.println("encryptMode = " + encryptMode); + System.out.println("ciphInited = " + ciphInited); + System.out.println("key.length = " + (key == null ? 0 : key.length)); + System.out.println("iv.length = " + (this.realIV == null ? 0 : this.realIV.length)); + System.out.println("padding = " + padding); + System.out.println("ciphAlgo = " + ciph.getAlgorithm()); + System.out.println("*******************************"); + } + + @JRubyMethod(required = 1) + public IRubyObject initialize(IRubyObject str) { + name = str.toString(); + if (!CipherModule.isSupportedCipher(name)) { + throw newCipherError(getRuntime(), String.format("unsupported cipher algorithm (%s)", name)); + } + String[] values = Algorithm.osslToJsse(name, padding); + cryptoBase = values[0]; + cryptoVersion = values[1]; + cryptoMode = values[2]; + realName = values[3]; + padding_type = values[4]; + ciph = getCipher(); + + if (hasLen(cryptoBase) && null != cryptoVersion) { + try { + keyLen = Integer.parseInt(cryptoVersion) / 8; + } catch (NumberFormatException e) { + keyLen = -1; + } + } + if (keyLen == -1) { + if ("DES".equalsIgnoreCase(cryptoBase)) { + ivLen = 8; + if ("EDE3".equalsIgnoreCase(cryptoVersion)) { + keyLen = 24; + } else { + keyLen = 8; + } + generateKeyLen = keyLen / 8 * 7; + } else if ("RC4".equalsIgnoreCase(cryptoBase)) { + ivLen = 0; + keyLen = 16; + } else { + keyLen = 16; + try { + if ((javax.crypto.Cipher.getMaxAllowedKeyLength(name) / 8) < keyLen) { + keyLen = javax.crypto.Cipher.getMaxAllowedKeyLength(name) / 8; + } + } catch (Exception e) { + // I hate checked exceptions + } + } + } + + if (ivLen == -1) { + if ("AES".equalsIgnoreCase(cryptoBase)) { + ivLen = 16; + } else { + ivLen = 8; + } + } + + // given 'rc4' must be 'RC4' here. OpenSSL checks it as a LN of object + // ID and set SN. We don't check 'name' is allowed as a LN in ASN.1 for + // the possibility of JCE specific algorithm so just do upperCase here + // for OpenSSL compatibility. + name = name.toUpperCase(); + + return this; + } + + @Override + @JRubyMethod(required = 1) + public IRubyObject initialize_copy(IRubyObject obj) { + if (this == obj) { + return this; + } + + checkFrozen(); + + cryptoBase = ((Cipher) obj).cryptoBase; + cryptoVersion = ((Cipher) obj).cryptoVersion; + cryptoMode = ((Cipher) obj).cryptoMode; + padding_type = ((Cipher) obj).padding_type; + realName = ((Cipher) obj).realName; + name = ((Cipher) obj).name; + keyLen = ((Cipher) obj).keyLen; + ivLen = ((Cipher) obj).ivLen; + encryptMode = ((Cipher) obj).encryptMode; + ciphInited = false; + if (((Cipher) obj).key != null) { + key = new byte[((Cipher) obj).key.length]; + System.arraycopy(((Cipher) obj).key, 0, key, 0, key.length); + } else { + key = null; + } + if (((Cipher) obj).realIV != null) { + this.realIV = new byte[((Cipher) obj).realIV.length]; + System.arraycopy(((Cipher) obj).realIV, 0, this.realIV, 0, this.realIV.length); + } else { + this.realIV = null; + } + this.orgIV = this.realIV; + padding = ((Cipher) obj).padding; + + ciph = getCipher(); + + return this; + } + + @JRubyMethod + public IRubyObject name() { + return getRuntime().newString(name); + } + + @JRubyMethod + public IRubyObject key_len() { + return getRuntime().newFixnum(keyLen); + } + + @JRubyMethod + public IRubyObject iv_len() { + return getRuntime().newFixnum(ivLen); + } + + @JRubyMethod(name = "key_len=", required = 1) + public IRubyObject set_key_len(IRubyObject len) { + this.keyLen = RubyNumeric.fix2int(len); + return len; + } + + @JRubyMethod(name = "key=", required = 1) + public IRubyObject set_key(IRubyObject key) { + byte[] keyBytes; + try { + keyBytes = key.convertToString().getBytes(); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + throw newCipherError(getRuntime(), e.getMessage()); + } + if (keyBytes.length < keyLen) { + throw newCipherError(getRuntime(), "key length to short"); + } + + if (keyBytes.length > keyLen) { + byte[] keys = new byte[keyLen]; + System.arraycopy(keyBytes, 0, keys, 0, keyLen); + keyBytes = keys; + } + + this.key = keyBytes; + return key; + } + + @JRubyMethod(name = "iv=", required = 1) + public IRubyObject set_iv(IRubyObject iv) { + byte[] ivBytes; + try { + ivBytes = iv.convertToString().getBytes(); + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + throw newCipherError(getRuntime(), e.getMessage()); + } + if (ivBytes.length < ivLen) { + throw newCipherError(getRuntime(), "iv length to short"); + } else { + // EVP_CipherInit_ex uses leading IV length of given sequence. + byte[] iv2 = new byte[ivLen]; + System.arraycopy(ivBytes, 0, iv2, 0, ivLen); + this.realIV = iv2; + } + this.orgIV = this.realIV; + if (!isStreamCipher()) { + ciphInited = false; + } + return iv; + } + + @JRubyMethod + public IRubyObject block_size() { + if (isStreamCipher()) { + // getBlockSize() returns 0 for stream cipher in JCE. OpenSSL returns 1 for RC4. + return getRuntime().newFixnum(1); + } + return getRuntime().newFixnum(ciph.getBlockSize()); + } + + protected void init(IRubyObject[] args, boolean encrypt) { + org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 0, 2); + + encryptMode = encrypt; + ciphInited = false; + + if (args.length > 0) { + /* + * oops. this code mistakes salt for IV. + * We deprecated the arguments for this method, but we decided + * keeping this behaviour for backward compatibility. + */ + byte[] pass = args[0].convertToString().getBytes(); + byte[] iv = null; + try { + iv = "OpenSSL for Ruby rulez!".getBytes("ISO8859-1"); + byte[] iv2 = new byte[this.ivLen]; + System.arraycopy(iv, 0, iv2, 0, this.ivLen); + iv = iv2; + } catch (Exception e) { + } + + if (args.length > 1 && !args[1].isNil()) { + getRuntime().getWarnings().warning(ID.MISCELLANEOUS, "key derivation by " + getMetaClass().getRealClass().getName() + "#encrypt is deprecated; use " + getMetaClass().getRealClass().getName() + "::pkcs5_keyivgen instead"); + iv = args[1].convertToString().getBytes(); + if (iv.length > this.ivLen) { + byte[] iv2 = new byte[this.ivLen]; + System.arraycopy(iv, 0, iv2, 0, this.ivLen); + iv = iv2; + } + } + + MessageDigest digest = Digest.getDigest("MD5", getRuntime()); + OpenSSLImpl.KeyAndIv result = OpenSSLImpl.EVP_BytesToKey(keyLen, ivLen, digest, iv, pass, 2048); + this.key = result.getKey(); + this.realIV = iv; + this.orgIV = this.realIV; + } + } + + @JRubyMethod(optional = 2) + public IRubyObject encrypt(IRubyObject[] args) { + this.realIV = orgIV; + init(args, true); + return this; + } + + @JRubyMethod(optional = 2) + public IRubyObject decrypt(IRubyObject[] args) { + this.realIV = orgIV; + init(args, false); + return this; + } + + @JRubyMethod + public IRubyObject reset() { + if (!isStreamCipher()) { + this.realIV = orgIV; + doInitialize(); + } + return this; + } + + javax.crypto.Cipher getCipher() { + try { + return javax.crypto.Cipher.getInstance(realName); + } catch (NoSuchAlgorithmException e) { + try { + return OpenSSLReal.getCipherBC(realName); + } catch (GeneralSecurityException ignore) { + } + throw newCipherError(getRuntime(), "unsupported cipher algorithm (" + realName + ")"); + } catch (javax.crypto.NoSuchPaddingException e) { + throw newCipherError(getRuntime(), "unsupported cipher padding (" + realName + ")"); + } + } + + private static boolean hasLen(String cryptoBase) { + return "AES".equalsIgnoreCase(cryptoBase) || "RC2".equalsIgnoreCase(cryptoBase) || "RC4".equalsIgnoreCase(cryptoBase); + } + + @JRubyMethod(required = 1, optional = 3) + public IRubyObject pkcs5_keyivgen(IRubyObject[] args) { + org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 1, 4); + byte[] pass = args[0].convertToString().getBytes(); + byte[] salt = null; + int iter = 2048; + IRubyObject vdigest = getRuntime().getNil(); + if (args.length > 1) { + if (!args[1].isNil()) { + salt = args[1].convertToString().getBytes(); + } + if (args.length > 2) { + if (!args[2].isNil()) { + iter = RubyNumeric.fix2int(args[2]); + } + if (args.length > 3) { + vdigest = args[3]; + } + } + } + if (null != salt) { + if (salt.length != 8) { + throw newCipherError(getRuntime(), "salt must be an 8-octet string"); + } + } + + final String algorithm = vdigest.isNil() ? "MD5" : ((Digest) vdigest).getAlgorithm(); + MessageDigest digest = Digest.getDigest(algorithm, getRuntime()); + OpenSSLImpl.KeyAndIv result = OpenSSLImpl.EVP_BytesToKey(keyLen, ivLen, digest, salt, pass, iter); + this.key = result.getKey(); + this.realIV = result.getIv(); + this.orgIV = this.realIV; + + doInitialize(); + + return getRuntime().getNil(); + } + + private void doInitialize() { + if (DEBUG) { + System.out.println("*** doInitialize"); + dumpVars(); + } + ciphInited = true; + try { + assert (key.length * 8 == keyLen) || (key.length == keyLen) : "Key wrong length"; + assert (this.realIV.length * 8 == ivLen) || (this.realIV.length == ivLen) : "IV wrong length"; + if (!"ECB".equalsIgnoreCase(cryptoMode)) { + if (this.realIV == null) { + this.realIV = new byte[ivLen]; + System.arraycopy("OpenSSL for JRuby rulez".getBytes(), 0, + this.realIV, 0, ivLen); + } + if ("RC2".equalsIgnoreCase(cryptoBase)) { + this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey("RC2", this.key), new RC2ParameterSpec(this.key.length * 8, this.realIV)); + } else if ("RC4".equalsIgnoreCase(cryptoBase)) { + this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey("RC4", this.key)); + } else { + this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey(realName.split("/")[0], this.key), new IvParameterSpec(this.realIV)); + } + } else { + this.ciph.init(encryptMode ? javax.crypto.Cipher.ENCRYPT_MODE : javax.crypto.Cipher.DECRYPT_MODE, new SimpleSecretKey(realName.split("/")[0], this.key)); + } + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + throw newCipherError(getRuntime(), e.getMessage()); + } + } + private byte[] lastIv = null; + + @JRubyMethod + public IRubyObject update(IRubyObject data) { + if (DEBUG) { + System.out.println("*** update [" + data + "]"); + } + + byte[] val = data.convertToString().getBytes(); + if (val.length == 0) { + throw getRuntime().newArgumentError("data must not be empty"); + } + + if (!ciphInited) { + if (DEBUG) { + System.out.println("BEFORE INITING"); + } + doInitialize(); + if (DEBUG) { + System.out.println("AFTER INITING"); + } + } + + byte[] str = new byte[0]; + try { + byte[] out = ciph.update(val); + if (out != null) { + str = out; + + if (this.realIV != null) { + if (lastIv == null) { + lastIv = new byte[ivLen]; + } + byte[] tmpIv = encryptMode ? out : val; + if (tmpIv.length >= ivLen) { + System.arraycopy(tmpIv, tmpIv.length - ivLen, lastIv, 0, ivLen); + } + } + } + } catch (Exception e) { + if (DEBUG) { + e.printStackTrace(); + } + throw newCipherError(getRuntime(), e.getMessage()); + } + + return getRuntime().newString(new ByteList(str, false)); + } + + @JRubyMethod(name = "<<") + public IRubyObject update_deprecated(IRubyObject data) { + getRuntime().getWarnings().warn(IRubyWarnings.ID.DEPRECATED_METHOD, "" + this.getMetaClass().getRealClass().getName() + "#<< is deprecated; use " + this.getMetaClass().getRealClass().getName() + "#update instead"); + return update(data); + } + + @JRubyMethod(name = "final") + public IRubyObject _final() { + if (!ciphInited) { + doInitialize(); + } + // trying to allow update after final like cruby-openssl. Bad idea. + if ("RC4".equalsIgnoreCase(cryptoBase)) { + return getRuntime().newString(""); + } + ByteList str = new ByteList(ByteList.NULL_ARRAY); + try { + byte[] out = ciph.doFinal(); + if (out != null) { + str = new ByteList(out, false); + // TODO: Modifying this line appears to fix the issue, but I do + // not have a good reason for why. Best I can tell, lastIv needs + // to be set regardless of encryptMode, so we'll go with this + // for now. JRUBY-3335. + //if(this.realIV != null && encryptMode) { + if (this.realIV != null) { + if (lastIv == null) { + lastIv = new byte[ivLen]; + } + byte[] tmpIv = out; + if (tmpIv.length >= ivLen) { + System.arraycopy(tmpIv, tmpIv.length - ivLen, lastIv, 0, ivLen); + } + } + } + if (this.realIV != null) { + this.realIV = lastIv; + doInitialize(); + } + } catch (Exception e) { + throw newCipherError(getRuntime(), e.getMessage()); + } + return getRuntime().newString(str); + } + + @JRubyMethod(name = "padding=") + public IRubyObject set_padding(IRubyObject padding) { + this.padding = padding.toString(); + initialize(getRuntime().newString(name)); + return padding; + } + + String getAlgorithm() { + return this.ciph.getAlgorithm(); + } + + String getName() { + return this.name; + } + + String getCryptoBase() { + return this.cryptoBase; + } + + String getCryptoMode() { + return this.cryptoMode; + } + + int getGenerateKeyLen() { + return (generateKeyLen == -1) ? keyLen : generateKeyLen; + } + + private boolean isStreamCipher() { + return ciph.getBlockSize() == 0; + } + + private static RaiseException newCipherError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::Cipher::CipherError", message); + } +} diff --git a/src/org/jruby/ext/openssl/CipherStrings.java b/src/org/jruby/ext/openssl/CipherStrings.java new file mode 100644 index 00000000000..15cb992cead --- /dev/null +++ b/src/org/jruby/ext/openssl/CipherStrings.java @@ -0,0 +1,1856 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * + * @author Ola Bini + */ +public class CipherStrings { + public final static String SSL2_TXT_DES_64_CFB64_WITH_MD5_1 = "DES-CFB-M1"; + public final static String SSL2_TXT_NULL_WITH_MD5 = "NULL-MD5"; + public final static String SSL2_TXT_RC4_128_WITH_MD5 = "RC4-MD5"; + public final static String SSL2_TXT_RC4_128_EXPORT40_WITH_MD5 = "EXP-RC4-MD5"; + public final static String SSL2_TXT_RC2_128_CBC_WITH_MD5 = "RC2-CBC-MD5"; + public final static String SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 = "EXP-RC2-CBC-MD5"; + public final static String SSL2_TXT_IDEA_128_CBC_WITH_MD5 = "IDEA-CBC-MD5"; + public final static String SSL2_TXT_DES_64_CBC_WITH_MD5 = "DES-CBC-MD5"; + public final static String SSL2_TXT_DES_64_CBC_WITH_SHA = "DES-CBC-SHA"; + public final static String SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5 = "DES-CBC3-MD5"; + public final static String SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA = "DES-CBC3-SHA"; + public final static String SSL2_TXT_RC4_64_WITH_MD5 = "RC4-64-MD5"; + public final static String SSL2_TXT_NULL = "NULL"; + + public final static String SSL3_TXT_RSA_NULL_MD5 = "NULL-MD5"; + public final static String SSL3_TXT_RSA_NULL_SHA = "NULL-SHA"; + public final static String SSL3_TXT_RSA_RC4_40_MD5 = "EXP-RC4-MD5"; + public final static String SSL3_TXT_RSA_RC4_128_MD5 = "RC4-MD5"; + public final static String SSL3_TXT_RSA_RC4_128_SHA = "RC4-SHA"; + public final static String SSL3_TXT_RSA_RC2_40_MD5 = "EXP-RC2-CBC-MD5"; + public final static String SSL3_TXT_RSA_IDEA_128_SHA = "IDEA-CBC-SHA"; + public final static String SSL3_TXT_RSA_DES_40_CBC_SHA = "EXP-DES-CBC-SHA"; + public final static String SSL3_TXT_RSA_DES_64_CBC_SHA = "DES-CBC-SHA"; + public final static String SSL3_TXT_RSA_DES_192_CBC3_SHA = "DES-CBC3-SHA"; + public final static String SSL3_TXT_DH_DSS_DES_40_CBC_SHA = "EXP-DH-DSS-DES-CBC-SHA"; + public final static String SSL3_TXT_DH_DSS_DES_64_CBC_SHA = "DH-DSS-DES-CBC-SHA"; + public final static String SSL3_TXT_DH_DSS_DES_192_CBC3_SHA = "DH-DSS-DES-CBC3-SHA"; + public final static String SSL3_TXT_DH_RSA_DES_40_CBC_SHA = "EXP-DH-RSA-DES-CBC-SHA"; + public final static String SSL3_TXT_DH_RSA_DES_64_CBC_SHA = "DH-RSA-DES-CBC-SHA"; + public final static String SSL3_TXT_DH_RSA_DES_192_CBC3_SHA = "DH-RSA-DES-CBC3-SHA"; + public final static String SSL3_TXT_EDH_DSS_DES_40_CBC_SHA = "EXP-EDH-DSS-DES-CBC-SHA"; + public final static String SSL3_TXT_EDH_DSS_DES_64_CBC_SHA = "EDH-DSS-DES-CBC-SHA"; + public final static String SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA = "EDH-DSS-DES-CBC3-SHA"; + public final static String SSL3_TXT_EDH_RSA_DES_40_CBC_SHA = "EXP-EDH-RSA-DES-CBC-SHA"; + public final static String SSL3_TXT_EDH_RSA_DES_64_CBC_SHA = "EDH-RSA-DES-CBC-SHA"; + public final static String SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA = "EDH-RSA-DES-CBC3-SHA"; + public final static String SSL3_TXT_ADH_RC4_40_MD5 = "EXP-ADH-RC4-MD5"; + public final static String SSL3_TXT_ADH_RC4_128_MD5 = "ADH-RC4-MD5"; + public final static String SSL3_TXT_ADH_DES_40_CBC_SHA = "EXP-ADH-DES-CBC-SHA"; + public final static String SSL3_TXT_ADH_DES_64_CBC_SHA = "ADH-DES-CBC-SHA"; + public final static String SSL3_TXT_ADH_DES_192_CBC_SHA = "ADH-DES-CBC3-SHA"; + public final static String SSL3_TXT_FZA_DMS_NULL_SHA = "FZA-NULL-SHA"; + public final static String SSL3_TXT_FZA_DMS_FZA_SHA = "FZA-FZA-CBC-SHA"; + public final static String SSL3_TXT_FZA_DMS_RC4_SHA = "FZA-RC4-SHA"; + public final static String SSL3_TXT_KRB5_DES_64_CBC_SHA = "KRB5-DES-CBC-SHA"; + public final static String SSL3_TXT_KRB5_DES_192_CBC3_SHA = "KRB5-DES-CBC3-SHA"; + public final static String SSL3_TXT_KRB5_RC4_128_SHA = "KRB5-RC4-SHA"; + public final static String SSL3_TXT_KRB5_IDEA_128_CBC_SHA = "KRB5-IDEA-CBC-SHA"; + public final static String SSL3_TXT_KRB5_DES_64_CBC_MD5 = "KRB5-DES-CBC-MD5"; + public final static String SSL3_TXT_KRB5_DES_192_CBC3_MD5 = "KRB5-DES-CBC3-MD5"; + public final static String SSL3_TXT_KRB5_RC4_128_MD5 = "KRB5-RC4-MD5"; + public final static String SSL3_TXT_KRB5_IDEA_128_CBC_MD5 = "KRB5-IDEA-CBC-MD5"; + public final static String SSL3_TXT_KRB5_DES_40_CBC_SHA = "EXP-KRB5-DES-CBC-SHA"; + public final static String SSL3_TXT_KRB5_RC2_40_CBC_SHA = "EXP-KRB5-RC2-CBC-SHA"; + public final static String SSL3_TXT_KRB5_RC4_40_SHA = "EXP-KRB5-RC4-SHA"; + public final static String SSL3_TXT_KRB5_DES_40_CBC_MD5 = "EXP-KRB5-DES-CBC-MD5"; + public final static String SSL3_TXT_KRB5_RC2_40_CBC_MD5 = "EXP-KRB5-RC2-CBC-MD5"; + public final static String SSL3_TXT_KRB5_RC4_40_MD5 = "EXP-KRB5-RC4-MD5"; + + public final static String SSL_TXT_NULL_WITH_MD5 = SSL2_TXT_NULL_WITH_MD5; + public final static String SSL_TXT_RC4_128_WITH_MD5 = SSL2_TXT_RC4_128_WITH_MD5; + public final static String SSL_TXT_RC4_128_EXPORT40_WITH_MD5 = SSL2_TXT_RC4_128_EXPORT40_WITH_MD5; + public final static String SSL_TXT_RC2_128_CBC_WITH_MD5 = SSL2_TXT_RC2_128_CBC_WITH_MD5; + public final static String SSL_TXT_RC2_128_CBC_EXPORT40_WITH_MD5 = SSL2_TXT_RC2_128_CBC_EXPORT40_WITH_MD5; + public final static String SSL_TXT_IDEA_128_CBC_WITH_MD5 = SSL2_TXT_IDEA_128_CBC_WITH_MD5; + public final static String SSL_TXT_DES_64_CBC_WITH_MD5 = SSL2_TXT_DES_64_CBC_WITH_MD5; + public final static String SSL_TXT_DES_64_CBC_WITH_SHA = SSL2_TXT_DES_64_CBC_WITH_SHA; + public final static String SSL_TXT_DES_192_EDE3_CBC_WITH_MD5 = SSL2_TXT_DES_192_EDE3_CBC_WITH_MD5; + public final static String SSL_TXT_DES_192_EDE3_CBC_WITH_SHA = SSL2_TXT_DES_192_EDE3_CBC_WITH_SHA; + + public final static String SSL_TXT_KRB5_DES_64_CBC_SHA = SSL3_TXT_KRB5_DES_64_CBC_SHA; + public final static String SSL_TXT_KRB5_DES_192_CBC3_SHA = SSL3_TXT_KRB5_DES_192_CBC3_SHA; + public final static String SSL_TXT_KRB5_RC4_128_SHA = SSL3_TXT_KRB5_RC4_128_SHA; + public final static String SSL_TXT_KRB5_IDEA_128_CBC_SHA = SSL3_TXT_KRB5_IDEA_128_CBC_SHA; + public final static String SSL_TXT_KRB5_DES_64_CBC_MD5 = SSL3_TXT_KRB5_DES_64_CBC_MD5; + public final static String SSL_TXT_KRB5_DES_192_CBC3_MD5 = SSL3_TXT_KRB5_DES_192_CBC3_MD5; + public final static String SSL_TXT_KRB5_RC4_128_MD5 = SSL3_TXT_KRB5_RC4_128_MD5; + public final static String SSL_TXT_KRB5_IDEA_128_CBC_MD5 = SSL3_TXT_KRB5_IDEA_128_CBC_MD5; + + public final static String SSL_TXT_KRB5_DES_40_CBC_SHA = SSL3_TXT_KRB5_DES_40_CBC_SHA; + public final static String SSL_TXT_KRB5_RC2_40_CBC_SHA = SSL3_TXT_KRB5_RC2_40_CBC_SHA; + public final static String SSL_TXT_KRB5_RC4_40_SHA = SSL3_TXT_KRB5_RC4_40_SHA; + public final static String SSL_TXT_KRB5_DES_40_CBC_MD5 = SSL3_TXT_KRB5_DES_40_CBC_MD5; + public final static String SSL_TXT_KRB5_RC2_40_CBC_MD5 = SSL3_TXT_KRB5_RC2_40_CBC_MD5; + public final static String SSL_TXT_KRB5_RC4_40_MD5 = SSL3_TXT_KRB5_RC4_40_MD5; + + public final static String SSL_TXT_LOW = "LOW"; + public final static String SSL_TXT_MEDIUM = "MEDIUM"; + public final static String SSL_TXT_HIGH = "HIGH"; + public final static String SSL_TXT_kFZA = "kFZA"; + public final static String SSL_TXT_aFZA = "aFZA"; + public final static String SSL_TXT_eFZA = "eFZA"; + public final static String SSL_TXT_FZA = "FZA"; + + public final static String SSL_TXT_aNULL = "aNULL"; + public final static String SSL_TXT_eNULL = "eNULL"; + public final static String SSL_TXT_NULL = "NULL"; + + public final static String SSL_TXT_kKRB5 = "kKRB5"; + public final static String SSL_TXT_aKRB5 = "aKRB5"; + public final static String SSL_TXT_KRB5 = "KRB5"; + + public final static String SSL_TXT_kRSA = "kRSA"; + public final static String SSL_TXT_kDHr = "kDHr"; + public final static String SSL_TXT_kDHd = "kDHd"; + public final static String SSL_TXT_kEDH = "kEDH"; + public final static String SSL_TXT_aRSA = "aRSA"; + public final static String SSL_TXT_aDSS = "aDSS"; + public final static String SSL_TXT_aDH = "aDH"; + public final static String SSL_TXT_DSS = "DSS"; + public final static String SSL_TXT_DH = "DH"; + public final static String SSL_TXT_EDH = "EDH"; + public final static String SSL_TXT_ADH = "ADH"; + public final static String SSL_TXT_RSA = "RSA"; + public final static String SSL_TXT_DES = "DES"; + public final static String SSL_TXT_3DES = "3DES"; + public final static String SSL_TXT_RC4 = "RC4"; + public final static String SSL_TXT_RC2 = "RC2"; + public final static String SSL_TXT_IDEA = "IDEA"; + public final static String SSL_TXT_AES = "AES"; + public final static String SSL_TXT_MD5 = "MD5"; + public final static String SSL_TXT_SHA1 = "SHA1"; + public final static String SSL_TXT_SHA = "SHA"; + public final static String SSL_TXT_EXP = "EXP"; + public final static String SSL_TXT_EXPORT = "EXPORT"; + public final static String SSL_TXT_EXP40 = "EXPORT40"; + public final static String SSL_TXT_EXP56 = "EXPORT56"; + public final static String SSL_TXT_SSLV2 = "SSLv2"; + public final static String SSL_TXT_SSLV3 = "SSLv3"; + public final static String SSL_TXT_TLSV1 = "TLSv1"; + public final static String SSL_TXT_ALL = "ALL"; + public final static String SSL_TXT_ECC = "ECCdraft"; + + public final static String SSL_TXT_CMPALL = "COMPLEMENTOFALL"; + public final static String SSL_TXT_CMPDEF = "COMPLEMENTOFDEFAULT"; + + // "ALL:!aNULL:!eNULL:!SSLv2" is for OpenSSL 1.0.0 GA + public final static String SSL_DEFAULT_CIPHER_LIST = "AES:ALL:!aNULL:!eNULL:+RC4:@STRENGTH"; + + public final static long SSL_MKEY_MASK = 0x000000FFL; + public final static long SSL_kRSA = 0x00000001L; + public final static long SSL_kDHr = 0x00000002L; + public final static long SSL_kDHd = 0x00000004L; + public final static long SSL_kFZA = 0x00000008L; + public final static long SSL_kEDH = 0x00000010L; + public final static long SSL_kKRB5 = 0x00000020L; + public final static long SSL_kECDH = 0x00000040L; + public final static long SSL_kECDHE = 0x00000080L; + public final static long SSL_aNULL = 0x00000800L; + public final static long SSL_AUTH_MASK = 0x00007F00L; + public final static long SSL_EDH = (SSL_kEDH|(SSL_AUTH_MASK^SSL_aNULL)); + public final static long SSL_aRSA = 0x00000100L; + public final static long SSL_aDSS = 0x00000200L; + public final static long SSL_DSS = SSL_aDSS; + public final static long SSL_aFZA = 0x00000400L; + public final static long SSL_aDH = 0x00001000L; + public final static long SSL_aKRB5 = 0x00002000L; + public final static long SSL_aECDSA = 0x00004000L; + public final static long SSL_eNULL = 0x00200000L; + public final static long SSL_eFZA = 0x00100000L; + public final static long SSL_NULL = (SSL_eNULL); + public final static long SSL_ADH = (SSL_kEDH|SSL_aNULL); + public final static long SSL_RSA = (SSL_kRSA|SSL_aRSA); + public final static long SSL_DH = (SSL_kDHr|SSL_kDHd|SSL_kEDH); + public final static long SSL_ECDH = (SSL_kECDH|SSL_kECDHE); + public final static long SSL_FZA = (SSL_aFZA|SSL_kFZA|SSL_eFZA); + public final static long SSL_KRB5 = (SSL_kKRB5|SSL_aKRB5); + public final static long SSL_ENC_MASK = 0x043F8000L; + public final static long SSL_DES = 0x00008000L; + public final static long SSL_3DES = 0x00010000L; + public final static long SSL_RC4 = 0x00020000L; + public final static long SSL_RC2 = 0x00040000L; + public final static long SSL_IDEA = 0x00080000L; + public final static long SSL_AES = 0x04000000L; + public final static long SSL_MAC_MASK = 0x00c00000L; + public final static long SSL_MD5 = 0x00400000L; + public final static long SSL_SHA1 = 0x00800000L; + public final static long SSL_SHA = (SSL_SHA1); + public final static long SSL_SSL_MASK = 0x03000000L; + public final static long SSL_SSLV2 = 0x01000000L; + public final static long SSL_SSLV3 = 0x02000000L; + public final static long SSL_TLSV1 = SSL_SSLV3; + public final static long SSL_EXP_MASK = 0x00000003L; + public final static long SSL_NOT_EXP = 0x00000001L; + public final static long SSL_EXPORT = 0x00000002L; + public final static long SSL_STRONG_MASK = 0x000000fcL; + public final static long SSL_STRONG_NONE = 0x00000004L; + public final static long SSL_EXP40 = 0x00000008L; + public final static long SSL_MICRO = (SSL_EXP40); + public final static long SSL_EXP56 = 0x00000010L; + public final static long SSL_MINI = (SSL_EXP56); + public final static long SSL_LOW = 0x00000020L; + public final static long SSL_MEDIUM = 0x00000040L; + public final static long SSL_HIGH = 0x00000080L; + public final static long SSL_ALL = 0xffffffffL; + public final static long SSL_ALL_CIPHERS = (SSL_MKEY_MASK|SSL_AUTH_MASK|SSL_ENC_MASK|SSL_MAC_MASK); + public final static long SSL_ALL_STRENGTHS = (SSL_EXP_MASK|SSL_STRONG_MASK); + public final static long SSL_PKEY_RSA_ENC = 0; + public final static long SSL_PKEY_RSA_SIGN = 1; + public final static long SSL_PKEY_DSA_SIGN = 2; + public final static long SSL_PKEY_DH_RSA = 3; + public final static long SSL_PKEY_DH_DSA = 4; + public final static long SSL_PKEY_ECC = 5; + public final static long SSL_PKEY_NUM = 6; + + public final static long SSL3_CK_RSA_NULL_MD5 = 0x03000001; + public final static long SSL3_CK_RSA_NULL_SHA = 0x03000002; + public final static long SSL3_CK_RSA_RC4_40_MD5 = 0x03000003; + public final static long SSL3_CK_RSA_RC4_128_MD5 = 0x03000004; + public final static long SSL3_CK_RSA_RC4_128_SHA = 0x03000005; + public final static long SSL3_CK_RSA_RC2_40_MD5 = 0x03000006; + public final static long SSL3_CK_RSA_IDEA_128_SHA = 0x03000007; + public final static long SSL3_CK_RSA_DES_40_CBC_SHA = 0x03000008; + public final static long SSL3_CK_RSA_DES_64_CBC_SHA = 0x03000009; + public final static long SSL3_CK_RSA_DES_192_CBC3_SHA = 0x0300000A; + public final static long SSL3_CK_DH_DSS_DES_40_CBC_SHA = 0x0300000B; + public final static long SSL3_CK_DH_DSS_DES_64_CBC_SHA = 0x0300000C; + public final static long SSL3_CK_DH_DSS_DES_192_CBC3_SHA = 0x0300000D; + public final static long SSL3_CK_DH_RSA_DES_40_CBC_SHA = 0x0300000E; + public final static long SSL3_CK_DH_RSA_DES_64_CBC_SHA = 0x0300000F; + public final static long SSL3_CK_DH_RSA_DES_192_CBC3_SHA = 0x03000010; + public final static long SSL3_CK_EDH_DSS_DES_40_CBC_SHA = 0x03000011; + public final static long SSL3_CK_EDH_DSS_DES_64_CBC_SHA = 0x03000012; + public final static long SSL3_CK_EDH_DSS_DES_192_CBC3_SHA = 0x03000013; + public final static long SSL3_CK_EDH_RSA_DES_40_CBC_SHA = 0x03000014; + public final static long SSL3_CK_EDH_RSA_DES_64_CBC_SHA = 0x03000015; + public final static long SSL3_CK_EDH_RSA_DES_192_CBC3_SHA = 0x03000016; + public final static long SSL3_CK_ADH_RC4_40_MD5 = 0x03000017; + public final static long SSL3_CK_ADH_RC4_128_MD5 = 0x03000018; + public final static long SSL3_CK_ADH_DES_40_CBC_SHA = 0x03000019; + public final static long SSL3_CK_ADH_DES_64_CBC_SHA = 0x0300001A; + public final static long SSL3_CK_ADH_DES_192_CBC_SHA = 0x0300001B; + public final static long SSL3_CK_FZA_DMS_NULL_SHA = 0x0300001C; + public final static long SSL3_CK_FZA_DMS_FZA_SHA = 0x0300001D; + public final static long SSL3_CK_KRB5_DES_64_CBC_SHA = 0x0300001E; + public final static long SSL3_CK_KRB5_DES_192_CBC3_SHA = 0x0300001F; + public final static long SSL3_CK_KRB5_RC4_128_SHA = 0x03000020; + public final static long SSL3_CK_KRB5_IDEA_128_CBC_SHA = 0x03000021; + public final static long SSL3_CK_KRB5_DES_64_CBC_MD5 = 0x03000022; + public final static long SSL3_CK_KRB5_DES_192_CBC3_MD5 = 0x03000023; + public final static long SSL3_CK_KRB5_RC4_128_MD5 = 0x03000024; + public final static long SSL3_CK_KRB5_IDEA_128_CBC_MD5 = 0x03000025; + public final static long SSL3_CK_KRB5_DES_40_CBC_SHA = 0x03000026; + public final static long SSL3_CK_KRB5_RC2_40_CBC_SHA = 0x03000027; + public final static long SSL3_CK_KRB5_RC4_40_SHA = 0x03000028; + public final static long SSL3_CK_KRB5_DES_40_CBC_MD5 = 0x03000029; + public final static long SSL3_CK_KRB5_RC2_40_CBC_MD5 = 0x0300002A; + public final static long SSL3_CK_KRB5_RC4_40_MD5 = 0x0300002B; + + + public final static long TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5 = 0x03000060; + public final static long TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 = 0x03000061; + public final static long TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA = 0x03000062; + public final static long TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA = 0x03000063; + public final static long TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA = 0x03000064; + public final static long TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA = 0x03000065; + public final static long TLS1_CK_DHE_DSS_WITH_RC4_128_SHA = 0x03000066; + public final static long TLS1_CK_RSA_WITH_AES_128_SHA = 0x0300002F; + public final static long TLS1_CK_DH_DSS_WITH_AES_128_SHA = 0x03000030; + public final static long TLS1_CK_DH_RSA_WITH_AES_128_SHA = 0x03000031; + public final static long TLS1_CK_DHE_DSS_WITH_AES_128_SHA = 0x03000032; + public final static long TLS1_CK_DHE_RSA_WITH_AES_128_SHA = 0x03000033; + public final static long TLS1_CK_ADH_WITH_AES_128_SHA = 0x03000034; + public final static long TLS1_CK_RSA_WITH_AES_256_SHA = 0x03000035; + public final static long TLS1_CK_DH_DSS_WITH_AES_256_SHA = 0x03000036; + public final static long TLS1_CK_DH_RSA_WITH_AES_256_SHA = 0x03000037; + public final static long TLS1_CK_DHE_DSS_WITH_AES_256_SHA = 0x03000038; + public final static long TLS1_CK_DHE_RSA_WITH_AES_256_SHA = 0x03000039; + public final static long TLS1_CK_ADH_WITH_AES_256_SHA = 0x0300003A; + public final static long TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA = 0x0300C001; + public final static long TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA = 0x0300C002; + public final static long TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA = 0x0300C003; + public final static long TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0x0300C004; + public final static long TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0x0300C005; + public final static long TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA = 0x0300C006; + public final static long TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA = 0x0300C007; + public final static long TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA = 0x0300C008; + public final static long TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0x0300C009; + public final static long TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0x0300C00A; + public final static long TLS1_CK_ECDH_RSA_WITH_NULL_SHA = 0x0300C00B; + public final static long TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA = 0x0300C00C; + public final static long TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA = 0x0300C00D; + public final static long TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA = 0x0300C00E; + public final static long TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA = 0x0300C00F; + public final static long TLS1_CK_ECDHE_RSA_WITH_NULL_SHA = 0x0300C010; + public final static long TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA = 0x0300C011; + public final static long TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA = 0x0300C012; + public final static long TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0x0300C013; + public final static long TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0x0300C014; + public final static long TLS1_CK_ECDH_anon_WITH_NULL_SHA = 0x0300C015; + public final static long TLS1_CK_ECDH_anon_WITH_RC4_128_SHA = 0x0300C016; + public final static long TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA = 0x0300C017; + public final static long TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA = 0x0300C018; + public final static long TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA = 0x0300C019; + + public final static String TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5 = "EXP1024-RC4-MD5"; + public final static String TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 = "EXP1024-RC2-CBC-MD5"; + public final static String TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA = "EXP1024-DES-CBC-SHA"; + public final static String TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA = "EXP1024-DHE-DSS-DES-CBC-SHA"; + public final static String TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA = "EXP1024-RC4-SHA"; + public final static String TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA = "EXP1024-DHE-DSS-RC4-SHA"; + public final static String TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA = "DHE-DSS-RC4-SHA"; + public final static String TLS1_TXT_RSA_WITH_AES_128_SHA = "AES128-SHA"; + public final static String TLS1_TXT_DH_DSS_WITH_AES_128_SHA = "DH-DSS-AES128-SHA"; + public final static String TLS1_TXT_DH_RSA_WITH_AES_128_SHA = "DH-RSA-AES128-SHA"; + public final static String TLS1_TXT_DHE_DSS_WITH_AES_128_SHA = "DHE-DSS-AES128-SHA"; + public final static String TLS1_TXT_DHE_RSA_WITH_AES_128_SHA = "DHE-RSA-AES128-SHA"; + public final static String TLS1_TXT_ADH_WITH_AES_128_SHA = "ADH-AES128-SHA"; + public final static String TLS1_TXT_RSA_WITH_AES_256_SHA = "AES256-SHA"; + public final static String TLS1_TXT_DH_DSS_WITH_AES_256_SHA = "DH-DSS-AES256-SHA"; + public final static String TLS1_TXT_DH_RSA_WITH_AES_256_SHA = "DH-RSA-AES256-SHA"; + public final static String TLS1_TXT_DHE_DSS_WITH_AES_256_SHA = "DHE-DSS-AES256-SHA"; + public final static String TLS1_TXT_DHE_RSA_WITH_AES_256_SHA = "DHE-RSA-AES256-SHA"; + public final static String TLS1_TXT_ADH_WITH_AES_256_SHA = "ADH-AES256-SHA"; + public final static String TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA = "ECDH-ECDSA-NULL-SHA"; + public final static String TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA = "ECDH-ECDSA-RC4-SHA"; + public final static String TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA = "ECDH-ECDSA-DES-CBC3-SHA"; + public final static String TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA = "ECDH-ECDSA-AES128-SHA"; + public final static String TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA = "ECDH-ECDSA-AES256-SHA"; + public final static String TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA = "ECDHE-ECDSA-NULL-SHA"; + public final static String TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA = "ECDHE-ECDSA-RC4-SHA"; + public final static String TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA = "ECDHE-ECDSA-DES-CBC3-SHA"; + public final static String TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = "ECDHE-ECDSA-AES128-SHA"; + public final static String TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = "ECDHE-ECDSA-AES256-SHA"; + public final static String TLS1_TXT_ECDH_RSA_WITH_NULL_SHA = "ECDH-RSA-NULL-SHA"; + public final static String TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA = "ECDH-RSA-RC4-SHA"; + public final static String TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA = "ECDH-RSA-DES-CBC3-SHA"; + public final static String TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA = "ECDH-RSA-AES128-SHA"; + public final static String TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA = "ECDH-RSA-AES256-SHA"; + public final static String TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA = "ECDHE-RSA-NULL-SHA"; + public final static String TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA = "ECDHE-RSA-RC4-SHA"; + public final static String TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA = "ECDHE-RSA-DES-CBC3-SHA"; + public final static String TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA = "ECDHE-RSA-AES128-SHA"; + public final static String TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA = "ECDHE-RSA-AES256-SHA"; + public final static String TLS1_TXT_ECDH_anon_WITH_NULL_SHA = "AECDH-NULL-SHA"; + public final static String TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA = "AECDH-RC4-SHA"; + public final static String TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA = "AECDH-DES-CBC3-SHA"; + public final static String TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA = "AECDH-AES128-SHA"; + public final static String TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA = "AECDH-AES256-SHA"; + + public static class Def { + public final int valid; + public final String name; + public final long id; + public final long algorithms; + public final long algo_strength; + public final long algorithm2; + public final int strength_bits; + public final int alg_bits; + public final long mask; + public final long mask_strength; + public String cipherSuite; + public Def(int valid, String name, long id, long algorithms, long algo_strength, long algorithm2, int strength_bits, int alg_bits, long mask, long mask_strength) { + this.valid = valid; + this.name = name; + this.id = id; + this.algorithms = algorithms; + this.algo_strength = algo_strength; + this.algorithm2 = algorithm2; + this.strength_bits = strength_bits; + this.alg_bits = alg_bits; + this.mask = mask; + this.mask_strength = mask_strength; + } + + @Override + public int hashCode() { + return name.hashCode(); + } + + @Override + public boolean equals(Object other) { + boolean ret = this == other; + if(!ret && (other instanceof Def)) { + ret = this.name.equals(((Def)other).name); + } + return ret; + } + + @Override + public String toString() { + return "Cipher<" + name + ">"; + } + + // from ssl_cipher_apply_rule + public boolean matches(Def current) { +// ma = mask & cp->algorithms; +// ma_s = mask_strength & cp->algo_strength; +// +// // Select: if none of the mask bit was met from the +// // cipher or not all of the bits were met, the +// // selection does not apply. +// if (((ma == 0) && (ma_s == 0)) || +// ((ma & algorithms) != ma) || +// ((ma_s & algo_strength) != ma_s)) +// continue; // does not apply +// } + long ma = mask & current.algorithms; + long ma_s = mask_strength & current.algo_strength; + if (((ma == 0) && (ma_s == 0)) || + ((ma & algorithms) != ma) || + ((ma_s & algo_strength) != ma_s)) { + return false; + } + return true; + } + } + + public final static Map Definitions = new HashMap(); + public final static List Ciphers = new ArrayList(); + public final static Map CipherNames = new HashMap(); + public final static Map SuiteToOSSL = new HashMap(); + + public static List getMatchingCiphers(String str, String[] all) { + String[] parts = str.split("[:, ]+"); + List currentList = new ArrayList(); + Set removed = new HashSet(); + + for (String part : parts) { + if (part.equals("@STRENGTH")) { + Collections.sort(currentList, new Comparator() { + + public int compare(Def first, Def second) { + return second.strength_bits - first.strength_bits; + } + }); + continue; + } + int index = 0; + switch (part.charAt(0)) { + case '!': + index++; + break; + case '+': + index++; + break; + case '-': + index++; + break; + } + List matching = getMatching(part.substring(index), all); + if (matching != null) { + if (index > 0) { + switch (part.charAt(0)) { + case '!': + currentList.removeAll(matching); + removed.addAll(matching); + break; + case '+': // '+' is for moving entry in the list. + for (Def ele : matching) { + if (!removed.contains(ele) && currentList.contains(ele)) { + currentList.remove(ele); + currentList.add(ele); + } + } + break; + case '-': + currentList.removeAll(matching); + break; + } + } else { + for (Def ele : matching) { + if (!removed.contains(ele) && !currentList.contains(ele)) { + currentList.add(ele); + } + } + } + } + } + return currentList; + } + + private static List getMatching(String definition, String[] all) { + List matching = null; + for (String name : definition.split("[+]")) { + Def pattern = Definitions.get(name); + if (pattern != null) { + if (matching == null) { + matching = getMatchingPattern(pattern, all); + } else { + List updated = new ArrayList(); + for (Def ele : getMatchingPattern(pattern, all)) { + if (matching.contains(ele)) { + updated.add(ele); + } + } + matching = updated; + } + } + } + return matching; + } + + private static List getMatchingPattern(Def pattern, String[] all) { + List matching = new ArrayList(); + for (String entry : all) { + String ossl = SuiteToOSSL.get(entry); + if (ossl != null) { + Def def = CipherNames.get(ossl); + if (def != null) { + def.cipherSuite = entry; + if (pattern.matches(def)) { + matching.add(def); + } + } + } + } + return matching; + } + + private static void addAlias(String cipherSuite, String ossl) { + SuiteToOSSL.put(cipherSuite, ossl); + } + + static { + Definitions.put(SSL_TXT_ALL,new Def(0,SSL_TXT_ALL, 0,SSL_ALL & ~SSL_eNULL & ~SSL_kECDH & ~SSL_kECDHE, SSL_ALL ,0,0,0,SSL_ALL,SSL_ALL)); + Definitions.put(SSL_TXT_CMPALL,new Def(0,SSL_TXT_CMPALL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_CMPDEF,new Def(0,SSL_TXT_CMPDEF,0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_kKRB5,new Def(0,SSL_TXT_kKRB5,0,SSL_kKRB5,0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_kRSA,new Def(0,SSL_TXT_kRSA,0,SSL_kRSA, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_kDHr,new Def(0,SSL_TXT_kDHr,0,SSL_kDHr, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_kDHd,new Def(0,SSL_TXT_kDHd,0,SSL_kDHd, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_kEDH,new Def(0,SSL_TXT_kEDH,0,SSL_kEDH, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_kFZA,new Def(0,SSL_TXT_kFZA,0,SSL_kFZA, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_DH,new Def(0,SSL_TXT_DH, 0,SSL_DH, 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_ECC,new Def(0,SSL_TXT_ECC, 0,(SSL_kECDH|SSL_kECDHE), 0,0,0,0,SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_EDH,new Def(0,SSL_TXT_EDH, 0,SSL_EDH, 0,0,0,0,SSL_MKEY_MASK|SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aKRB5,new Def(0,SSL_TXT_aKRB5,0,SSL_aKRB5,0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aRSA,new Def(0,SSL_TXT_aRSA,0,SSL_aRSA, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aDSS,new Def(0,SSL_TXT_aDSS,0,SSL_aDSS, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aFZA,new Def(0,SSL_TXT_aFZA,0,SSL_aFZA, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aNULL,new Def(0,SSL_TXT_aNULL,0,SSL_aNULL,0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_aDH,new Def(0,SSL_TXT_aDH, 0,SSL_aDH, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_DSS,new Def(0,SSL_TXT_DSS, 0,SSL_DSS, 0,0,0,0,SSL_AUTH_MASK,0)); + Definitions.put(SSL_TXT_DES,new Def(0,SSL_TXT_DES, 0,SSL_DES, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_3DES,new Def(0,SSL_TXT_3DES,0,SSL_3DES, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_RC4,new Def(0,SSL_TXT_RC4, 0,SSL_RC4, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_RC2,new Def(0,SSL_TXT_RC2, 0,SSL_RC2, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_IDEA,new Def(0,SSL_TXT_IDEA,0,SSL_IDEA, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_eNULL,new Def(0,SSL_TXT_eNULL,0,SSL_eNULL,0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_eFZA,new Def(0,SSL_TXT_eFZA,0,SSL_eFZA, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_AES,new Def(0,SSL_TXT_AES, 0,SSL_AES, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_MD5,new Def(0,SSL_TXT_MD5, 0,SSL_MD5, 0,0,0,0,SSL_MAC_MASK,0)); + Definitions.put(SSL_TXT_SHA1,new Def(0,SSL_TXT_SHA1,0,SSL_SHA1, 0,0,0,0,SSL_MAC_MASK,0)); + Definitions.put(SSL_TXT_SHA,new Def(0,SSL_TXT_SHA, 0,SSL_SHA, 0,0,0,0,SSL_MAC_MASK,0)); + Definitions.put(SSL_TXT_NULL,new Def(0,SSL_TXT_NULL,0,SSL_NULL, 0,0,0,0,SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_KRB5,new Def(0,SSL_TXT_KRB5,0,SSL_KRB5, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_RSA,new Def(0,SSL_TXT_RSA, 0,SSL_RSA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_ADH,new Def(0,SSL_TXT_ADH, 0,SSL_ADH, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK,0)); + Definitions.put(SSL_TXT_FZA,new Def(0,SSL_TXT_FZA, 0,SSL_FZA, 0,0,0,0,SSL_AUTH_MASK|SSL_MKEY_MASK|SSL_ENC_MASK,0)); + Definitions.put(SSL_TXT_SSLV2,new Def(0,SSL_TXT_SSLV2, 0,SSL_SSLV2, 0,0,0,0,SSL_SSL_MASK,0)); + Definitions.put(SSL_TXT_SSLV3,new Def(0,SSL_TXT_SSLV3, 0,SSL_SSLV3, 0,0,0,0,SSL_SSL_MASK,0)); + Definitions.put(SSL_TXT_TLSV1,new Def(0,SSL_TXT_TLSV1, 0,SSL_TLSV1, 0,0,0,0,SSL_SSL_MASK,0)); + Definitions.put(SSL_TXT_EXP,new Def(0,SSL_TXT_EXP ,0, 0,SSL_EXPORT, 0,0,0,0,SSL_EXP_MASK)); + Definitions.put(SSL_TXT_EXPORT,new Def(0,SSL_TXT_EXPORT,0, 0,SSL_EXPORT, 0,0,0,0,SSL_EXP_MASK)); + Definitions.put(SSL_TXT_EXP40,new Def(0,SSL_TXT_EXP40, 0, 0, SSL_EXP40, 0,0,0,0,SSL_STRONG_MASK)); + Definitions.put(SSL_TXT_EXP56,new Def(0,SSL_TXT_EXP56, 0, 0, SSL_EXP56, 0,0,0,0,SSL_STRONG_MASK)); + Definitions.put(SSL_TXT_LOW,new Def(0,SSL_TXT_LOW, 0, 0, SSL_LOW, 0,0,0,0,SSL_STRONG_MASK)); + Definitions.put(SSL_TXT_MEDIUM,new Def(0,SSL_TXT_MEDIUM,0, 0,SSL_MEDIUM, 0,0,0,0,SSL_STRONG_MASK)); + Definitions.put(SSL_TXT_HIGH,new Def(0,SSL_TXT_HIGH, 0, 0, SSL_HIGH, 0,0,0,0,SSL_STRONG_MASK)); + + /* Cipher 01 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_NULL_MD5, + SSL3_CK_RSA_NULL_MD5, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_MD5|SSL_SSLV3, + SSL_NOT_EXP|SSL_STRONG_NONE, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 02 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_NULL_SHA, + SSL3_CK_RSA_NULL_SHA, + SSL_kRSA|SSL_aRSA|SSL_eNULL |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_STRONG_NONE, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 03 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_RC4_40_MD5, + SSL3_CK_RSA_RC4_40_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 04 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_RC4_128_MD5, + SSL3_CK_RSA_RC4_128_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_MD5|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 05 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_RC4_128_SHA, + SSL3_CK_RSA_RC4_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_RC4 |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 06 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_RC2_40_MD5, + SSL3_CK_RSA_RC2_40_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 07 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_IDEA_128_SHA, + SSL3_CK_RSA_IDEA_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_IDEA |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 08 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_DES_40_CBC_SHA, + SSL3_CK_RSA_DES_40_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 09 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_DES_64_CBC_SHA, + SSL3_CK_RSA_DES_64_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 0A */ + Ciphers.add(new Def( + 1, + SSL3_TXT_RSA_DES_192_CBC3_SHA, + SSL3_CK_RSA_DES_192_CBC3_SHA, + SSL_kRSA|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* The DH ciphers */ + /* Cipher 0B */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_DSS_DES_40_CBC_SHA, + SSL3_CK_DH_DSS_DES_40_CBC_SHA, + SSL_kDHd |SSL_aDH|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 0C */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_DSS_DES_64_CBC_SHA, + SSL3_CK_DH_DSS_DES_64_CBC_SHA, + SSL_kDHd |SSL_aDH|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 0D */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_DSS_DES_192_CBC3_SHA, + SSL3_CK_DH_DSS_DES_192_CBC3_SHA, + SSL_kDHd |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 0E */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_RSA_DES_40_CBC_SHA, + SSL3_CK_DH_RSA_DES_40_CBC_SHA, + SSL_kDHr |SSL_aDH|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 0F */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_RSA_DES_64_CBC_SHA, + SSL3_CK_DH_RSA_DES_64_CBC_SHA, + SSL_kDHr |SSL_aDH|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 10 */ + Ciphers.add(new Def( + 0, + SSL3_TXT_DH_RSA_DES_192_CBC3_SHA, + SSL3_CK_DH_RSA_DES_192_CBC3_SHA, + SSL_kDHr |SSL_aDH|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* The Ephemeral DH ciphers */ + /* Cipher 11 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_DSS_DES_40_CBC_SHA, + SSL3_CK_EDH_DSS_DES_40_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 12 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_DSS_DES_64_CBC_SHA, + SSL3_CK_EDH_DSS_DES_64_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 13 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_DSS_DES_192_CBC3_SHA, + SSL3_CK_EDH_DSS_DES_192_CBC3_SHA, + SSL_kEDH|SSL_aDSS|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 14 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_RSA_DES_40_CBC_SHA, + SSL3_CK_EDH_RSA_DES_40_CBC_SHA, + SSL_kEDH|SSL_aRSA|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 15 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_RSA_DES_64_CBC_SHA, + SSL3_CK_EDH_RSA_DES_64_CBC_SHA, + SSL_kEDH|SSL_aRSA|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 16 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_EDH_RSA_DES_192_CBC3_SHA, + SSL3_CK_EDH_RSA_DES_192_CBC3_SHA, + SSL_kEDH|SSL_aRSA|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 17 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_ADH_RC4_40_MD5, + SSL3_CK_ADH_RC4_40_MD5, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 18 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_ADH_RC4_128_MD5, + SSL3_CK_ADH_RC4_128_MD5, + SSL_kEDH |SSL_aNULL|SSL_RC4 |SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 19 */ + Ciphers.add(new Def( + 1, + SSL3_TXT_ADH_DES_40_CBC_SHA, + SSL3_CK_ADH_DES_40_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_DES|SSL_SHA1|SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 1A */ + Ciphers.add(new Def( + 1, + SSL3_TXT_ADH_DES_64_CBC_SHA, + SSL3_CK_ADH_DES_64_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 1B */ + Ciphers.add(new Def( + 1, + SSL3_TXT_ADH_DES_192_CBC_SHA, + SSL3_CK_ADH_DES_192_CBC_SHA, + SSL_kEDH |SSL_aNULL|SSL_3DES |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Fortezza */ + /* Cipher 1C */ + Ciphers.add(new Def( + 0, + SSL3_TXT_FZA_DMS_NULL_SHA, + SSL3_CK_FZA_DMS_NULL_SHA, + SSL_kFZA|SSL_aFZA |SSL_eNULL |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_STRONG_NONE, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 1D */ + Ciphers.add(new Def( + 0, + SSL3_TXT_FZA_DMS_FZA_SHA, + SSL3_CK_FZA_DMS_FZA_SHA, + SSL_kFZA|SSL_aFZA |SSL_eFZA |SSL_SHA1|SSL_SSLV3, + SSL_NOT_EXP|SSL_STRONG_NONE, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 1E VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_64_CBC_SHA, + SSL3_CK_KRB5_DES_64_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 1F VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_192_CBC3_SHA, + SSL3_CK_KRB5_DES_192_CBC3_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_3DES|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 112, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 20 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC4_128_SHA, + SSL3_CK_KRB5_RC4_128_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_RC4|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 21 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_IDEA_128_CBC_SHA, + SSL3_CK_KRB5_IDEA_128_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_IDEA|SSL_SHA1 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 22 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_64_CBC_MD5, + SSL3_CK_KRB5_DES_64_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_LOW, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 23 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_192_CBC3_MD5, + SSL3_CK_KRB5_DES_192_CBC3_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_3DES|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_HIGH, + 0, + 112, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 24 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC4_128_MD5, + SSL3_CK_KRB5_RC4_128_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_RC4|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 25 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_IDEA_128_CBC_MD5, + SSL3_CK_KRB5_IDEA_128_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_IDEA|SSL_MD5 |SSL_SSLV3, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 26 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_40_CBC_SHA, + SSL3_CK_KRB5_DES_40_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_SHA1 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 27 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC2_40_CBC_SHA, + SSL3_CK_KRB5_RC2_40_CBC_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_RC2|SSL_SHA1 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 28 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC4_40_SHA, + SSL3_CK_KRB5_RC4_40_SHA, + SSL_kKRB5|SSL_aKRB5| SSL_RC4|SSL_SHA1 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 29 VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_DES_40_CBC_MD5, + SSL3_CK_KRB5_DES_40_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_DES|SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 2A VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC2_40_CBC_MD5, + SSL3_CK_KRB5_RC2_40_CBC_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_RC2|SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 40, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 2B VRS */ + Ciphers.add(new Def( + 1, + SSL3_TXT_KRB5_RC4_40_MD5, + SSL3_CK_KRB5_RC4_40_MD5, + SSL_kKRB5|SSL_aKRB5| SSL_RC4|SSL_MD5 |SSL_SSLV3, + SSL_EXPORT|SSL_EXP40, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 2F */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_WITH_AES_128_SHA, + TLS1_CK_RSA_WITH_AES_128_SHA, + SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 30 */ + Ciphers.add(new Def( + 0, + TLS1_TXT_DH_DSS_WITH_AES_128_SHA, + TLS1_CK_DH_DSS_WITH_AES_128_SHA, + SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 31 */ + Ciphers.add(new Def( + 0, + TLS1_TXT_DH_RSA_WITH_AES_128_SHA, + TLS1_CK_DH_RSA_WITH_AES_128_SHA, + SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 32 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_DSS_WITH_AES_128_SHA, + TLS1_CK_DHE_DSS_WITH_AES_128_SHA, + SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 33 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_RSA_WITH_AES_128_SHA, + TLS1_CK_DHE_RSA_WITH_AES_128_SHA, + SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 34 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ADH_WITH_AES_128_SHA, + TLS1_CK_ADH_WITH_AES_128_SHA, + SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher 35 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_WITH_AES_256_SHA, + TLS1_CK_RSA_WITH_AES_256_SHA, + SSL_kRSA|SSL_aRSA|SSL_AES|SSL_SHA |SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 36 */ + Ciphers.add(new Def( + 0, + TLS1_TXT_DH_DSS_WITH_AES_256_SHA, + TLS1_CK_DH_DSS_WITH_AES_256_SHA, + SSL_kDHd|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 37 */ + Ciphers.add(new Def( + 0, + TLS1_TXT_DH_RSA_WITH_AES_256_SHA, + TLS1_CK_DH_RSA_WITH_AES_256_SHA, + SSL_kDHr|SSL_aDH|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 38 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_DSS_WITH_AES_256_SHA, + TLS1_CK_DHE_DSS_WITH_AES_256_SHA, + SSL_kEDH|SSL_aDSS|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 39 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_RSA_WITH_AES_256_SHA, + TLS1_CK_DHE_RSA_WITH_AES_256_SHA, + SSL_kEDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 3A */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ADH_WITH_AES_256_SHA, + TLS1_CK_ADH_WITH_AES_256_SHA, + SSL_kEDH|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* New TLS Export CipherSuites */ + /* Cipher 60 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_MD5, + TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_MD5|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 61 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, + TLS1_CK_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5, + SSL_kRSA|SSL_aRSA|SSL_RC2|SSL_MD5|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 62 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_DES_CBC_SHA, + TLS1_CK_RSA_EXPORT1024_WITH_DES_CBC_SHA, + SSL_kRSA|SSL_aRSA|SSL_DES|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 63 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, + TLS1_CK_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA, + SSL_kEDH|SSL_aDSS|SSL_DES|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 56, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 64 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_RSA_EXPORT1024_WITH_RC4_56_SHA, + TLS1_CK_RSA_EXPORT1024_WITH_RC4_56_SHA, + SSL_kRSA|SSL_aRSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 65 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, + TLS1_CK_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA, + SSL_kEDH|SSL_aDSS|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_EXPORT|SSL_EXP56, + 0, + 56, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher 66 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_DHE_DSS_WITH_RC4_128_SHA, + TLS1_CK_DHE_DSS_WITH_RC4_128_SHA, + SSL_kEDH|SSL_aDSS|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_MEDIUM, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + /* Cipher C001 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_ECDSA_WITH_NULL_SHA, + TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA, + SSL_kECDH|SSL_aECDSA|SSL_eNULL|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C002 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_ECDSA_WITH_RC4_128_SHA, + TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA, + SSL_kECDH|SSL_aECDSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C003 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_ECDSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDH_ECDSA_WITH_DES_192_CBC3_SHA, + SSL_kECDH|SSL_aECDSA|SSL_3DES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C004 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDH_ECDSA_WITH_AES_128_CBC_SHA, + SSL_kECDH|SSL_aECDSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C005 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDH_ECDSA_WITH_AES_256_CBC_SHA, + SSL_kECDH|SSL_aECDSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C006 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_NULL_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_NULL_SHA, + SSL_kECDHE|SSL_aECDSA|SSL_eNULL|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C007 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_RC4_128_SHA, + SSL_kECDHE|SSL_aECDSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C008 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA, + SSL_kECDHE|SSL_aECDSA|SSL_3DES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C009 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE|SSL_aECDSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00A */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE|SSL_aECDSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00B */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_RSA_WITH_NULL_SHA, + TLS1_CK_ECDH_RSA_WITH_NULL_SHA, + SSL_kECDH|SSL_aRSA|SSL_eNULL|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00C */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_RSA_WITH_RC4_128_SHA, + TLS1_CK_ECDH_RSA_WITH_RC4_128_SHA, + SSL_kECDH|SSL_aRSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00D */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_RSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDH_RSA_WITH_DES_192_CBC3_SHA, + SSL_kECDH|SSL_aRSA|SSL_3DES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00E */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_RSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDH_RSA_WITH_AES_128_CBC_SHA, + SSL_kECDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C00F */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_RSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDH_RSA_WITH_AES_256_CBC_SHA, + SSL_kECDH|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C010 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_RSA_WITH_NULL_SHA, + TLS1_CK_ECDHE_RSA_WITH_NULL_SHA, + SSL_kECDHE|SSL_aRSA|SSL_eNULL|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C011 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_RSA_WITH_RC4_128_SHA, + TLS1_CK_ECDHE_RSA_WITH_RC4_128_SHA, + SSL_kECDHE|SSL_aRSA|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C012 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDHE_RSA_WITH_DES_192_CBC3_SHA, + SSL_kECDHE|SSL_aRSA|SSL_3DES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C013 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_128_CBC_SHA, + SSL_kECDHE|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C014 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDHE_RSA_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDHE_RSA_WITH_AES_256_CBC_SHA, + SSL_kECDHE|SSL_aRSA|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C015 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_anon_WITH_NULL_SHA, + TLS1_CK_ECDH_anon_WITH_NULL_SHA, + SSL_kECDHE|SSL_aNULL|SSL_eNULL|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 0, + 0, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C016 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_anon_WITH_RC4_128_SHA, + TLS1_CK_ECDH_anon_WITH_RC4_128_SHA, + SSL_kECDHE|SSL_aNULL|SSL_RC4|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C017 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_anon_WITH_DES_192_CBC3_SHA, + TLS1_CK_ECDH_anon_WITH_DES_192_CBC3_SHA, + SSL_kECDHE|SSL_aNULL|SSL_3DES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 168, + 168, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C018 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_anon_WITH_AES_128_CBC_SHA, + TLS1_CK_ECDH_anon_WITH_AES_128_CBC_SHA, + SSL_kECDHE|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 128, + 128, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + /* Cipher C019 */ + Ciphers.add(new Def( + 1, + TLS1_TXT_ECDH_anon_WITH_AES_256_CBC_SHA, + TLS1_CK_ECDH_anon_WITH_AES_256_CBC_SHA, + SSL_kECDHE|SSL_aNULL|SSL_AES|SSL_SHA|SSL_TLSV1, + SSL_NOT_EXP|SSL_HIGH, + 0, + 256, + 256, + SSL_ALL_CIPHERS, + SSL_ALL_STRENGTHS + )); + + for(Def def : Ciphers) { + CipherNames.put(def.name, def); + } + + addAlias("SSL_RSA_WITH_NULL_MD5","NULL-MD5"); + addAlias("SSL_RSA_WITH_NULL_SHA","NULL-SHA"); + addAlias("SSL_RSA_EXPORT_WITH_RC4_40_MD5","EXP-RC4-MD5"); + addAlias("SSL_RSA_WITH_RC4_128_MD5","RC4-MD5"); + addAlias("SSL_RSA_WITH_RC4_128_SHA","RC4-SHA"); + addAlias("SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5","EXP-RC2-CBC-MD5"); + addAlias("SSL_RSA_WITH_IDEA_CBC_SHA","IDEA-CBC-SHA"); + addAlias("SSL_RSA_EXPORT_WITH_DES40_CBC_SHA","EXP-DES-CBC-SHA"); + addAlias("SSL_RSA_WITH_DES_CBC_SHA","DES-CBC-SHA"); + addAlias("SSL_RSA_WITH_3DES_EDE_CBC_SHA","DES-CBC3-SHA"); + addAlias("SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA","EXP-EDH-DSS-DES-CBC-SHA"); + addAlias("SSL_DHE_DSS_WITH_DES_CBC_SHA","EDH-DSS-CBC-SHA"); + addAlias("SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA","EDH-DSS-DES-CBC3-SHA"); + addAlias("SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA","EXP-EDH-RSA-DES-CBC-SHA"); + addAlias("SSL_DHE_RSA_WITH_DES_CBC_SHA","EDH-RSA-DES-CBC-SHA"); + addAlias("SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA","EDH-RSA-DES-CBC3-SHA"); + addAlias("SSL_DH_anon_EXPORT_WITH_RC4_40_MD5","EXP-ADH-RC4-MD5"); + addAlias("SSL_DH_anon_WITH_RC4_128_MD5","ADH-RC4-MD5"); + addAlias("SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA","EXP-ADH-DES-CBC-SHA"); + addAlias("SSL_DH_anon_WITH_DES_CBC_SHA","ADH-DES-CBC-SHA"); + addAlias("SSL_DH_anon_WITH_3DES_EDE_CBC_SHA","ADH-DES-CBC3-SHA"); + addAlias("TLS_RSA_WITH_NULL_MD5","NULL-MD5"); + addAlias("TLS_RSA_WITH_NULL_SHA","NULL-SHA"); + addAlias("TLS_RSA_EXPORT_WITH_RC4_40_MD5","EXP-RC4-MD5"); + addAlias("TLS_RSA_WITH_RC4_128_MD5","RC4-MD5"); + addAlias("TLS_RSA_WITH_RC4_128_SHA","RC4-SHA"); + addAlias("TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5","EXP-RC2-CBC-MD5"); + addAlias("TLS_RSA_WITH_IDEA_CBC_SHA","IDEA-CBC-SHA"); + addAlias("TLS_RSA_EXPORT_WITH_DES40_CBC_SHA","EXP-DES-CBC-SHA"); + addAlias("TLS_RSA_WITH_DES_CBC_SHA","DES-CBC-SHA"); + addAlias("TLS_RSA_WITH_3DES_EDE_CBC_SHA","DES-CBC3-SHA"); + addAlias("TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA","EXP-EDH-DSS-DES-CBC-SHA"); + addAlias("TLS_DHE_DSS_WITH_DES_CBC_SHA","EDH-DSS-CBC-SHA"); + addAlias("TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA","EDH-DSS-DES-CBC3-SHA"); + addAlias("TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA","EXP-EDH-RSA-DES-CBC-SHA"); + addAlias("TLS_DHE_RSA_WITH_DES_CBC_SHA","EDH-RSA-DES-CBC-SHA"); + addAlias("TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA","EDH-RSA-DES-CBC3-SHA"); + addAlias("TLS_DH_anon_EXPORT_WITH_RC4_40_MD5","EXP-ADH-RC4-MD5"); + addAlias("TLS_DH_anon_WITH_RC4_128_MD5","ADH-RC4-MD5"); + addAlias("TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA","EXP-ADH-DES-CBC-SHA"); + addAlias("TLS_DH_anon_WITH_DES_CBC_SHA","ADH-DES-CBC-SHA"); + addAlias("TLS_DH_anon_WITH_3DES_EDE_CBC_SHA","ADH-DES-CBC3-SHA"); + addAlias("TLS_RSA_WITH_AES_128_CBC_SHA","AES128-SHA"); + addAlias("TLS_RSA_WITH_AES_256_CBC_SHA","AES256-SHA"); + addAlias("TLS_DH_DSS_WITH_AES_128_CBC_SHA","DH-DSS-AES128-SHA"); + addAlias("TLS_DH_DSS_WITH_AES_256_CBC_SHA","DH-DSS-AES256-SHA"); + addAlias("TLS_DH_RSA_WITH_AES_128_CBC_SHA","DH-RSA-AES128-SHA"); + addAlias("TLS_DH_RSA_WITH_AES_256_CBC_SHA","DH-RSA-AES256-SHA"); + addAlias("TLS_DHE_DSS_WITH_AES_128_CBC_SHA","DHE-DSS-AES128-SHA"); + addAlias("TLS_DHE_DSS_WITH_AES_256_CBC_SHA","DHE-DSS-AES256-SHA"); + addAlias("TLS_DHE_RSA_WITH_AES_128_CBC_SHA","DHE-RSA-AES128-SHA"); + addAlias("TLS_DHE_RSA_WITH_AES_256_CBC_SHA","DHE-RSA-AES256-SHA"); + addAlias("TLS_DH_anon_WITH_AES_128_CBC_SHA","ADH-AES128-SHA"); + addAlias("TLS_DH_anon_WITH_AES_256_CBC_SHA","ADH-AES256-SHA"); + addAlias("TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA","EXP1024-DES-CBC-SHA"); + addAlias("TLS_RSA_EXPORT1024_WITH_RC4_56_SHA","EXP1024-RC4-SHA"); + addAlias("TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA","EXP1024-DHE-DSS-DES-CBC-SHA"); + addAlias("TLS_DHE_DSS_EXPORT1024_WITH_RC4_56_SHA","EXP1024-DHE-DSS-RC4-SHA"); + addAlias("TLS_DHE_DSS_WITH_RC4_128_SHA","DHE-DSS-RC4-SHA"); + addAlias("SSL_CK_RC4_128_WITH_MD5","RC4-MD5"); + addAlias("SSL_CK_RC4_128_EXPORT40_WITH_MD5","EXP-RC4-MD5"); + addAlias("SSL_CK_RC2_128_CBC_WITH_MD5","RC2-MD5"); + addAlias("SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5","EXP-RC2-MD5"); + addAlias("SSL_CK_IDEA_128_CBC_WITH_MD5","IDEA-CBC-MD5"); + addAlias("SSL_CK_DES_64_CBC_WITH_MD5","DES-CBC-MD5"); + addAlias("SSL_CK_DES_192_EDE3_CBC_WITH_MD5","DES-CBC3-MD5"); + } +}// CipherStrings diff --git a/src/org/jruby/ext/openssl/Config.java b/src/org/jruby/ext/openssl/Config.java new file mode 100644 index 00000000000..dd8fd302c2c --- /dev/null +++ b/src/org/jruby/ext/openssl/Config.java @@ -0,0 +1,49 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; + +/** + * @author Ola Bini + */ +public class Config { + // TODO: we cannot detect OS's default config file. ignore? + public static final String DEFAULT_CONFIG_FILE = "./openssl.cnf"; + + public static void createConfig(Ruby runtime, RubyModule mOSSL) { + RubyClass cConfig = mOSSL.defineClassUnder("Config", runtime.getObject(), runtime.getObject().getAllocator()); + cConfig.defineAnnotatedMethods(Config.class); + RubyClass openSSLError = mOSSL.getClass("OpenSSLError"); + mOSSL.defineClassUnder("ConfigError", openSSLError, openSSLError.getAllocator()); + // TODO: we should define this constant with proper path. (see above) + //cConfig.setConstant("DEFAULT_CONFIG_FILE", runtime.newString(DEFAULT_CONFIG_FILE)); + } +}// Config diff --git a/src/org/jruby/ext/openssl/DefaultPEMHandler.java b/src/org/jruby/ext/openssl/DefaultPEMHandler.java new file mode 100644 index 00000000000..d47337c03aa --- /dev/null +++ b/src/org/jruby/ext/openssl/DefaultPEMHandler.java @@ -0,0 +1,44 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.Reader; +import java.io.Writer; + +/** + * @author Ola Bini + */ +public class DefaultPEMHandler implements PEMHandler { + public Object readPEM(Reader read, String password) { + return null; + } + public void writePEM(Writer writ, Object obj, String algorithm, char[] password) { + } + public void writePEM(Writer writ, Object obj) { + } +}// DefaultPEMHandler diff --git a/src/org/jruby/ext/openssl/Digest.java b/src/org/jruby/ext/openssl/Digest.java new file mode 100644 index 00000000000..a36337f85b3 --- /dev/null +++ b/src/org/jruby/ext/openssl/Digest.java @@ -0,0 +1,191 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class Digest extends RubyObject { + private static final long serialVersionUID = 1L; + + private static ObjectAllocator DIGEST_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new Digest(runtime, klass); + } + }; + + public static void createDigest(Ruby runtime, RubyModule mOSSL) { + runtime.getLoadService().require("digest"); + RubyModule mDigest = runtime.fastGetModule("Digest"); + RubyClass cDigestClass = mDigest.fastGetClass("Class"); + RubyClass cDigest = mOSSL.defineClassUnder("Digest", cDigestClass, DIGEST_ALLOCATOR); + cDigest.defineAnnotatedMethods(Digest.class); + RubyClass openSSLError = mOSSL.getClass("OpenSSLError"); + mOSSL.defineClassUnder("DigestError", openSSLError, openSSLError.getAllocator()); + } + + static MessageDigest getDigest(final String name, final Ruby runtime) { + String algorithm = transformDigest(name); + try { + return MessageDigest.getInstance(algorithm); + } catch (NoSuchAlgorithmException e) { + try { + return OpenSSLReal.getMessageDigestBC(algorithm); + } catch (GeneralSecurityException ignore) { + } + throw runtime.newNotImplementedError("Unsupported digest algorithm (" + name + ")"); + } + } + + // name mapping for openssl -> JCE + private static String transformDigest(String inp) { + String[] sp = inp.split("::"); + if (sp.length > 1) { // We only want Digest names from the last part of class name + inp = sp[sp.length - 1]; + } + // MessageDigest algorithm name normalization. + // BC accepts "SHA1" but it should be "SHA-1" per spec. + if ("DSS".equalsIgnoreCase(inp)) { + return "SHA"; // why? + } else if ("DSS1".equalsIgnoreCase(inp)) { + return "SHA-1"; + } else if (inp.toUpperCase().startsWith("SHA") && inp.length() > 3 && inp.charAt(3) != '-') { + inp = "SHA-" + inp.substring(3); + } + return inp; + } + + public Digest(Ruby runtime, RubyClass type) { + super(runtime,type); + // do not initialize MessageDigest at allocation time (same as the ruby-openssl) + name = null; + algo = null; + } + private MessageDigest algo; + private String name; + + public String getRealName() { + return transformDigest(name); + } + + public String getName() { + return name; + } + + @JRubyMethod(required = 1, optional = 1) + public IRubyObject initialize(IRubyObject[] args) { + IRubyObject type = args[0]; + IRubyObject data = getRuntime().getNil(); + if (args.length > 1) { + data = args[1]; + } + name = type.toString(); + algo = getDigest(name, getRuntime()); + if (!data.isNil()) { + update(data.convertToString()); + } + return this; + } + + @Override + @JRubyMethod + public IRubyObject initialize_copy(IRubyObject obj) { + checkFrozen(); + if(this == obj) { + return this; + } + name = ((Digest)obj).algo.getAlgorithm(); + try { + algo = (MessageDigest)((Digest)obj).algo.clone(); + } catch(CloneNotSupportedException e) { + throw getRuntime().newTypeError("Could not initialize copy of digest (" + name + ")"); + } + return this; + } + + @JRubyMethod(name={"update","<<"}) + public IRubyObject update(IRubyObject obj) { + ByteList bytes = obj.convertToString().getByteList(); + algo.update(bytes.bytes, bytes.begin, bytes.realSize); + return this; + } + + @JRubyMethod + public IRubyObject reset() { + algo.reset(); + return this; + } + + @JRubyMethod + public IRubyObject finish() { + IRubyObject digest = RubyString.newStringNoCopy(getRuntime(), algo.digest()); + algo.reset(); + return digest; + } + + @JRubyMethod + public IRubyObject name() { + return getRuntime().newString(name); + } + + @JRubyMethod() + public IRubyObject digest_length() { + return RubyFixnum.newFixnum(getRuntime(), algo.getDigestLength()); + } + + @JRubyMethod() + public IRubyObject block_length() { + // TODO: ruby-openssl supports it. + throw getRuntime().newRuntimeError( + this.getMetaClass() + " doesn't implement block_length()"); + } + + String getAlgorithm() { + return this.algo.getAlgorithm(); + } + + String getShortAlgorithm() { + return getAlgorithm().replace("-", ""); + } +} + diff --git a/src/org/jruby/ext/openssl/HMAC.java b/src/org/jruby/ext/openssl/HMAC.java new file mode 100644 index 00000000000..d2b5e6237e2 --- /dev/null +++ b/src/org/jruby/ext/openssl/HMAC.java @@ -0,0 +1,178 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.NoSuchAlgorithmException; +import javax.crypto.Mac; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class HMAC extends RubyObject { + private static final long serialVersionUID = 7602535792884680307L; + + private static ObjectAllocator HMAC_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new HMAC(runtime, klass); + } + }; + + public static void createHMAC(Ruby runtime, RubyModule ossl) { + RubyClass cHMAC = ossl.defineClassUnder("HMAC",runtime.getObject(),HMAC_ALLOCATOR); + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + ossl.defineClassUnder("HMACError",openSSLError,openSSLError.getAllocator()); + + cHMAC.defineAnnotatedMethods(HMAC.class); + } + + static Mac getMac(String algoName) throws NoSuchAlgorithmException { + // some algorithms need the - removed; this is ugly, I know. + try { + return Mac.getInstance("HMAC" + algoName.replaceAll("-", "")); + } catch (NoSuchAlgorithmException nsae) { + return Mac.getInstance("HMAC-" + algoName.replaceAll("-", "")); + } + } + + @JRubyMethod(name = "digest", meta = true) + public static IRubyObject s_digest(IRubyObject recv, IRubyObject digest, IRubyObject kay, IRubyObject data) { + String algoName = getDigestAlgorithmName(digest); + try { + Mac mac = getMac(algoName); + byte[] key = kay.convertToString().getBytes(); + SecretKey keysp = new SecretKeySpec(key, mac.getAlgorithm()); + mac.init(keysp); + return RubyString.newString(recv.getRuntime(), mac.doFinal(data.convertToString().getBytes())); + } catch (Exception e) { + e.printStackTrace(); + throw recv.getRuntime().newNotImplementedError(e.getMessage()); + } + } + + @JRubyMethod(name = "hexdigest", meta = true) + public static IRubyObject s_hexdigest(IRubyObject recv, IRubyObject digest, IRubyObject kay, IRubyObject data) { + String algoName = getDigestAlgorithmName(digest); + try { + Mac mac = getMac(algoName); + byte[] key = kay.convertToString().getBytes(); + SecretKey keysp = new SecretKeySpec(key, mac.getAlgorithm()); + mac.init(keysp); + return RubyString.newString(recv.getRuntime(), ByteList.plain(Utils.toHex(mac.doFinal(data.convertToString().getBytes())))); + } catch (Exception e) { + throw recv.getRuntime().newNotImplementedError(e.getMessage()); + } + } + + public HMAC(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private Mac mac; + private byte[] key; + private StringBuffer data = new StringBuffer(); + + @JRubyMethod + public IRubyObject initialize(IRubyObject kay, IRubyObject digest) { + String algoName = getDigestAlgorithmName(digest); + try { + mac = getMac(algoName); + key = kay.convertToString().getBytes(); + SecretKey keysp = new SecretKeySpec(key, mac.getAlgorithm()); + mac.init(keysp); + } catch (Exception e) { + throw getRuntime().newNotImplementedError(e.getMessage()); + } + return this; + } + + @Override + @JRubyMethod + public IRubyObject initialize_copy(IRubyObject obj) { + if(this == obj) { + return this; + } + checkFrozen(); + String name = ((HMAC)obj).mac.getAlgorithm(); + try { + mac = Mac.getInstance(name); + key = ((HMAC)obj).key; + SecretKey keysp = new SecretKeySpec(key,name); + mac.init(keysp); + } catch(Exception e) { + throw getRuntime().newNotImplementedError("Unsupported MAC algorithm (" + name + ")"); + } + + data = new StringBuffer(((HMAC)obj).data.toString()); + + return this; + } + + @JRubyMethod(name={"update", "<<"}) + public IRubyObject update(IRubyObject obj) { + data.append(obj); + return this; + } + + @JRubyMethod + public IRubyObject digest() { + mac.reset(); + return RubyString.newString(getRuntime(), mac.doFinal(ByteList.plain(data))); + } + + @JRubyMethod(name={"hexdigest","inspect","to_s"}) + public IRubyObject hexdigest() { + mac.reset(); + return RubyString.newString(getRuntime(), ByteList.plain(Utils.toHex(mac.doFinal(ByteList.plain(data))))); + } + + String getAlgorithm() { + return this.mac.getAlgorithm(); + } + + private static String getDigestAlgorithmName(IRubyObject digest) { + String algoName = null; + if (digest instanceof Digest) { + algoName = ((Digest) digest).getShortAlgorithm(); + } else { + algoName = digest.asString().toString(); + } + return algoName; + } +}// HMAC diff --git a/src/org/jruby/ext/openssl/NetscapeSPKI.java b/src/org/jruby/ext/openssl/NetscapeSPKI.java new file mode 100644 index 00000000000..59692c766a9 --- /dev/null +++ b/src/org/jruby/ext/openssl/NetscapeSPKI.java @@ -0,0 +1,252 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.PublicKey; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.DERNull; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.jce.netscape.NetscapeCertRequest; +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.impl.Base64; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class NetscapeSPKI extends RubyObject { + private static final long serialVersionUID = 3211242351810109432L; + + private static ObjectAllocator NETSCAPESPKI_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new NetscapeSPKI(runtime, klass); + } + }; + + public static void createNetscapeSPKI(Ruby runtime, RubyModule ossl) { + RubyModule mNetscape = ossl.defineModuleUnder("Netscape"); + RubyClass cSPKI = mNetscape.defineClassUnder("SPKI",runtime.getObject(),NETSCAPESPKI_ALLOCATOR); + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + mNetscape.defineClassUnder("SPKIError",openSSLError,openSSLError.getAllocator()); + + cSPKI.defineAnnotatedMethods(NetscapeSPKI.class); + } + + public NetscapeSPKI(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private IRubyObject public_key; + private IRubyObject challenge; + + private NetscapeCertRequest cert; + + @JRubyMethod(name = "initialize", rest = true) + public IRubyObject _initialize(IRubyObject[] args) { + if (args.length > 0) { + byte[] b = args[0].convertToString().getBytes(); + b = tryBase64Decode(b); + final byte[] b2 = b; + String algo = null; + byte[] enc = null; + try { + // NetscapeCertRequest requires "BC" provider. + PublicKey pkey = (PublicKey) OpenSSLReal.getWithBCProvider(new OpenSSLReal.Callable() { + + public Object call() throws GeneralSecurityException { + try { + // NetscapeCertRequest throws java.lang.IllegalArgumentException + // when no BC provider allowed, with a message + // "java.security.NoSuchProviderException: no such provider: BC" + // instead of NoSuchProviderException. + cert = new NetscapeCertRequest(b2); + challenge = getRuntime().newString(cert.getChallenge()); + return cert.getPublicKey(); + } catch (IOException ioe) { + throw new GeneralSecurityException(ioe.getMessage(), ioe); + } + } + }); + algo = pkey.getAlgorithm(); + enc = pkey.getEncoded(); + } catch (GeneralSecurityException gse) { + throw newSPKIError(getRuntime(), gse.getMessage()); + } + + if ("RSA".equalsIgnoreCase(algo)) { + this.public_key = Utils.newRubyInstance(getRuntime(), "OpenSSL::PKey::RSA", RubyString.newString(getRuntime(), enc)); + } else if ("DSA".equalsIgnoreCase(algo)) { + this.public_key = Utils.newRubyInstance(getRuntime(), "OpenSSL::PKey::DSA", RubyString.newString(getRuntime(), enc)); + } else { + throw getRuntime().newLoadError("not implemented algo for public key: " + algo); + } + } + return this; + } + + // just try to decode for the time when the given bytes are base64 encoded. + private byte[] tryBase64Decode(byte[] b) { + try { + b = Base64.decode(b, 0, b.length, Base64.NO_OPTIONS); + } catch (Exception ignored) { + } + return b; + } + + @JRubyMethod + public IRubyObject to_der() { + try { + return RubyString.newString(getRuntime(), internalToDer()); + } catch (IOException ioe) { + throw newSPKIError(getRuntime(), ioe.getMessage()); + } + } + + @JRubyMethod(name={"to_pem","to_s"}) + public IRubyObject to_pem() { + try { + byte[] source = internalToDer(); + // no Base64.DO_BREAK_LINES option needed for NSPKI. + return getRuntime().newString(Base64.encodeBytes(source, 0, source.length, Base64.NO_OPTIONS)); + } catch (IOException ioe) { + throw newSPKIError(getRuntime(), ioe.getMessage()); + } + } + + private byte[] internalToDer() throws IOException { + DERSequence b = (DERSequence)cert.toASN1Object(); + DERObjectIdentifier encType = null; + DERBitString publicKey = new DERBitString(((PKey)public_key).to_der().convertToString().getBytes()); + DERIA5String encodedChallenge = new DERIA5String(this.challenge.toString()); + DERObjectIdentifier sigAlg = null; + DERBitString sig = null; + encType = (DERObjectIdentifier)((DERSequence)((DERSequence)((DERSequence)b.getObjectAt(0)).getObjectAt(0)).getObjectAt(0)).getObjectAt(0); + sigAlg = ((AlgorithmIdentifier)b.getObjectAt(1)).getObjectId(); + sig = (DERBitString)b.getObjectAt(2); + + ASN1EncodableVector v1 = new ASN1EncodableVector(); + ASN1EncodableVector v1_2 = new ASN1EncodableVector(); + ASN1EncodableVector v2 = new ASN1EncodableVector(); + ASN1EncodableVector v3 = new ASN1EncodableVector(); + ASN1EncodableVector v4 = new ASN1EncodableVector(); + v4.add(encType); + v4.add(new DERNull()); + v3.add(new DERSequence(v4)); + v3.add(publicKey); + v2.add(new DERSequence(v3)); + v2.add(encodedChallenge); + v1.add(new DERSequence(v2)); + v1_2.add(sigAlg); + v1_2.add(new DERNull()); + v1.add(new DERSequence(v1_2)); + v1.add(sig); + return new DERSequence(v1).getEncoded(); + } + + @JRubyMethod + public IRubyObject to_text() { + System.err.println("WARNING: calling unimplemented method: to_text"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject public_key() { + return this.public_key; + } + + @JRubyMethod(name="public_key=") + public IRubyObject set_public_key(IRubyObject arg) { + this.public_key = arg; + return arg; + } + + @JRubyMethod + public IRubyObject sign(final IRubyObject key, IRubyObject digest) { + String keyAlg = ((PKey) key).getAlgorithm(); + String digAlg = ((Digest) digest).getShortAlgorithm(); + final DERObjectIdentifier alg = ASN1.getOIDLookup(getRuntime()).get(keyAlg.toLowerCase() + "-" + digAlg.toLowerCase()); + try { + // NetscapeCertRequest requires "BC" provider. + OpenSSLReal.doWithBCProvider(new OpenSSLReal.Runnable() { + + public void run() throws GeneralSecurityException { + cert = new NetscapeCertRequest(challenge.toString(), new AlgorithmIdentifier(alg), ((PKey) public_key).getPublicKey()); + cert.sign(((PKey) key).getPrivateKey()); + } + }); + } catch (GeneralSecurityException gse) { + throw newSPKIError(getRuntime(), gse.getMessage()); + } + return this; + } + + @JRubyMethod + public IRubyObject verify(final IRubyObject pkey) { + cert.setPublicKey(((PKey) pkey).getPublicKey()); + try { + // NetscapeCertRequest requires "BC" provider. + Boolean result = (Boolean) OpenSSLReal.getWithBCProvider(new OpenSSLReal.Callable() { + + public Boolean call() throws GeneralSecurityException { + return cert.verify(challenge.toString()); + } + }); + return result.booleanValue() ? getRuntime().getTrue() : getRuntime().getFalse(); + } catch (GeneralSecurityException gse) { + throw newSPKIError(getRuntime(), gse.getMessage()); + } + } + + @JRubyMethod + public IRubyObject challenge() { + return this.challenge; + } + + @JRubyMethod(name="challenge=") + public IRubyObject set_challenge(IRubyObject arg) { + this.challenge = arg; + return arg; + } + + private static RaiseException newSPKIError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::Netscape::SPKIError", message); + } +}// NetscapeSPKI diff --git a/src/org/jruby/ext/openssl/OSSLLibrary.java b/src/org/jruby/ext/openssl/OSSLLibrary.java new file mode 100644 index 00000000000..a1846bcd1d4 --- /dev/null +++ b/src/org/jruby/ext/openssl/OSSLLibrary.java @@ -0,0 +1,14 @@ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.ext.nkf.RubyNKF; +import org.jruby.ext.openssl.OpenSSLReal; +import org.jruby.runtime.load.Library; + +import java.io.IOException; + +public class OSSLLibrary implements Library { + public void load(Ruby runtime, boolean wrap) throws IOException { + OpenSSLReal.createOpenSSL(runtime); + } +} \ No newline at end of file diff --git a/src/org/jruby/ext/openssl/OpenSSLImpl.java b/src/org/jruby/ext/openssl/OpenSSLImpl.java new file mode 100644 index 00000000000..7363dd830bf --- /dev/null +++ b/src/org/jruby/ext/openssl/OpenSSLImpl.java @@ -0,0 +1,357 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.StringReader; +import java.security.MessageDigest; + +import org.jruby.Ruby; +import org.jruby.RubyString; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * Static class that holds various OpenSSL methods that aren't + * really easy to do any other way. + * + * @author Ola Bini + */ +public class OpenSSLImpl { + /** + * No instantiating this class... + */ + private OpenSSLImpl() {} + + public static IRubyObject to_der(IRubyObject obj) { + return obj.callMethod(obj.getRuntime().getCurrentContext(),"to_der"); + } + + public static IRubyObject to_der_if_possible(IRubyObject obj) { + if(obj.respondsTo("to_der")) { + return to_der(obj); + } else { + return obj; + } + } + + public static byte[] readX509PEM(IRubyObject arg) { + arg = to_der_if_possible(arg); + // TODO: should handle RubyFile + RubyString str = arg.convertToString(); + StringReader in = null; + try { + in = new StringReader(str.getUnicodeValue()); + byte[] bytes = PEMInputOutput.readX509PEM(in); + if (bytes != null) { + return bytes; + } + } catch (Exception e) { + // this is not PEM encoded, let's use the default argument + if (in != null) { + in.close(); + } + } + return str.getBytes(); + } + + public static void defaultObjects(Ruby runtime) { +ASN1.addObject(runtime, 0, null, null,"1.2.840.113549.1.12.1"); +ASN1.addObject(runtime, 1, null, "rsadsi","1.2.840.113549"); +ASN1.addObject(runtime, 2, null, "pkcs","1.2.840.113549.1"); +ASN1.addObject(runtime, 3, "MD2", "md2","1.2.840.113549.2.2"); +ASN1.addObject(runtime, 4, "MD5", "md5","1.2.840.113549.2.5"); +ASN1.addObject(runtime, 5, "RC4", "rc4","1.2.840.113549.3.4"); +ASN1.addObject(runtime, 6, null, "rsaEncryption","1.2.840.113549.1.1.1"); +ASN1.addObject(runtime, 7, "RSA-MD2", "md2WithRSAEncryption","1.2.840.113549.1.1.2"); +ASN1.addObject(runtime, 8, "RSA-MD5", "md5WithRSAEncryption","1.2.840.113549.1.1.4"); +ASN1.addObject(runtime, 9, "PBE-MD2-DES", "pbeWithMD2AndDES-CBC","1.2.840.113549.1.5.1"); +ASN1.addObject(runtime, 10, "PBE-MD5-DES", "pbeWithMD5AndDES-CBC","1.2.840.113549.1.5.3"); +ASN1.addObject(runtime, 11, null, "X500","2.5"); +ASN1.addObject(runtime, 12, null, "X509","2.5.4"); +ASN1.addObject(runtime, 13, "CN", "commonName","2.5.4.3"); +ASN1.addObject(runtime, 14, "C", "countryName","2.5.4.6"); +ASN1.addObject(runtime, 15, "L", "localityName","2.5.4.7"); +ASN1.addObject(runtime, 16, "ST", "stateOrProvinceName","2.5.4.8"); +ASN1.addObject(runtime, 17, "O", "organizationName","2.5.4.10"); +ASN1.addObject(runtime, 18, "OU", "organizationalUnitName","2.5.4.11"); +ASN1.addObject(runtime, 19, "RSA", "rsa","2.5.8.1.1"); +ASN1.addObject(runtime, 20, null, "pkcs7","1.2.840.113549.1.7"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_data, null, "pkcs7-data","1.2.840.113549.1.7.1"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_signed, null, "pkcs7-signedData","1.2.840.113549.1.7.2"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_enveloped, null, "pkcs7-envelopedData","1.2.840.113549.1.7.3"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_signedAndEnveloped, null, "pkcs7-signedAndEnvelopedData","1.2.840.113549.1.7.4"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_digest, null, "pkcs7-digestData","1.2.840.113549.1.7.5"); +ASN1.addObject(runtime, org.jruby.ext.openssl.impl.ASN1Registry.NID_pkcs7_encrypted, null, "pkcs7-encryptedData","1.2.840.113549.1.7.6"); +ASN1.addObject(runtime, 27, null, "pkcs3","1.2.840.113549.1.3"); +ASN1.addObject(runtime, 28, null, "dhKeyAgreement","1.2.840.113549.1.3.1"); +ASN1.addObject(runtime, 29, "DES-ECB", "des-ecb","1.3.14.3.2.6"); +ASN1.addObject(runtime, 30, "DES-CFB", "des-cfb","1.3.14.3.2.9"); +ASN1.addObject(runtime, 31, "DES-CBC", "des-cbc","1.3.14.3.2.7"); +ASN1.addObject(runtime, 32, "DES-EDE", "des-ede","1.3.14.3.2.17"); +ASN1.addObject(runtime, 33, "DES-EDE3", "des-ede3",null); +ASN1.addObject(runtime, 34, "IDEA-CBC", "idea-cbc","1.3.6.1.4.1.188.7.1.1.2"); +ASN1.addObject(runtime, 35, "IDEA-CFB", "idea-cfb",null); +ASN1.addObject(runtime, 36, "IDEA-ECB", "idea-ecb",null); +ASN1.addObject(runtime, 37, "RC2-CBC", "rc2-cbc","1.2.840.113549.3.2"); +ASN1.addObject(runtime, 38, "RC2-ECB", "rc2-ecb",null); +ASN1.addObject(runtime, 39, "RC2-CFB", "rc2-cfb",null); +ASN1.addObject(runtime, 40, "RC2-OFB", "rc2-ofb",null); +ASN1.addObject(runtime, 41, "SHA", "sha","1.3.14.3.2.18"); +ASN1.addObject(runtime, 42, "RSA-SHA", "shaWithRSAEncryption","1.3.14.3.2.15"); +ASN1.addObject(runtime, 43, "DES-EDE-CBC", "des-ede-cbc",null); +ASN1.addObject(runtime, 44, "DES-EDE3-CBC", "des-ede3-cbc","1.2.840.113549.3.7"); +ASN1.addObject(runtime, 45, "DES-OFB", "des-ofb","1.3.14.3.2.8"); +ASN1.addObject(runtime, 46, "IDEA-OFB", "idea-ofb",null); +ASN1.addObject(runtime, 47, null, "pkcs9","1.2.840.113549.1.9"); +ASN1.addObject(runtime, 48, "Email", "emailAddress","1.2.840.113549.1.9.1"); +ASN1.addObject(runtime, 49, null, "unstructuredName","1.2.840.113549.1.9.2"); +ASN1.addObject(runtime, 50, null, "contentType","1.2.840.113549.1.9.3"); +ASN1.addObject(runtime, 51, null, "messageDigest","1.2.840.113549.1.9.4"); +ASN1.addObject(runtime, 52, null, "signingTime","1.2.840.113549.1.9.5"); +ASN1.addObject(runtime, 53, null, "countersignature","1.2.840.113549.1.9.6"); +ASN1.addObject(runtime, 54, null, "challengePassword","1.2.840.113549.1.9.7"); +ASN1.addObject(runtime, 55, null, "unstructuredAddress","1.2.840.113549.1.9.8"); +ASN1.addObject(runtime, 56, null, "extendedCertificateAttributes","1.2.840.113549.1.9.9"); +ASN1.addObject(runtime, 57, "Netscape", "Netscape Communications Corp.","2.16.840.1.113730"); +ASN1.addObject(runtime, 58, "nsCertExt", "Netscape Certificate Extension","2.16.840.1.113730.1"); +ASN1.addObject(runtime, 59, "nsDataType", "Netscape Data Type","2.16.840.1.113730.2"); +ASN1.addObject(runtime, 60, "DES-EDE-CFB", "des-ede-cfb",null); +ASN1.addObject(runtime, 61, "DES-EDE3-CFB", "des-ede3-cfb",null); +ASN1.addObject(runtime, 62, "DES-EDE-OFB", "des-ede-ofb",null); +ASN1.addObject(runtime, 63, "DES-EDE3-OFB", "des-ede3-ofb",null); +ASN1.addObject(runtime, 64, "SHA1", "sha1","1.3.14.3.2.26"); +ASN1.addObject(runtime, 65, "RSA-SHA1", "sha1WithRSAEncryption","1.2.840.113549.1.1.5"); +ASN1.addObject(runtime, 66, "DSA-SHA", "dsaWithSHA","1.3.14.3.2.13"); +ASN1.addObject(runtime, 67, "DSA-old", "dsaEncryption-old","1.3.14.3.2.12"); +ASN1.addObject(runtime, 68, "PBE-SHA1-RC2-64", "pbeWithSHA1AndRC2-CBC","1.2.840.113549.1.5.11"); +ASN1.addObject(runtime, 69, null, "PBKDF2","1.2.840.113549.1.5.12"); +ASN1.addObject(runtime, 70, "DSA-SHA1-old", "dsaWithSHA1-old","1.3.14.3.2.27"); +ASN1.addObject(runtime, 71, "nsCertType", "Netscape Cert Type","2.16.840.1.113730.1.1"); +ASN1.addObject(runtime, 72, "nsBaseUrl", "Netscape Base Url","2.16.840.1.113730.1.2"); +ASN1.addObject(runtime, 73, "nsRevocationUrl", "Netscape Revocation Url","2.16.840.1.113730.1.3"); +ASN1.addObject(runtime, 74, "nsCaRevocationUrl", "Netscape CA Revocation Url","2.16.840.1.113730.1.4"); +ASN1.addObject(runtime, 75, "nsRenewalUrl", "Netscape Renewal Url","2.16.840.1.113730.1.7"); +ASN1.addObject(runtime, 76, "nsCaPolicyUrl", "Netscape CA Policy Url","2.16.840.1.113730.1.8"); +ASN1.addObject(runtime, 77, "nsSslServerName", "Netscape SSL Server Name","2.16.840.1.113730.1.12"); +ASN1.addObject(runtime, 78, "nsComment", "Netscape Comment","2.16.840.1.113730.1.13"); +ASN1.addObject(runtime, 79, "nsCertSequence", "Netscape Certificate Sequence","2.16.840.1.113730.2.5"); +ASN1.addObject(runtime, 80, "DESX-CBC", "desx-cbc",null); +ASN1.addObject(runtime, 81, "id-ce", null,"2.5.29"); +ASN1.addObject(runtime, 82, "subjectKeyIdentifier", "X509v3 Subject Key Identifier","2.5.29.14"); +ASN1.addObject(runtime, 83, "keyUsage", "X509v3 Key Usage","2.5.29.15"); +ASN1.addObject(runtime, 84, "privateKeyUsagePeriod", "X509v3 Private Key Usage Period","2.5.29.16"); +ASN1.addObject(runtime, 85, "subjectAltName", "X509v3 Subject Alternative Name","2.5.29.17"); +ASN1.addObject(runtime, 86, "issuerAltName", "X509v3 Issuer Alternative Name","2.5.29.18"); +ASN1.addObject(runtime, 87, "basicConstraints", "X509v3 Basic Constraints","2.5.29.19"); +ASN1.addObject(runtime, 88, "crlNumber", "X509v3 CRL Number","2.5.29.20"); +ASN1.addObject(runtime, 89, "certificatePolicies", "X509v3 Certificate Policies","2.5.29.32"); +ASN1.addObject(runtime, 90, "authorityKeyIdentifier", "X509v3 Authority Key Identifier","2.5.29.35"); +ASN1.addObject(runtime, 91, "BF-CBC", "bf-cbc","1.3.6.1.4.1.3029.1.2"); +ASN1.addObject(runtime, 92, "BF-ECB", "bf-ecb",null); +ASN1.addObject(runtime, 93, "BF-CFB", "bf-cfb",null); +ASN1.addObject(runtime, 94, "BF-OFB", "bf-ofb",null); +ASN1.addObject(runtime, 95, "MDC2", "mdc2","2.5.8.3.101"); +ASN1.addObject(runtime, 96, "RSA-MDC2", "mdc2withRSA","2.5.8.3.100"); +ASN1.addObject(runtime, 97, "RC4-40", "rc4-40",null); +ASN1.addObject(runtime, 98, "RC2-40-CBC", "rc2-40-cbc",null); +ASN1.addObject(runtime, 99, "G", "givenName","2.5.4.42"); +ASN1.addObject(runtime, 100, "S", "surname","2.5.4.4"); +ASN1.addObject(runtime, 101, "I", "initials","2.5.4.43"); +ASN1.addObject(runtime, 102, "UID", "uniqueIdentifier","2.5.4.45"); +ASN1.addObject(runtime, 103, "crlDistributionPoints", "X509v3 CRL Distribution Points","2.5.29.31"); +ASN1.addObject(runtime, 104, "RSA-NP-MD5", "md5WithRSA","1.3.14.3.2.3"); +ASN1.addObject(runtime, 105, "SN", "serialNumber","2.5.4.5"); +ASN1.addObject(runtime, 106, "T", "title","2.5.4.12"); +ASN1.addObject(runtime, 107, "D", "description","2.5.4.13"); +ASN1.addObject(runtime, 108, "CAST5-CBC", "cast5-cbc","1.2.840.113533.7.66.10"); +ASN1.addObject(runtime, 109, "CAST5-ECB", "cast5-ecb",null); +ASN1.addObject(runtime, 110, "CAST5-CFB", "cast5-cfb",null); +ASN1.addObject(runtime, 111, "CAST5-OFB", "cast5-ofb",null); +ASN1.addObject(runtime, 112, null, "pbeWithMD5AndCast5CBC","1.2.840.113533.7.66.12"); +ASN1.addObject(runtime, 113, "DSA-SHA1", "dsaWithSHA1","1.2.840.10040.4.3"); +ASN1.addObject(runtime, 114, "MD5-SHA1", "md5-sha1",null); +ASN1.addObject(runtime, 115, "RSA-SHA1-2", "sha1WithRSA","1.3.14.3.2.29"); +ASN1.addObject(runtime, 116, "DSA", "dsaEncryption","1.2.840.10040.4.1"); +ASN1.addObject(runtime, 117, "RIPEMD160", "ripemd160","1.3.36.3.2.1"); +ASN1.addObject(runtime, 118, "RSA-RIPEMD160", "ripemd160WithRSA","1.3.36.3.3.1.2"); +ASN1.addObject(runtime, 119, "RC5-CBC", "rc5-cbc","1.2.840.113549.3.8"); +ASN1.addObject(runtime, 120, "RC5-ECB", "rc5-ecb",null); +ASN1.addObject(runtime, 121, "RC5-CFB", "rc5-cfb",null); +ASN1.addObject(runtime, 122, "RC5-OFB", "rc5-ofb",null); +ASN1.addObject(runtime, 123, "RLE", "run length compression","1.1.1.1.666.1"); +ASN1.addObject(runtime, 124, "ZLIB", "zlib compression","1.1.1.1.666.2"); +ASN1.addObject(runtime, 125, "extendedKeyUsage", "X509v3 Extended Key Usage","2.5.29.37"); +ASN1.addObject(runtime, 126, "PKIX", null,"1.3.6.1.5.5.7"); +ASN1.addObject(runtime, 127, "id-kp", null,"1.3.6.1.5.5.7.3"); +ASN1.addObject(runtime, 128, "serverAuth", "TLS Web Server Authentication","1.3.6.1.5.5.7.3.1"); +ASN1.addObject(runtime, 129, "clientAuth", "TLS Web Client Authentication","1.3.6.1.5.5.7.3.2"); +ASN1.addObject(runtime, 130, "codeSigning", "Code Signing","1.3.6.1.5.5.7.3.3"); +ASN1.addObject(runtime, 131, "emailProtection", "E-mail Protection","1.3.6.1.5.5.7.3.4"); +ASN1.addObject(runtime, 132, "timeStamping", "Time Stamping","1.3.6.1.5.5.7.3.8"); +ASN1.addObject(runtime, 133, "msCodeInd", "Microsoft Individual Code Signing","1.3.6.1.4.1.311.2.1.21"); +ASN1.addObject(runtime, 134, "msCodeCom", "Microsoft Commercial Code Signing","1.3.6.1.4.1.311.2.1.22"); +ASN1.addObject(runtime, 135, "msCTLSign", "Microsoft Trust List Signing","1.3.6.1.4.1.311.10.3.1"); +ASN1.addObject(runtime, 136, "msSGC", "Microsoft Server Gated Crypto","1.3.6.1.4.1.311.10.3.3"); +ASN1.addObject(runtime, 137, "msEFS", "Microsoft Encrypted File System","1.3.6.1.4.1.311.10.3.4"); +ASN1.addObject(runtime, 138, "nsSGC", "Netscape Server Gated Crypto","2.16.840.1.113730.4.1"); +ASN1.addObject(runtime, 139, "deltaCRL", "X509v3 Delta CRL Indicator","2.5.29.27"); +ASN1.addObject(runtime, 140, "CRLReason", "CRL Reason Code","2.5.29.21"); +ASN1.addObject(runtime, 141, "invalidityDate", "Invalidity Date","2.5.29.24"); +ASN1.addObject(runtime, 142, "SXNetID", "Strong Extranet ID","1.3.101.1.4.1"); +ASN1.addObject(runtime, 143, "PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4","1.2.840.113549.1.12.1.1"); +ASN1.addObject(runtime, 144, "PBE-SHA1-RC4-40", "pbeWithSHA1And40BitRC4","1.2.840.113549.1.12.1.2"); +ASN1.addObject(runtime, 145, "PBE-SHA1-3DES", "pbeWithSHA1And3-KeyTripleDES-CBC","1.2.840.113549.1.12.1.3"); +ASN1.addObject(runtime, 146, "PBE-SHA1-2DES", "pbeWithSHA1And2-KeyTripleDES-CBC","1.2.840.113549.1.12.1.4"); +ASN1.addObject(runtime, 147, "PBE-SHA1-RC2-128", "pbeWithSHA1And128BitRC2-CBC","1.2.840.113549.1.12.1.5"); +ASN1.addObject(runtime, 148, "PBE-SHA1-RC2-40", "pbeWithSHA1And40BitRC2-CBC","1.2.840.113549.1.12.1.6"); +ASN1.addObject(runtime, 149, null, "keyBag","1.2.840.113549.1.12.10.1.1"); +ASN1.addObject(runtime, 150, null, "pkcs8ShroudedKeyBag","1.2.840.113549.1.12.10.1.2"); +ASN1.addObject(runtime, 151, null, "certBag","1.2.840.113549.1.12.10.1.3"); +ASN1.addObject(runtime, 152, null, "crlBag","1.2.840.113549.1.12.10.1.4"); +ASN1.addObject(runtime, 153, null, "secretBag","1.2.840.113549.1.12.10.1.5"); +ASN1.addObject(runtime, 154, null, "safeContentsBag","1.2.840.113549.1.12.10.1.6"); +ASN1.addObject(runtime, 155, null, "PBES2","1.2.840.113549.1.5.13"); +ASN1.addObject(runtime, 156, null, "PBMAC1","1.2.840.113549.1.5.14"); +ASN1.addObject(runtime, 157, null, "hmacWithSHA1","1.2.840.113549.2.7"); +ASN1.addObject(runtime, 158, "id-qt-cps", "Policy Qualifier CPS","1.3.6.1.5.5.7.2.1"); +ASN1.addObject(runtime, 159, "id-qt-unotice", "Policy Qualifier User Notice","1.3.6.1.5.5.7.2.2"); +ASN1.addObject(runtime, 160, "RC2-64-CBC", "rc2-64-cbc",null); +ASN1.addObject(runtime, 161, "SMIME-CAPS", "S/MIME Capabilities","1.2.840.113549.1.9.15"); +ASN1.addObject(runtime, 162, "PBE-MD2-RC2-64", "pbeWithMD2AndRC2-CBC","1.2.840.113549.1.5.4"); +ASN1.addObject(runtime, 163, "PBE-MD5-RC2-64", "pbeWithMD5AndRC2-CBC","1.2.840.113549.1.5.6"); +ASN1.addObject(runtime, 164, "PBE-SHA1-DES", "pbeWithSHA1AndDES-CBC","1.2.840.113549.1.5.10"); +ASN1.addObject(runtime, 165, "msExtReq", "Microsoft Extension Request","1.3.6.1.4.1.311.2.1.14"); +ASN1.addObject(runtime, 166, "extReq", "Extension Request","1.2.840.113549.1.9.14"); +ASN1.addObject(runtime, 167, "name", "name","2.5.4.41"); +ASN1.addObject(runtime, 168, "dnQualifier", "dnQualifier","2.5.4.46"); +ASN1.addObject(runtime, 169, "id-pe", null,"1.3.6.1.5.5.7.1"); +ASN1.addObject(runtime, 170, "id-ad", null,"1.3.6.1.5.5.7.48"); +ASN1.addObject(runtime, 171, "authorityInfoAccess", "Authority Information Access","1.3.6.1.5.5.7.1.1"); +ASN1.addObject(runtime, 172, "OCSP", "OCSP","1.3.6.1.5.5.7.48.1"); +ASN1.addObject(runtime, 173, "caIssuers", "CA Issuers","1.3.6.1.5.5.7.48.2"); +ASN1.addObject(runtime, 174, "OCSPSigning", "OCSP Signing","1.3.6.1.5.5.7.3.9"); +ASN1.addObject(runtime, 175, "AES-128-EBC", "aes-128-ebc","2.16.840.1.101.3.4.1.1"); +ASN1.addObject(runtime, 176, "AES-128-CBC", "aes-128-cbc","2.16.840.1.101.3.4.1.2"); +ASN1.addObject(runtime, 177, "AES-128-OFB", "aes-128-ofb","2.16.840.1.101.3.4.1.3"); +ASN1.addObject(runtime, 178, "AES-128-CFB", "aes-128-cfb","2.16.840.1.101.3.4.1.4"); +ASN1.addObject(runtime, 179, "AES-192-EBC", "aes-192-ebc","2.16.840.1.101.3.4.1.21"); +ASN1.addObject(runtime, 180, "AES-192-CBC", "aes-192-cbc","2.16.840.1.101.3.4.1.22"); +ASN1.addObject(runtime, 181, "AES-192-OFB", "aes-192-ofb","2.16.840.1.101.3.4.1.23"); +ASN1.addObject(runtime, 182, "AES-192-CFB", "aes-192-cfb","2.16.840.1.101.3.4.1.24"); +ASN1.addObject(runtime, 183, "AES-256-EBC", "aes-256-ebc","2.16.840.1.101.3.4.1.41"); +ASN1.addObject(runtime, 184, "AES-256-CBC", "aes-256-cbc","2.16.840.1.101.3.4.1.42"); +ASN1.addObject(runtime, 185, "AES-256-OFB", "aes-256-ofb","2.16.840.1.101.3.4.1.43"); +ASN1.addObject(runtime, 186, "AES-256-CFB", "aes-256-cfb","2.16.840.1.101.3.4.1.44"); + } + + public static interface KeyAndIv { + byte[] getKey(); + byte[] getIv(); + } + + private static class KeyAndIvImpl implements KeyAndIv { + private final byte[] key; + private final byte[] iv; + public KeyAndIvImpl(byte[] key, byte[] iv) { + this.key = key; + this.iv = iv; + } + public byte[] getKey() { + return key; + } + public byte[] getIv() { + return iv; + } + } + + public static PEMHandler getPEMHandler() { + try { + return new org.jruby.ext.openssl.BouncyCastlePEMHandler(); + } catch (Exception e) { + // fallback to... + } + return new DefaultPEMHandler(); + } + + public static KeyAndIv EVP_BytesToKey(int key_len, int iv_len, MessageDigest md, byte[] salt, byte[] data, int count) { + byte[] key = new byte[key_len]; + byte[] iv = new byte[iv_len]; + int key_ix = 0; + int iv_ix = 0; + byte[] md_buf = null; + int nkey = key_len; + int niv = iv_len; + int i = 0; + if(data == null) { + return new KeyAndIvImpl(key,iv); + } + int addmd = 0; + for(;;) { + md.reset(); + if(addmd++ > 0) { + md.update(md_buf); + } + md.update(data); + if(null != salt) { + md.update(salt,0,8); + } + md_buf = md.digest(); + for(i=1;i 0) { + for(;;) { + if(nkey == 0) break; + if(i == md_buf.length) break; + key[key_ix++] = md_buf[i]; + nkey--; + i++; + } + } + if(niv > 0 && i != md_buf.length) { + for(;;) { + if(niv == 0) break; + if(i == md_buf.length) break; + iv[iv_ix++] = md_buf[i]; + niv--; + i++; + } + } + if(nkey == 0 && niv == 0) { + break; + } + } + for(i=0;i + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; + +import javax.crypto.SecretKeyFactory; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateFactory; + +/** + * @author Ola Bini + */ +public class OpenSSLReal { + private static java.security.Provider BC_PROVIDER = null; + + static { + try { + BC_PROVIDER = (java.security.Provider) Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider").newInstance(); + } catch (Throwable ignored) { + // no bouncy castle available + } + } + + public interface Runnable { + public void run() throws GeneralSecurityException; + } + + public interface Callable { + public Object call() throws GeneralSecurityException; + } + + public static void doWithBCProvider(final Runnable toRun) throws GeneralSecurityException { + getWithBCProvider(new Callable() { + + public Object call() throws GeneralSecurityException { + toRun.run(); + return null; + } + }); + } + + // This method just adds BouncyCastleProvider if it's allowed. Removing + // "BC" can remove pre-installed or runtime-added BC provider by elsewhere + // and it causes unknown runtime error anywhere. We avoid this. To use + // part of jruby-openssl feature (X.509 and PKCS), users must be aware of + // dynamic BC provider adding. + public static Object getWithBCProvider(Callable toCall) throws GeneralSecurityException { + try { + if (BC_PROVIDER != null && java.security.Security.getProvider("BC") == null) { + java.security.Security.addProvider(BC_PROVIDER); + } + return toCall.call(); + } catch (NoSuchProviderException nspe) { + throw new GeneralSecurityException(bcExceptionMessage(nspe), nspe); + } catch (Exception e) { + throw new GeneralSecurityException(e.getMessage(), e); + } + } + + public static String bcExceptionMessage(NoSuchProviderException nspe) { + return "You need to configure JVM/classpath to enable BouncyCastle Security Provider: " + nspe.getMessage(); + } + + public static String bcExceptionMessage(NoClassDefFoundError ncdfe) { + return "You need to configure JVM/classpath to enable BouncyCastle Security Provider: NoClassDefFoundError: " + ncdfe.getMessage(); + } + + public static void createOpenSSL(Ruby runtime) { + RubyModule ossl = runtime.getOrCreateModule("OpenSSL"); + RubyClass standardError = runtime.getClass("StandardError"); + ossl.defineClassUnder("OpenSSLError", standardError, standardError.getAllocator()); + + // those are BC provider free (uses BC class but does not use BC provider) + PKey.createPKey(runtime, ossl); + BN.createBN(runtime, ossl); + Digest.createDigest(runtime, ossl); + Cipher.createCipher(runtime, ossl); + Random.createRandom(runtime, ossl); + HMAC.createHMAC(runtime, ossl); + Config.createConfig(runtime, ossl); + + // these classes depends on BC provider now. + try { + ASN1.createASN1(runtime, ossl); + X509.createX509(runtime, ossl); + NetscapeSPKI.createNetscapeSPKI(runtime, ossl); + PKCS7.createPKCS7(runtime, ossl); + } catch (SecurityException ignore) { + // some class might be prohibited to use. + runtime.getLoadService().require("openssl/dummy"); + } catch (Error ignore) { + // mainly for rescuing NoClassDefFoundError: no bc*.jar + runtime.getLoadService().require("openssl/dummy"); + } + try { + SSL.createSSL(runtime, ossl); + } catch (SecurityException ignore) { + // some class might be prohibited to use. ex. SSL* on GAE/J. + runtime.getLoadService().require("openssl/dummyssl"); + } catch (Error ignore) { + // mainly for rescuing NoClassDefFoundError: no bc*.jar + runtime.getLoadService().require("openssl/dummyssl"); + } + + runtime.getLoadService().require("jopenssl/version"); + String jopensslVersion = runtime.getClassFromPath("Jopenssl::Version").getConstant("VERSION").toString(); + ossl.setConstant("VERSION", runtime.newString("1.0.0")); + ossl.setConstant("OPENSSL_VERSION", + runtime.newString("jruby-ossl " + jopensslVersion)); + + try { + java.security.MessageDigest.getInstance("SHA224", BC_PROVIDER); + ossl.setConstant("OPENSSL_VERSION_NUMBER", runtime.newFixnum(9469999)); + } catch (NoSuchAlgorithmException nsae) { + ossl.setConstant("OPENSSL_VERSION_NUMBER", runtime.newFixnum(9469952)); + } + } + + public static javax.crypto.Cipher getCipherBC(final String algorithm) throws GeneralSecurityException { + return (javax.crypto.Cipher) getWithBCProvider(new Callable() { + + public Object call() throws GeneralSecurityException { + return javax.crypto.Cipher.getInstance(algorithm, "BC"); + } + }); + } + + public static SecretKeyFactory getSecretKeyFactoryBC(final String algorithm) throws GeneralSecurityException { + return (SecretKeyFactory) getWithBCProvider(new Callable() { + + public Object call() throws GeneralSecurityException { + return SecretKeyFactory.getInstance(algorithm, "BC"); + } + }); + } + + public static MessageDigest getMessageDigestBC(final String algorithm) throws GeneralSecurityException { + return (MessageDigest) getWithBCProvider(new Callable() { + + public Object call() throws GeneralSecurityException { + return MessageDigest.getInstance(algorithm, "BC"); + } + }); + } + + public static CertificateFactory getX509CertificateFactoryBC() throws GeneralSecurityException { + return (CertificateFactory) getWithBCProvider(new Callable() { + + public Object call() throws GeneralSecurityException { + return CertificateFactory.getInstance("X.509", "BC"); + } + }); + } +}// OpenSSLReal + diff --git a/src/org/jruby/ext/openssl/PEMHandler.java b/src/org/jruby/ext/openssl/PEMHandler.java new file mode 100644 index 00000000000..9e523f266c1 --- /dev/null +++ b/src/org/jruby/ext/openssl/PEMHandler.java @@ -0,0 +1,40 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.Reader; +import java.io.Writer; + +/** + * @author Ola Bini + */ +public interface PEMHandler { + Object readPEM(Reader read, String password) throws Exception; + void writePEM(Writer writ, Object obj, String algorithm, char[] password) throws Exception; + void writePEM(Writer writ, Object obj) throws Exception; +}// PEMHandler diff --git a/src/org/jruby/ext/openssl/PKCS10CertificationRequestExt.java b/src/org/jruby/ext/openssl/PKCS10CertificationRequestExt.java new file mode 100644 index 00000000000..58575f6063a --- /dev/null +++ b/src/org/jruby/ext/openssl/PKCS10CertificationRequestExt.java @@ -0,0 +1,158 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.ByteArrayOutputStream; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; + +import javax.security.auth.x500.X500Principal; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DEROutputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.pkcs.CertificationRequestInfo; +import org.bouncycastle.jce.PKCS10CertificationRequest; + +/** + * @author Ola Bini + */ +public class PKCS10CertificationRequestExt extends PKCS10CertificationRequest { + public PKCS10CertificationRequestExt(byte[] bytes) { + super(bytes); + } + + public PKCS10CertificationRequestExt(ASN1Sequence sequence) { + super(sequence); + } + + public PKCS10CertificationRequestExt( + String signatureAlgorithm, + org.bouncycastle.asn1.x509.X509Name subject, + PublicKey key, + ASN1Set attributes, + PrivateKey signingKey) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, SignatureException + { + super(signatureAlgorithm,subject,key,attributes,signingKey); + } + + public PKCS10CertificationRequestExt( + String signatureAlgorithm, + X500Principal subject, + PublicKey key, + ASN1Set attributes, + PrivateKey signingKey) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, SignatureException + { + super(signatureAlgorithm,subject,key,attributes,signingKey); + } + + public PKCS10CertificationRequestExt( + String signatureAlgorithm, + X500Principal subject, + PublicKey key, + ASN1Set attributes, + PrivateKey signingKey, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, SignatureException + { + super(signatureAlgorithm,subject,key,attributes,signingKey,provider); + } + + public PKCS10CertificationRequestExt( + String signatureAlgorithm, + org.bouncycastle.asn1.x509.X509Name subject, + PublicKey key, + ASN1Set attributes, + PrivateKey signingKey, + String provider) + throws NoSuchAlgorithmException, NoSuchProviderException, + InvalidKeyException, SignatureException + { + super(signatureAlgorithm,subject,key,attributes,signingKey,provider); + } + + public void setAttributes(DERSet attrs) { + ASN1Sequence seq = (ASN1Sequence)this.reqInfo.toASN1Object(); + ASN1EncodableVector v1 = new ASN1EncodableVector(); + for(int i=0;i<(seq.size()-1);i++) { + v1.add(seq.getObjectAt(i)); + } + v1.add(new DERTaggedObject(0,attrs)); + this.reqInfo = new CertificationRequestInfo(new DERSequence(v1)); + } + + public void setVersion(int v) { + DERInteger nVersion = new DERInteger(v); + ASN1Sequence seq = (ASN1Sequence)this.reqInfo.toASN1Object(); + ASN1EncodableVector v1 = new ASN1EncodableVector(); + v1.add(nVersion); + for(int i=1;i + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + + +import java.io.IOException; +import java.io.StringWriter; +import java.security.GeneralSecurityException; +import java.security.PrivateKey; +import java.security.cert.CertificateEncodingException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyBignum; +import org.jruby.RubyClass; +import org.jruby.RubyFile; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.impl.ASN1Registry; +import org.jruby.ext.openssl.impl.BIO; +import org.jruby.ext.openssl.impl.CipherSpec; +import org.jruby.ext.openssl.impl.MemBIO; +import org.jruby.ext.openssl.impl.Mime; +import org.jruby.ext.openssl.impl.NotVerifiedPKCS7Exception; +import org.jruby.ext.openssl.impl.PKCS7Exception; +import org.jruby.ext.openssl.impl.RecipInfo; +import org.jruby.ext.openssl.impl.SMIME; +import org.jruby.ext.openssl.impl.SignerInfoWithPkey; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.ext.openssl.x509store.Store; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.runtime.Arity; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class PKCS7 extends RubyObject { + private static final long serialVersionUID = -3925104500966826973L; + + private static ObjectAllocator PKCS7_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new PKCS7(runtime, klass); + } + }; + + public static void createPKCS7(Ruby runtime, RubyModule mOSSL) { + ThreadContext context = runtime.getCurrentContext(); + RubyClass cPKCS7 = mOSSL.defineClassUnder("PKCS7",runtime.getObject(),PKCS7_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + cPKCS7.defineClassUnder("PKCS7Error",openSSLError,openSSLError.getAllocator()); + cPKCS7.addReadWriteAttribute(context, "data"); + cPKCS7.addReadWriteAttribute(context, "error_string"); + cPKCS7.defineAnnotatedMethods(PKCS7.class); + cPKCS7.defineAnnotatedMethods(ModuleMethods.class); + + SignerInfo.createSignerInfo(runtime,cPKCS7); + RecipientInfo.createRecipientInfo(runtime,cPKCS7); + + cPKCS7.setConstant("TEXT",runtime.newFixnum(1)); + cPKCS7.setConstant("NOCERTS",runtime.newFixnum(2)); + cPKCS7.setConstant("NOSIGS",runtime.newFixnum(4)); + cPKCS7.setConstant("NOCHAIN",runtime.newFixnum(8)); + cPKCS7.setConstant("NOINTERN",runtime.newFixnum(16)); + cPKCS7.setConstant("NOVERIFY",runtime.newFixnum(32)); + cPKCS7.setConstant("DETACHED",runtime.newFixnum(64)); + cPKCS7.setConstant("BINARY",runtime.newFixnum(128)); + cPKCS7.setConstant("NOATTR",runtime.newFixnum(256)); + cPKCS7.setConstant("NOSMIMECAP",runtime.newFixnum(512)); + } + + public static BIO obj2bio(IRubyObject obj) { + if(obj instanceof RubyFile) { + throw new IllegalArgumentException("TODO: handle RubyFile correctly"); +// if (TYPE(obj) == T_FILE) { +// OpenFile *fptr; +// GetOpenFile(obj, fptr); +// rb_io_check_readable(fptr); +// bio = BIO_new_fp(fptr->f, BIO_NOCLOSE); + } else { + RubyString str = obj.convertToString(); + ByteList bl = str.getByteList(); + return BIO.memBuf(bl.bytes, bl.begin, bl.realSize); + } + } + + public static PKCS7 wrap(RubyClass klass, org.jruby.ext.openssl.impl.PKCS7 p7) { + PKCS7 wrapped = new PKCS7(klass.getRuntime(), klass); + wrapped.p7 = p7; + return wrapped; + } + + public static IRubyObject membio2str(Ruby runtime, BIO bio) { + return runtime.newString(new ByteList(((MemBIO)bio).getMemCopy(), false)); + } + + private static List x509_ary2sk(IRubyObject ary) { + List certs = new ArrayList(); + RubyArray arr = (RubyArray)ary; + for(int i = 0; i x509s = certs.isNil() + ? null + : x509_ary2sk(certs); + + try { + org.jruby.ext.openssl.impl.PKCS7 p7 = org.jruby.ext.openssl.impl.PKCS7.sign(x509, pkey, x509s, in, flg); + PKCS7 ret = wrap(Utils.getClassFromPath(recv.getRuntime(), "OpenSSL::PKCS7::PKCS7"), p7); + ret.setData(data); + return ret; + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(recv.getRuntime(), pkcs7e); + } + } + + /** ossl_pkcs7_s_encrypt + * + */ + @JRubyMethod(meta=true, rest=true) + public static IRubyObject encrypt(IRubyObject recv, IRubyObject[] args) { + IRubyObject certs, data, cipher = recv.getRuntime().getNil(), flags = recv.getRuntime().getNil(); + switch(Arity.checkArgumentCount(recv.getRuntime(), args, 2, 4)) { + case 4: + flags = args[3]; + case 3: + cipher = args[2]; + } + data = args[1]; + certs = args[0]; + CipherSpec ciph = null; + if (cipher.isNil()) { + try { + ciph = new CipherSpec(javax.crypto.Cipher.getInstance("RC2/CBC/PKCS5Padding"), Cipher.Algorithm.jsseToOssl("RC2/CBC/PKCS5Padding", 40), 40); + } catch (GeneralSecurityException gse) { + throw newPKCS7Error(recv.getRuntime(), gse.getMessage()); + } + } else { + Cipher c = ((Cipher) cipher); + ciph = new CipherSpec(c.getCipher(), c.getName(), c.getGenerateKeyLen() * 8); + } + int flg = flags.isNil() ? 0 : RubyNumeric.fix2int(flags); + byte[] in = data.convertToString().getBytes(); + List x509s = x509_ary2sk(certs); + try { + org.jruby.ext.openssl.impl.PKCS7 p7 = org.jruby.ext.openssl.impl.PKCS7.encrypt(x509s, in, ciph, flg); + PKCS7 ret = wrap(Utils.getClassFromPath(recv.getRuntime(), "OpenSSL::PKCS7::PKCS7"), p7); + ret.setData(data); + return ret; + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(recv.getRuntime(), pkcs7e); + } + } + } + + public PKCS7(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private org.jruby.ext.openssl.impl.PKCS7 p7; + + public void setData(IRubyObject object) { + setInstanceVariable("@data", object); + } + + public IRubyObject getData() { + return getInstanceVariable("@data"); + } + + @JRubyMethod(name="initialize", rest=true) + public IRubyObject _initialize(IRubyObject[] args) { + IRubyObject arg = null; + if(Arity.checkArgumentCount(getRuntime(), args, 0, 1) == 0) { + return this; + } + arg = args[0]; + arg = OpenSSLImpl.to_der_if_possible(arg); + BIO input = obj2bio(arg); + try { + p7 = org.jruby.ext.openssl.impl.PKCS7.readPEM(input); + if (p7 == null) { + input.reset(); + p7 = org.jruby.ext.openssl.impl.PKCS7.fromASN1(input); + } + } catch (IOException ioe) { + throw newPKCS7Error(getRuntime(), ioe.getMessage()); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + setData(getRuntime().getNil()); + return this; + } + + @Override + @JRubyMethod + public IRubyObject initialize_copy(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#init_copy"); + return this; + } + + @JRubyMethod(name="type=") + public IRubyObject set_type(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#type="); + return getRuntime().getNil(); + } + + @JRubyMethod(name="type") + public IRubyObject get_type() { + if(p7.isSigned()) { + return getRuntime().newSymbol("signed"); + } + if(p7.isEncrypted()) { + return getRuntime().newSymbol("encrypted"); + } + if(p7.isEnveloped()) { + return getRuntime().newSymbol("enveloped"); + } + if(p7.isSignedAndEnveloped()) { + return getRuntime().newSymbol("signedAndEnveloped"); + } + if(p7.isData()) { + return getRuntime().newSymbol("data"); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="detached=") + public IRubyObject set_detached(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#detached="); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject detached() { + System.err.println("WARNING: unimplemented method called PKCS7#detached"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="detached?") + public IRubyObject detached_p() { + System.err.println("WARNING: unimplemented method called PKCS7#detached?"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="cipher=") + public IRubyObject set_cipher(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#cipher="); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject add_signer(IRubyObject obj) { + SignerInfoWithPkey p7si = ((SignerInfo)obj).getSignerInfo().dup(); + + try { + p7.addSigner(p7si); + } catch (PKCS7Exception pkcse) { + throw newPKCS7Exception(getRuntime(), pkcse); + } + // TODO: Handle exception here + + if(p7.isSigned()) { + p7si.addSignedAttribute(ASN1Registry.NID_pkcs9_contentType, ASN1Registry.nid2obj(ASN1Registry.NID_pkcs7_data)); + } + + return this; + } + + /** ossl_pkcs7_get_signer + * + * This seems to return a list of SignerInfo objects. + * + */ + @JRubyMethod + public IRubyObject signers() { + Collection sk = p7.getSignerInfo(); + RubyArray ary = getRuntime().newArray(sk.size()); + for(SignerInfoWithPkey si : sk) { + ary.append(SignerInfo.create(getRuntime(), si)); + } + return ary; + } + + @JRubyMethod + public IRubyObject add_recipient(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#add_recipient"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject recipients() { + Collection sk = null; + + if(p7.isEnveloped()) { + sk = p7.getEnveloped().getRecipientInfo(); + } else if(p7.isSignedAndEnveloped()) { + sk = p7.getSignedAndEnveloped().getRecipientInfo(); + } else { + sk = null; + } + if(sk == null) { + return getRuntime().newArray(); + } + + RubyArray ary = getRuntime().newArray(sk.size()); + for(RecipInfo ri : sk) { + ary.append(RecipientInfo.create(getRuntime(), ri)); + } + return ary; + } + + @JRubyMethod + public IRubyObject add_certificate(IRubyObject obj) { + try { + p7.addCertificate(((X509Cert)obj).getAuxCert()); + } catch (PKCS7Exception pkcse) { + throw newPKCS7Exception(getRuntime(), pkcse); + } + return this; + } + + @JRubyMethod(name="certificates=") + public IRubyObject set_certificates(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#certificates="); + return getRuntime().getNil(); + } + + private Collection getCertificates() { + Collection certs; + int i = p7.getType(); + switch(i) { + case ASN1Registry.NID_pkcs7_signed: + certs = p7.getSign().getCert(); + break; + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + certs = p7.getSignedAndEnveloped().getCert(); + break; + default: + certs = new HashSet(); + break; + } + return certs; + } + + private RubyArray certsToArray(Collection certs) throws CertificateEncodingException { + RubyArray ary = getRuntime().newArray(certs.size()); + for(X509AuxCertificate x509 : certs) { + ary.append(X509Cert.wrap(getRuntime(), x509)); + } + return ary; + } + + @JRubyMethod + public IRubyObject certificates() { + try { + return certsToArray(getCertificates()); + } catch (CertificateEncodingException cee) { + throw newPKCS7Error(getRuntime(), cee.getMessage()); + } + } + + @JRubyMethod + public IRubyObject add_crl(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#add_crl"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="crls=") + public IRubyObject set_crls(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#crls="); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject crls() { + System.err.println("WARNING: unimplemented method called PKCS7#crls"); + return getRuntime().getNil(); + } + + @JRubyMethod(name={"add_data", "data="}) + public IRubyObject add_data(IRubyObject obj) { + System.err.println("WARNING: unimplemented method called PKCS7#add_data"); + return getRuntime().getNil(); + } + + @JRubyMethod(rest=true) + public IRubyObject verify(IRubyObject[] args) { + IRubyObject certs = null; + IRubyObject store = null; + IRubyObject indata = getRuntime().getNil(); + IRubyObject vflags = getRuntime().getNil(); + + switch(Arity.checkArgumentCount(getRuntime(), args, 2, 4)) { + case 4: + vflags = args[3]; + case 3: + indata = args[2]; + default: + store = args[1]; + certs = args[0]; + } + int flg = vflags.isNil() ? 0 : RubyNumeric.fix2int(vflags); + + if(indata.isNil()) { + indata = getData(); + } + + BIO in = indata.isNil() ? null : obj2bio(indata); + + List x509s = certs.isNil() + ? null + : x509_ary2sk(certs); + + Store x509st = ((X509Store)store).getStore(); + BIO out = BIO.mem(); + + boolean result = false; + try { + p7.verify(x509s, x509st, in, out, flg); + result = true; + } catch(NotVerifiedPKCS7Exception e) { + result = false; + } catch(PKCS7Exception pkcs7e) { + if (getRuntime().isDebug()) { + System.err.println(pkcs7e.toString()); + pkcs7e.printStackTrace(System.err); + } + result = false; + } + + IRubyObject data = membio2str(getRuntime(), out); + setData(data); + + return result ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod(rest=true) + public IRubyObject decrypt(IRubyObject[] args) { + IRubyObject dflags = getRuntime().getNil(); + if(Arity.checkArgumentCount(getRuntime(), args, 2, 3) == 3) { + dflags = args[2]; + } + IRubyObject pkey = args[0]; + IRubyObject cert = args[1]; + PrivateKey key = ((PKey)pkey).getPrivateKey(); + X509AuxCertificate x509 = ((X509Cert)cert).getAuxCert(); + int flg = dflags.isNil() ? 0 : RubyNumeric.fix2int(dflags); + + BIO out = BIO.mem(); + try { + p7.decrypt(key, x509, out, flg); + } catch (PKCS7Exception pkcs7e) { + throw newPKCS7Exception(getRuntime(), pkcs7e); + } + + return membio2str(getRuntime(), out); + } + + public static RaiseException newPKCS7Exception(Ruby ruby, PKCS7Exception pkcs7e) { + if (ruby.isDebug()) { + System.err.println(pkcs7e.toString()); + pkcs7e.printStackTrace(System.err); + } + return Utils.newError(ruby, "OpenSSL::PKCS7::PKCS7Error", pkcs7e.getMessage()); + } + + @JRubyMethod(name = {"to_pem", "to_s"}) + public IRubyObject to_pem() { + try { + StringWriter w = new StringWriter(); + PEMInputOutput.writePKCS7(w, p7.toASN1()); + w.close(); + return getRuntime().newString(w.toString()); + } catch (IOException ex) { + throw getRuntime().newIOErrorFromException(ex); + } + } + + @JRubyMethod + public IRubyObject to_der() { + try { + return getRuntime().newString(new ByteList(p7.toASN1(), false)); + } catch (IOException ioe) { + throw newPKCS7Error(getRuntime(), ioe.getMessage()); + } + } + + public static class SignerInfo extends RubyObject { + private static final long serialVersionUID = -3799397032272738848L; + + private static ObjectAllocator SIGNERINFO_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new SignerInfo(runtime, klass); + } + }; + + public static void createSignerInfo(Ruby runtime, RubyModule cPKCS7) { + RubyClass cPKCS7Signer = cPKCS7.defineClassUnder("SignerInfo",runtime.getObject(),SIGNERINFO_ALLOCATOR); + cPKCS7.defineConstant("Signer",cPKCS7Signer); + + cPKCS7Signer.defineAnnotatedMethods(SignerInfo.class); + } + + public static SignerInfo create(Ruby runtime, SignerInfoWithPkey info) { + SignerInfo sinfo = new SignerInfo(runtime, Utils.getClassFromPath(runtime, "OpenSSL::PKCS7::SignerInfo")); + sinfo.initWithSignerInformation(info); + return sinfo; + } + + public SignerInfo(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private SignerInfoWithPkey info; + + private void initWithSignerInformation(SignerInfoWithPkey info) { + this.info = info; + } + + SignerInfoWithPkey getSignerInfo() { + return info; + } + + @JRubyMethod + public IRubyObject initialize(IRubyObject arg1, IRubyObject arg2, IRubyObject arg3) { + System.err.println("WARNING: unimplemented method called SignerInfo#initialize"); + return this; + } + + + @JRubyMethod(name={"issuer","name"}) + public IRubyObject issuer() { + return X509Name.create(getRuntime(), info.getIssuerAndSerialNumber().getName()); + } + + @JRubyMethod + public IRubyObject serial() { + return RubyBignum.bignorm(getRuntime(), info.getIssuerAndSerialNumber().getCertificateSerialNumber().getValue()); + } + + @JRubyMethod + public IRubyObject signed_time() { + System.err.println("WARNING: unimplemented method called SignerInfo#signed_time"); + return getRuntime().getNil(); + } + } + + public static class RecipientInfo extends RubyObject { + private static final long serialVersionUID = 6977793206950149902L; + + private static ObjectAllocator RECIPIENTINFO_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new RecipientInfo(runtime, klass); + } + }; + + public static void createRecipientInfo(Ruby runtime, RubyModule cPKCS7) { + RubyClass cPKCS7Recipient = cPKCS7.defineClassUnder("RecipientInfo",runtime.getObject(),RECIPIENTINFO_ALLOCATOR); + + cPKCS7Recipient.defineAnnotatedMethods(RecipientInfo.class); + } + + public RecipientInfo(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + + public static RecipientInfo create(Ruby runtime, RecipInfo info) { + RecipientInfo rinfo = new RecipientInfo(runtime, Utils.getClassFromPath(runtime, "OpenSSL::PKCS7::RecipientInfo")); + rinfo.initWithRecipientInformation(info); + return rinfo; + } + + private RecipInfo info; + + private void initWithRecipientInformation(RecipInfo info) { + this.info = info; + } + + @JRubyMethod + public IRubyObject initialize(IRubyObject arg) { + System.err.println("WARNING: unimplemented method called RecipientInfo#initialize"); + return this; + } + + @JRubyMethod + public IRubyObject issuer() { + return X509Name.create(getRuntime(), info.getIssuerAndSerial().getName()); + } + + @JRubyMethod + public IRubyObject serial() { + return RubyBignum.bignorm(getRuntime(), info.getIssuerAndSerial().getCertificateSerialNumber().getValue()); + } + + @JRubyMethod + public IRubyObject enc_key() { + System.err.println("WARNING: unimplemented method called RecipientInfo#enc_key"); + return getRuntime().getNil(); + } + } + + private static RaiseException newPKCS7Error(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::PKCS7::PKCS7Error", message); + } +}// PKCS7 diff --git a/src/org/jruby/ext/openssl/PKey.java b/src/org/jruby/ext/openssl/PKey.java new file mode 100644 index 00000000000..88139980d51 --- /dev/null +++ b/src/org/jruby/ext/openssl/PKey.java @@ -0,0 +1,176 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.SignatureException; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public abstract class PKey extends RubyObject { + private static final long serialVersionUID = 6114668087816965720L; + + public static void createPKey(Ruby runtime, RubyModule ossl) { + RubyModule mPKey = ossl.defineModuleUnder("PKey"); + // PKey is abstract + RubyClass cPKey = mPKey.defineClassUnder("PKey",runtime.getObject(),ObjectAllocator.NOT_ALLOCATABLE_ALLOCATOR); + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + mPKey.defineClassUnder("PKeyError",openSSLError,openSSLError.getAllocator()); + + cPKey.defineAnnotatedMethods(PKey.class); + + PKeyRSA.createPKeyRSA(runtime,mPKey); + PKeyDSA.createPKeyDSA(runtime,mPKey); + PKeyDH.createPKeyDH(runtime, mPKey, cPKey); + } + + public static RaiseException newPKeyError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::PKey::PKeyError", message); + } + + public PKey(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + @Override + @JRubyMethod + public IRubyObject initialize() { + return this; + } + + PublicKey getPublicKey() { + return null; + } + + PrivateKey getPrivateKey() { + return null; + } + + String getAlgorithm() { + return "NONE"; + } + + // FIXME: any compelling reason for abstract method here? + public abstract IRubyObject to_der(); + + @JRubyMethod + public IRubyObject sign(IRubyObject digest, IRubyObject data) { + if (!this.callMethod(getRuntime().getCurrentContext(), "private?").isTrue()) { + throw getRuntime().newArgumentError("Private key is needed."); + } + String digAlg = ((Digest) digest).getShortAlgorithm(); + try { + Signature sig = Signature.getInstance(digAlg + "WITH" + getAlgorithm()); + sig.initSign(getPrivateKey()); + byte[] inp = data.convertToString().getBytes(); + sig.update(inp); + byte[] sigge = sig.sign(); + return RubyString.newString(getRuntime(), sigge); + } catch (GeneralSecurityException gse) { + throw newPKeyError(getRuntime(), gse.getMessage()); + } + /* + GetPKey(self, pkey); + EVP_SignInit(&ctx, GetDigestPtr(digest)); + StringValue(data); + EVP_SignUpdate(&ctx, RSTRING(data)->ptr, RSTRING(data)->len); + str = rb_str_new(0, EVP_PKEY_size(pkey)+16); + if (!EVP_SignFinal(&ctx, RSTRING(str)->ptr, &buf_len, pkey)) + ossl_raise(ePKeyError, NULL); + assert(buf_len <= RSTRING(str)->len); + RSTRING(str)->len = buf_len; + RSTRING(str)->ptr[buf_len] = 0; + + return str; + */ + } + + @JRubyMethod + public IRubyObject verify(IRubyObject digest, IRubyObject sig, IRubyObject data) { + if (!(digest instanceof Digest)) { + throw newPKeyError(getRuntime(), "invalid digest"); + } + if (!(sig instanceof RubyString)) { + throw newPKeyError(getRuntime(), "invalid signature"); + } + if (!(data instanceof RubyString)) { + throw newPKeyError(getRuntime(), "invalid data"); + } + byte[] sigBytes = ((RubyString)sig).getBytes(); + byte[] dataBytes = ((RubyString)data).getBytes(); + String algorithm = ((Digest)digest).getShortAlgorithm() + "WITH" + getAlgorithm(); + boolean valid; + try { + Signature signature = Signature.getInstance(algorithm); + signature.initVerify(getPublicKey()); + signature.update(dataBytes); + valid = signature.verify(sigBytes); + } catch (NoSuchAlgorithmException e) { + throw newPKeyError(getRuntime(), "unsupported algorithm: " + algorithm); + } catch (SignatureException e) { + throw newPKeyError(getRuntime(), "invalid signature"); + } catch (InvalidKeyException e) { + throw newPKeyError(getRuntime(), "invalid key"); + } + return getRuntime().newBoolean(valid); + } + + protected static void addSplittedAndFormatted(StringBuilder result, BigInteger value) { + String v = value.toString(16); + if ((v.length() % 2) != 0) { + v = "0" + v; + } + String sep = ""; + for (int i = 0; i < v.length(); i += 2) { + result.append(sep); + if ((i % 30) == 0) { + result.append("\n "); + } + result.append(v.substring(i, i + 2)); + sep = ":"; + } + result.append("\n"); + } +}// PKey diff --git a/src/org/jruby/ext/openssl/PKeyDH.java b/src/org/jruby/ext/openssl/PKeyDH.java new file mode 100644 index 00000000000..79a4b34f6ff --- /dev/null +++ b/src/org/jruby/ext/openssl/PKeyDH.java @@ -0,0 +1,394 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2007 William N Dortch + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.security.spec.InvalidParameterSpecException; +import java.util.HashMap; + +import javax.crypto.spec.DHParameterSpec; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyHash; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.Arity; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * OpenSSL::PKey::DH implementation. + * + * @author Bill Dortch + */ +public class PKeyDH extends PKey { + private static final long serialVersionUID = 293266329939132250L; + + // parameters used in generating 'p'; see [ossl]/crypto/dh/dh_gen.c #dh_builtin_genparams + private static final BigInteger GEN_2_ADD_PARAM = BigInteger.valueOf(24); + private static final BigInteger GEN_2_REM_PARAM = BigInteger.valueOf(11); + private static final BigInteger GEN_5_ADD_PARAM = BigInteger.valueOf(10); + private static final BigInteger GEN_5_REM_PARAM = BigInteger.valueOf(3); + private static final BigInteger DEFAULT_ADD_PARAM = BigInteger.valueOf(2); + private static final BigInteger DEFAULT_REM_PARAM = BigInteger.ONE; + + private static final BigInteger TWO = BigInteger.valueOf(2); + + // from [ossl]/crypto/dh/dh.h + private static final int OPENSSL_DH_MAX_MODULUS_BITS = 10000; + + private static ObjectAllocator PKEYDH_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new PKeyDH(runtime, klass); + } + }; + + public static void createPKeyDH(Ruby runtime, RubyModule pkeyModule, RubyClass pkeyClass) { + RubyClass dh = pkeyModule.defineClassUnder("DH", pkeyClass, PKEYDH_ALLOCATOR); + + RubyClass pkeyError = pkeyModule.getClass("PKeyError"); + pkeyModule.defineClassUnder("DHError",pkeyError,pkeyError.getAllocator()); + + dh.defineAnnotatedMethods(PKeyDH.class); + } + + public static RaiseException newDHError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::PKey::DHError", message); + } + + private static SecureRandom _secureRandom; + + private static SecureRandom getSecureRandom() { + SecureRandom rand; + if ((rand = _secureRandom) != null) { + return rand; + } + // FIXME: do we want a particular algorithm / provider? BC? + return _secureRandom = new SecureRandom(); + } + + // transient because: we do not want these value serialized (insecure) + // volatile because: permits unsynchronized reads in some cases + private transient volatile BigInteger dh_p; + private transient volatile BigInteger dh_g; + private transient volatile BigInteger dh_pub_key; + private transient volatile BigInteger dh_priv_key; + + // FIXME! need to figure out what it means in MRI/OSSL code to + // claim a DH is(/has) private if an engine is present -- doesn't really + // map to Java implementation. + + //private volatile boolean haveEngine; + + public PKeyDH(Ruby runtime, RubyClass clazz) { + super(runtime, clazz); + } + + @JRubyMethod(name="initialize", rest=true) + public synchronized IRubyObject dh_initialize(IRubyObject[] args) { + Ruby runtime = getRuntime(); + if (this.dh_p != null || this.dh_g != null || this.dh_pub_key != null || this.dh_priv_key != null) { + throw newDHError(runtime, "illegal initialization"); + } + int argc = Arity.checkArgumentCount(runtime, args, 0, 2); + if (argc > 0) { + IRubyObject arg0 = args[0]; + if (argc == 1 && arg0 instanceof RubyString) { + try { + DHParameterSpec spec = PEMInputOutput.readDHParameters(new StringReader(arg0.toString())); + this.dh_p = spec.getP(); + this.dh_g = spec.getG(); + } catch (NoClassDefFoundError ncdfe) { + throw newDHError(runtime, OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException e) { + throw runtime.newIOErrorFromException(e); + } catch (InvalidParameterSpecException e) { + throw runtime.newArgumentError(e.getMessage()); + } + } else { + int bits = RubyNumeric.fix2int(args[0]); + // g defaults to 2 + int gval = argc == 2 ? RubyNumeric.fix2int(args[1]) : 2; + BigInteger p; + try { + p = generateP(bits, gval); + } catch(IllegalArgumentException e) { + throw runtime.newArgumentError(e.getMessage()); + } + BigInteger g = BigInteger.valueOf(gval); + BigInteger x = generateX(p); + BigInteger y = generateY(p, g, x); + this.dh_p = p; + this.dh_g = g; + this.dh_priv_key = x; + this.dh_pub_key = y; + } + } + return this; + } + + public static BigInteger generateP(int bits, int g) { + + // FIXME? I'm following algorithms used in OpenSSL, could use JCE provider instead. + // (Note that I tried that, but got mystifying values of g returned by the param generator. + // In any case, in OpenSSL/MRI-OpenSSL, the caller supplies g, or it defaults to 2.) + + // see [ossl]/crypto/dh/dh_gen.c #dh_builtin_genparams + + if (bits < 2) throw new IllegalArgumentException("invalid bit length"); + if (g < 2) throw new IllegalArgumentException("invalid generator"); + + // generate safe prime meeting appropriate add/rem (mod) criteria + + switch(g) { + case 2: + // add = 24, rem = 11 + return BN.generatePrime(bits, true, GEN_2_ADD_PARAM, GEN_2_REM_PARAM); + case 5: + // add = 10, rem = 3 + return BN.generatePrime(bits, true, GEN_5_ADD_PARAM, GEN_5_REM_PARAM); + default: + // add = 2, rem = 1 + return BN.generatePrime(bits, true, DEFAULT_ADD_PARAM, DEFAULT_REM_PARAM); + } + } + + public static BigInteger generateX(BigInteger p, int limit) { + if (limit < 0) throw new IllegalArgumentException("invalid limit"); + + BigInteger x; + SecureRandom secureRandom = getSecureRandom(); + // adapting algorithm from org.bouncycastle.crypto.generators.DHKeyGeneratorHelper, + // which seems a little stronger (?) than OpenSSL's (OSSL just generates a random, + // while BC generates a random potential prime [for limit > 0], though it's not + // subject to Miller-Rabin [certainty = 0], but is subject to other constraints) + // see also [ossl]/crypto/dh/dh_key.c #generate_key + if (limit == 0) { + BigInteger pSub2 = p.subtract(TWO); + do { + x = BN.getRandomBIInRange(pSub2, secureRandom); + } while (x.equals(BigInteger.ZERO)); + } else { + do { + // generate potential prime, though with 0 certainty (no Miller-Rabin tests) + x = new BigInteger(limit, 0, secureRandom); + } while (x.equals(BigInteger.ZERO)); + } + return x; + } + + public static BigInteger generateX(BigInteger p) { + // OpenSSL default l(imit) is p bits - 1 -- see [ossl]/crypto/dh/dh_key.c #generate_key + return generateX(p, p.bitLength() - 1); + } + + public static BigInteger generateY(BigInteger p, BigInteger g, BigInteger x) { + return g.modPow(x, p); + } + + public static BigInteger generateY(BigInteger p, int g, BigInteger x) { + return generateY(p, BigInteger.valueOf(g), x); + } + + @JRubyMethod(name="generate_key!") + public synchronized IRubyObject dh_generate_key() { + BigInteger p, g, x, y; + if ((p = this.dh_p) == null || (g = this.dh_g) == null) { + throw newDHError(getRuntime(), "can't generate key"); + } + if ((x = this.dh_priv_key) == null) { + x = generateX(p); + } + y = generateY(p, g, x); + this.dh_priv_key = x; + this.dh_pub_key = y; + return this; + } + + @JRubyMethod(name="compute_key") + public synchronized IRubyObject dh_compute_key(IRubyObject other_pub_key) { + BigInteger x, y, p; + if ((y = BN.getBigInteger(other_pub_key)) == null) { + throw getRuntime().newArgumentError("invalid public key"); + } + if ((x = this.dh_priv_key) == null || (p = this.dh_p) == null) { + throw newDHError(getRuntime(), "can't compute key"); + } + int plen; + if ((plen = p.bitLength()) == 0 || plen > OPENSSL_DH_MAX_MODULUS_BITS) { + throw newDHError(getRuntime(), "can't compute key"); + } + return getRuntime().newString(new ByteList(computeKey(y, x, p), false)); + } + + public static byte[] computeKey(BigInteger y, BigInteger x, BigInteger p) { + return y.modPow(x, p).toByteArray(); + } + + @JRubyMethod(name="public?") + public IRubyObject dh_is_public() { + return getRuntime().newBoolean(dh_pub_key != null); + } + + @JRubyMethod(name="private?") + public IRubyObject dh_is_private() { + // FIXME! need to figure out what it means in MRI/OSSL code to + // claim a DH is private if an engine is present -- doesn't really + // map to Java implementation. + return getRuntime().newBoolean(dh_priv_key != null /* || haveEngine */); + } + + @JRubyMethod(name={"export", "to_pem", "to_s"}) + public IRubyObject dh_export() { + BigInteger p, g; + synchronized(this) { + p = this.dh_p; + g = this.dh_g; + } + StringWriter w = new StringWriter(); + try { + PEMInputOutput.writeDHParameters(w, new DHParameterSpec(p, g)); + w.flush(); + w.close(); + } catch (NoClassDefFoundError ncdfe) { + throw newDHError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException e) { + // shouldn't happen (string/buffer io only) + throw getRuntime().newIOErrorFromException(e); + } + return getRuntime().newString(w.toString()); + } + + @JRubyMethod(name = "to_der") + public IRubyObject dh_to_der() { + BigInteger p, g; + synchronized (this) { + p = this.dh_p; + g = this.dh_g; + } + try { + byte[] bytes = org.jruby.ext.openssl.impl.PKey.toDerDHKey(p, g); + return RubyString.newString(getRuntime(), bytes); + } catch (NoClassDefFoundError ncdfe) { + throw newDHError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException ioe) { + throw newDHError(getRuntime(), ioe.getMessage()); + } + } + + @JRubyMethod(name="params") + public IRubyObject dh_get_params() { + BigInteger p, g, x, y; + synchronized(this) { + p = this.dh_p; + g = this.dh_g; + x = this.dh_priv_key; + y = this.dh_pub_key; + } + Ruby runtime = getRuntime(); + HashMap params = new HashMap(); + + params.put(runtime.newString("p"), BN.newBN(runtime, p)); + params.put(runtime.newString("g"), BN.newBN(runtime, g)); + params.put(runtime.newString("pub_key"), BN.newBN(runtime, x)); + params.put(runtime.newString("priv_key"), BN.newBN(runtime, y)); + + return RubyHash.newHash(runtime, params, runtime.getNil()); + } + + // don't need synchronized as value is volatile + @JRubyMethod(name="p") + public IRubyObject dh_get_p() { + return getBN(dh_p); + } + + @JRubyMethod(name="p=") + public synchronized IRubyObject dh_set_p(IRubyObject arg) { + this.dh_p = BN.getBigInteger(arg); + return arg; + } + + // don't need synchronized as value is volatile + @JRubyMethod(name="g") + public IRubyObject dh_get_g() { + return getBN(dh_g); + } + + @JRubyMethod(name="g=") + public synchronized IRubyObject dh_set_g(IRubyObject arg) { + this.dh_g = BN.getBigInteger(arg); + return arg; + } + + // don't need synchronized as value is volatile + @JRubyMethod(name="pub_key") + public IRubyObject dh_get_pub_key() { + return getBN(dh_pub_key); + } + + @JRubyMethod(name="pub_key=") + public synchronized IRubyObject dh_set_pub_key(IRubyObject arg) { + this.dh_pub_key = BN.getBigInteger(arg); + return arg; + } + + // don't need synchronized as value is volatile + @JRubyMethod(name="priv_key") + public IRubyObject dh_get_priv_key() { + return getBN(dh_priv_key); + } + + @JRubyMethod(name="priv_key=") + public synchronized IRubyObject dh_set_priv_key(IRubyObject arg) { + this.dh_priv_key = BN.getBigInteger(arg); + return arg; + } + + private IRubyObject getBN(BigInteger value) { + if (value != null) { + return BN.newBN(getRuntime(), value); + } + return getRuntime().getNil(); + } + + // override differently-named abstract method from PKey + public IRubyObject to_der() { + return dh_to_der(); + } + +} diff --git a/src/org/jruby/ext/openssl/PKeyDSA.java b/src/org/jruby/ext/openssl/PKeyDSA.java new file mode 100644 index 00000000000..4aa3fd397d5 --- /dev/null +++ b/src/org/jruby/ext/openssl/PKeyDSA.java @@ -0,0 +1,474 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * Copyright (C) 2007 Wiliam N Dortch + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.interfaces.DSAKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class PKeyDSA extends PKey { + private static final long serialVersionUID = 2359742219218350277L; + + private static ObjectAllocator PKEYDSA_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new PKeyDSA(runtime, klass); + } + }; + + public static void createPKeyDSA(Ruby runtime, RubyModule mPKey) { + RubyClass cDSA = mPKey.defineClassUnder("DSA",mPKey.getClass("PKey"),PKEYDSA_ALLOCATOR); + RubyClass pkeyError = mPKey.getClass("PKeyError"); + mPKey.defineClassUnder("DSAError",pkeyError,pkeyError.getAllocator()); + + + cDSA.defineAnnotatedMethods(PKeyDSA.class); + } + + public static RaiseException newDSAError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::PKey::DSAError", message); + } + + public PKeyDSA(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private DSAPrivateKey privKey; + private DSAPublicKey pubKey; + + // specValues holds individual DSAPublicKeySpec components. this allows + // a public key to be constructed incrementally, as required by the + // current implementation of Net::SSH. + // (see net-ssh-1.1.2/lib/net/ssh/transport/ossl/buffer.rb #read_keyblob) + private BigInteger[] specValues; + + private static final int SPEC_Y = 0; + private static final int SPEC_P = 1; + private static final int SPEC_Q = 2; + private static final int SPEC_G = 3; + + @Override + PublicKey getPublicKey() { + return pubKey; + } + + @Override + PrivateKey getPrivateKey() { + return privKey; + } + + @Override + String getAlgorithm() { + return "DSA"; + } + + @JRubyMethod(name = "generate", meta = true) + public static IRubyObject generate(IRubyObject recv, IRubyObject arg) { + int keysize = RubyNumeric.fix2int(arg); + PKeyDSA dsa = new PKeyDSA(recv.getRuntime(), (RubyClass) recv); + dsaGenerate(dsa, keysize); + return dsa; + } + + /* + * c: dsa_generate + */ + private static void dsaGenerate(PKeyDSA dsa, int keysize) throws RaiseException { + try { + KeyPairGenerator gen = KeyPairGenerator.getInstance("DSA"); + gen.initialize(keysize, new SecureRandom()); + KeyPair pair = gen.generateKeyPair(); + dsa.privKey = (DSAPrivateKey) (pair.getPrivate()); + dsa.pubKey = (DSAPublicKey) (pair.getPublic()); + } catch (Exception e) { + throw newDSAError(dsa.getRuntime(), e.getMessage()); + } + } + + @JRubyMethod(rest = true) + public IRubyObject initialize(IRubyObject[] args) { + IRubyObject arg; + IRubyObject pass = null; + char[] passwd = null; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 0, 2) == 0) { + privKey = null; + pubKey = null; + } else { + arg = args[0]; + if (args.length > 1) { + pass = args[1]; + } + if (arg instanceof RubyFixnum) { + int keysize = RubyNumeric.fix2int(arg); + dsaGenerate(this, keysize); + } else { + if (pass != null && !pass.isNil()) { + passwd = pass.toString().toCharArray(); + } + arg = OpenSSLImpl.to_der_if_possible(arg); + RubyString str = arg.convertToString(); + + Object val = null; + KeyFactory fact = null; + try { + fact = KeyFactory.getInstance("DSA"); + } catch (NoSuchAlgorithmException e) { + throw getRuntime().newLoadError("unsupported key algorithm (DSA)"); + } + // TODO: ugly NoClassDefFoundError catching for no BC env. How can we remove this? + if (null == val) { + // PEM_read_bio_DSAPrivateKey + try { + val = PEMInputOutput.readDSAPrivateKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // PEM_read_bio_DSAPublicKey + try { + val = PEMInputOutput.readDSAPublicKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // PEM_read_bio_DSA_PUBKEY + try { + val = PEMInputOutput.readDSAPubKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // d2i_DSAPrivateKey_bio + try { + val = org.jruby.ext.openssl.impl.PKey.readDSAPrivateKey(str.getBytes()); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // d2i_DSA_PUBKEY_bio + try { + val = org.jruby.ext.openssl.impl.PKey.readDSAPublicKey(str.getBytes()); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + try { + val = fact.generatePrivate(new PKCS8EncodedKeySpec(str.getBytes())); + } catch (Exception e) { + val = null; + } + } + if (null == val) { + try { + val = fact.generatePublic(new X509EncodedKeySpec(str.getBytes())); + } catch (Exception e) { + val = null; + } + } + if (null == val) { + throw newDSAError(getRuntime(), "Neither PUB key nor PRIV key:"); + } + + if (val instanceof KeyPair) { + privKey = (DSAPrivateKey) (((KeyPair) val).getPrivate()); + pubKey = (DSAPublicKey) (((KeyPair) val).getPublic()); + } else if (val instanceof DSAPrivateKey) { + privKey = (DSAPrivateKey) val; + } else if (val instanceof DSAPublicKey) { + pubKey = (DSAPublicKey) val; + privKey = null; + } else { + throw newDSAError(getRuntime(), "Neither PUB key nor PRIV key:"); + } + } + } + return this; + } + + @JRubyMethod(name="public?") + public IRubyObject public_p() { + return pubKey != null ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod(name="private?") + public IRubyObject private_p() { + return privKey != null ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod + public IRubyObject to_der() { + try { + byte[] bytes = org.jruby.ext.openssl.impl.PKey.toDerDSAKey(pubKey, privKey); + return RubyString.newString(getRuntime(), bytes); + } catch (NoClassDefFoundError ncdfe) { + throw newDSAError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException ioe) { + throw newDSAError(getRuntime(), ioe.getMessage()); + } + } + + @JRubyMethod + public IRubyObject to_text() { + StringBuilder result = new StringBuilder(); + if (privKey != null) { + int len = privKey.getParams().getP().bitLength(); + result.append("Private-Key: (").append(len).append(" bit)").append("\n"); + result.append("priv:"); + addSplittedAndFormatted(result, privKey.getX()); + } + result.append("pub:"); + addSplittedAndFormatted(result, pubKey.getY()); + result.append("P:"); + addSplittedAndFormatted(result, pubKey.getParams().getP()); + result.append("Q:"); + addSplittedAndFormatted(result, pubKey.getParams().getQ()); + result.append("G:"); + addSplittedAndFormatted(result, pubKey.getParams().getG()); + return getRuntime().newString(result.toString()); + } + + @JRubyMethod + public IRubyObject public_key() { + PKeyDSA val = new PKeyDSA(getRuntime(),getMetaClass().getRealClass()); + val.privKey = null; + val.pubKey = this.pubKey; + return val; + } + + @JRubyMethod(name = {"export", "to_pem", "to_s"}, rest = true) + public IRubyObject export(IRubyObject[] args) { + StringWriter w = new StringWriter(); + org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 0, 2); + char[] passwd = null; + String algo = null; + if (args.length > 0 && !args[0].isNil()) { + algo = ((Cipher) args[0]).getAlgorithm(); + if (args.length > 1 && !args[1].isNil()) { + passwd = args[1].toString().toCharArray(); + } + } + try { + if (privKey != null) { + PEMInputOutput.writeDSAPrivateKey(w, privKey, algo, passwd); + } else { + PEMInputOutput.writeDSAPublicKey(w, pubKey); + } + w.close(); + return getRuntime().newString(w.toString()); + } catch (NoClassDefFoundError ncdfe) { + throw newDSAError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException ioe) { + throw newDSAError(getRuntime(), ioe.getMessage()); + } + } + + @JRubyMethod + public IRubyObject syssign(IRubyObject arg) { + // TODO + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject sysverify(IRubyObject arg, IRubyObject arg2) { + // TODO + return getRuntime().getNil(); + } + + @JRubyMethod(name="p") + public synchronized IRubyObject get_p() { + // FIXME: return only for public? + DSAKey key; + BigInteger param; + if ((key = this.pubKey) != null || (key = this.privKey) != null) { + if ((param = key.getParams().getP()) != null) { + return BN.newBN(getRuntime(), param); + } + } else if (specValues != null) { + if ((param = specValues[SPEC_P]) != null) { + return BN.newBN(getRuntime(), param); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="p=") + public synchronized IRubyObject set_p(IRubyObject p) { + return setKeySpecComponent(SPEC_P, p); + } + + @JRubyMethod(name="q") + public synchronized IRubyObject get_q() { + // FIXME: return only for public? + DSAKey key; + BigInteger param; + if ((key = this.pubKey) != null || (key = this.privKey) != null) { + if ((param = key.getParams().getQ()) != null) { + return BN.newBN(getRuntime(), param); + } + } else if (specValues != null) { + if ((param = specValues[SPEC_Q]) != null) { + return BN.newBN(getRuntime(), param); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="q=") + public synchronized IRubyObject set_q(IRubyObject q) { + return setKeySpecComponent(SPEC_Q, q); + } + + @JRubyMethod(name="g") + public synchronized IRubyObject get_g() { + // FIXME: return only for public? + DSAKey key; + BigInteger param; + if ((key = this.pubKey) != null || (key = this.privKey) != null) { + if ((param = key.getParams().getG()) != null) { + return BN.newBN(getRuntime(), param); + } + } else if (specValues != null) { + if ((param = specValues[SPEC_G]) != null) { + return BN.newBN(getRuntime(), param); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="g=") + public synchronized IRubyObject set_g(IRubyObject g) { + return setKeySpecComponent(SPEC_G, g); + } + + @JRubyMethod(name="pub_key") + public synchronized IRubyObject get_pub_key() { + DSAPublicKey key; + BigInteger param; + if ((key = this.pubKey) != null) { + return BN.newBN(getRuntime(), key.getY()); + } else if (specValues != null) { + if ((param = specValues[SPEC_Y]) != null) { + return BN.newBN(getRuntime(), param); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="pub_key=") + public synchronized IRubyObject set_pub_key(IRubyObject pub_key) { + return setKeySpecComponent(SPEC_Y, pub_key); + } + + private IRubyObject setKeySpecComponent(int index, IRubyObject value) { + BigInteger[] vals; + // illegal to set if we already have a key for this component + // FIXME: allow changes after keys are created? MRI doesn't prevent it... + if (this.pubKey != null || this.privKey != null || + (vals = this.specValues) != null && vals[index] != null) { + throw newDSAError(getRuntime(), "illegal modification"); + } + // get the BigInteger value + BigInteger bival = BN.getBigInteger(value); + + if (vals != null) { + // we already have some vals stored, store this one, too + vals[index] = bival; + // check to see if we have all values yet + for (int i = vals.length; --i >= 0; ) { + if (vals[i] == null) { + // still missing components, return + return value; + } + } + // we now have all components. create the key. + DSAPublicKeySpec spec = new DSAPublicKeySpec(vals[SPEC_Y], vals[SPEC_P], vals[SPEC_Q], vals[SPEC_G]); + try { + this.pubKey = (DSAPublicKey)KeyFactory.getInstance("DSA").generatePublic(spec); + } catch (InvalidKeySpecException e) { + throw newDSAError(getRuntime(), "invalid keyspec"); + } catch (NoSuchAlgorithmException e) { + throw newDSAError(getRuntime(), "unsupported key algorithm (DSA)"); + } + // clear out the specValues + this.specValues = null; + + } else { + + // first value received, save + this.specValues = new BigInteger[4]; + this.specValues[index] = bival; + } + return value; + } + +}// PKeyDSA diff --git a/src/org/jruby/ext/openssl/PKeyRSA.java b/src/org/jruby/ext/openssl/PKeyRSA.java new file mode 100644 index 00000000000..242a035d915 --- /dev/null +++ b/src/org/jruby/ext/openssl/PKeyRSA.java @@ -0,0 +1,751 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.RSAKeyGenParameterSpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.security.spec.X509EncodedKeySpec; + +import javax.crypto.Cipher; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyBignum; +import org.jruby.RubyFixnum; +import org.jruby.RubyHash; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.Arity; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class PKeyRSA extends PKey { + private static final long serialVersionUID = 3675324750727019454L; + + private static ObjectAllocator PKEYRSA_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new PKeyRSA(runtime, klass); + } + }; + + public static void createPKeyRSA(Ruby runtime, RubyModule mPKey) { + RubyClass cRSA = mPKey.defineClassUnder("RSA",mPKey.getClass("PKey"),PKEYRSA_ALLOCATOR); + RubyClass pkeyError = mPKey.getClass("PKeyError"); + mPKey.defineClassUnder("RSAError",pkeyError,pkeyError.getAllocator()); + + cRSA.defineAnnotatedMethods(PKeyRSA.class); + + cRSA.setConstant("PKCS1_PADDING",runtime.newFixnum(1)); + cRSA.setConstant("SSLV23_PADDING",runtime.newFixnum(2)); + cRSA.setConstant("NO_PADDING",runtime.newFixnum(3)); + cRSA.setConstant("PKCS1_OAEP_PADDING",runtime.newFixnum(4)); + } + + public static RaiseException newRSAError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::PKey::RSAError", message); + } + + public PKeyRSA(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private transient volatile RSAPrivateCrtKey privKey; + private transient volatile RSAPublicKey pubKey; + + // fields to hold individual RSAPublicKeySpec components. this allows + // a public key to be constructed incrementally, as required by the + // current implementation of Net::SSH. + // (see net-ssh-1.1.2/lib/net/ssh/transport/ossl/buffer.rb #read_keyblob) + private transient volatile BigInteger rsa_e; + private transient volatile BigInteger rsa_n; + + private transient volatile BigInteger rsa_d; + private transient volatile BigInteger rsa_p; + private transient volatile BigInteger rsa_q; + private transient volatile BigInteger rsa_dmp1; + private transient volatile BigInteger rsa_dmq1; + private transient volatile BigInteger rsa_iqmp; + + @Override + PublicKey getPublicKey() { + return pubKey; + } + + @Override + PrivateKey getPrivateKey() { + return privKey; + } + + @Override + String getAlgorithm() { + return "RSA"; + } + + @JRubyMethod(name = "generate", meta = true, rest = true) + public static IRubyObject generate(IRubyObject recv, IRubyObject[] args) { + BigInteger exp = RSAKeyGenParameterSpec.F4; + if (Arity.checkArgumentCount(recv.getRuntime(), args, 1, 2) == 2) { + if (args[1] instanceof RubyFixnum) { + exp = BigInteger.valueOf(RubyNumeric.num2long(args[1])); + } else { + exp = ((RubyBignum) args[1]).getValue(); + } + } + int keysize = RubyNumeric.fix2int(args[0]); + PKeyRSA rsa = new PKeyRSA(recv.getRuntime(), (RubyClass) recv); + rsaGenerate(rsa, keysize, exp); + return rsa; + } + + /* + * c: rsa_generate + */ + private static void rsaGenerate(PKeyRSA rsa, int keysize, BigInteger exp) throws RaiseException { + try { + KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); + gen.initialize(new RSAKeyGenParameterSpec(keysize, exp), new SecureRandom()); + KeyPair pair = gen.generateKeyPair(); + rsa.privKey = (RSAPrivateCrtKey) (pair.getPrivate()); + rsa.pubKey = (RSAPublicKey) (pair.getPublic()); + } catch (Exception e) { + throw newRSAError(rsa.getRuntime(), e.getMessage()); + } + } + + @JRubyMethod(frame = true, rest = true) + public IRubyObject initialize(IRubyObject[] args, Block block) { + IRubyObject arg; + IRubyObject pass = null; + char[] passwd = null; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 0, 2) == 0) { + privKey = null; + pubKey = null; + } else { + arg = args[0]; + if (args.length > 1) { + pass = args[1]; + } + if (arg instanceof RubyFixnum) { + int keysize = RubyNumeric.fix2int(arg); + BigInteger exp = RSAKeyGenParameterSpec.F4; + if (null != pass && !pass.isNil()) { + exp = BigInteger.valueOf(RubyNumeric.num2long(pass)); + } + rsaGenerate(this, keysize, exp); + } else { + if (pass != null && !pass.isNil()) { + passwd = pass.toString().toCharArray(); + } + arg = OpenSSLImpl.to_der_if_possible(arg); + RubyString str = arg.convertToString(); + + Object val = null; + KeyFactory fact = null; + try { + fact = KeyFactory.getInstance("RSA"); + } catch (Exception e) { + throw getRuntime().newRuntimeError("unsupported key algorithm (RSA)"); + } + // TODO: ugly NoClassDefFoundError catching for no BC env. How can we remove this? + if (null == val) { + // PEM_read_bio_RSAPrivateKey + try { + val = PEMInputOutput.readPrivateKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // PEM_read_bio_RSAPublicKey + try { + val = PEMInputOutput.readRSAPublicKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // PEM_read_bio_RSA_PUBKEY + try { + val = PEMInputOutput.readRSAPubKey(new StringReader(str.toString()), passwd); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // d2i_RSAPrivateKey_bio + try { + val = org.jruby.ext.openssl.impl.PKey.readRSAPrivateKey(str.getBytes()); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // d2i_RSAPublicKey_bio + try { + val = org.jruby.ext.openssl.impl.PKey.readRSAPublicKey(str.getBytes()); + } catch (NoClassDefFoundError e) { + val = null; + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // try to read PrivateKeyInfo. + try { + val = fact.generatePrivate(new PKCS8EncodedKeySpec(str.getBytes())); + } catch (Exception e) { + val = null; + } + } + if (null == val) { + // try to read SubjectPublicKeyInfo. + try { + val = fact.generatePublic(new X509EncodedKeySpec(str.getBytes())); + } catch (Exception e) { + val = null; + } + } + if (null == val) { + throw newRSAError(getRuntime(), "Neither PUB key nor PRIV key:"); + } + + if (val instanceof KeyPair) { + privKey = (RSAPrivateCrtKey) (((KeyPair) val).getPrivate()); + pubKey = (RSAPublicKey) (((KeyPair) val).getPublic()); + } else if (val instanceof RSAPrivateCrtKey) { + privKey = (RSAPrivateCrtKey) val; + try { + pubKey = (RSAPublicKey) (fact.generatePublic(new RSAPublicKeySpec(privKey.getModulus(), privKey.getPublicExponent()))); + } catch (Exception e) { + throw newRSAError(getRuntime(), "Something rotten with private key"); + } + } else if (val instanceof RSAPublicKey) { + pubKey = (RSAPublicKey) val; + privKey = null; + } else { + throw newRSAError(getRuntime(), "Neither PUB key nor PRIV key:"); + } + } + } + return this; + } + + @JRubyMethod(name="public?") + public IRubyObject public_p() { + return pubKey != null ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod(name="private?") + public IRubyObject private_p() { + return privKey != null ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod + public IRubyObject to_der() { + try { + byte[] bytes = org.jruby.ext.openssl.impl.PKey.toDerRSAKey(pubKey, privKey); + return RubyString.newString(getRuntime(), bytes); + } catch (NoClassDefFoundError ncdfe) { + throw newRSAError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException ioe) { + throw newRSAError(getRuntime(), ioe.getMessage()); + } + } + + @JRubyMethod + public IRubyObject public_key() { + PKeyRSA val = new PKeyRSA(getRuntime(),getMetaClass().getRealClass()); + val.privKey = null; + val.pubKey = this.pubKey; + return val; + } + + @JRubyMethod + public IRubyObject params() { + ThreadContext ctx = getRuntime().getCurrentContext(); + RubyHash hash = RubyHash.newHash(getRuntime()); + if(privKey != null) { + hash.op_aset(ctx, getRuntime().newString("iqmp"), BN.newBN(getRuntime(), privKey.getCrtCoefficient())); + hash.op_aset(ctx, getRuntime().newString("n"), BN.newBN(getRuntime(), privKey.getModulus())); + hash.op_aset(ctx, getRuntime().newString("d"), BN.newBN(getRuntime(), privKey.getPrivateExponent())); + hash.op_aset(ctx, getRuntime().newString("p"), BN.newBN(getRuntime(), privKey.getPrimeP())); + hash.op_aset(ctx, getRuntime().newString("e"), BN.newBN(getRuntime(), privKey.getPublicExponent())); + hash.op_aset(ctx, getRuntime().newString("q"), BN.newBN(getRuntime(), privKey.getPrimeQ())); + hash.op_aset(ctx, getRuntime().newString("dmq1"), BN.newBN(getRuntime(), privKey.getPrimeExponentQ())); + hash.op_aset(ctx, getRuntime().newString("dmp1"), BN.newBN(getRuntime(), privKey.getPrimeExponentP())); + + } else { + hash.op_aset(ctx, getRuntime().newString("iqmp"), BN.newBN(getRuntime(), BigInteger.ZERO)); + hash.op_aset(ctx, getRuntime().newString("n"), BN.newBN(getRuntime(), pubKey.getModulus())); + hash.op_aset(ctx, getRuntime().newString("d"), BN.newBN(getRuntime(), BigInteger.ZERO)); + hash.op_aset(ctx, getRuntime().newString("p"), BN.newBN(getRuntime(), BigInteger.ZERO)); + hash.op_aset(ctx, getRuntime().newString("e"), BN.newBN(getRuntime(), pubKey.getPublicExponent())); + hash.op_aset(ctx, getRuntime().newString("q"), BN.newBN(getRuntime(), BigInteger.ZERO)); + hash.op_aset(ctx, getRuntime().newString("dmq1"), BN.newBN(getRuntime(), BigInteger.ZERO)); + hash.op_aset(ctx, getRuntime().newString("dmp1"), BN.newBN(getRuntime(), BigInteger.ZERO)); + } + return hash; + } + + @JRubyMethod + public IRubyObject to_text() { + StringBuilder result = new StringBuilder(); + if (privKey != null) { + int len = privKey.getModulus().bitLength(); + result.append("Private-Key: (").append(len).append(" bit)").append("\n"); + result.append("modulus:"); + addSplittedAndFormatted(result, privKey.getModulus()); + result.append("publicExponent: ").append(privKey.getPublicExponent()).append(" (0x").append(privKey.getPublicExponent().toString(16)).append(")\n"); + result.append("privateExponent:"); + addSplittedAndFormatted(result, privKey.getPrivateExponent()); + result.append("prime1:"); + addSplittedAndFormatted(result, privKey.getPrimeP()); + result.append("prime2:"); + addSplittedAndFormatted(result, privKey.getPrimeQ()); + result.append("exponent1:"); + addSplittedAndFormatted(result, privKey.getPrimeExponentP()); + result.append("exponent2:"); + addSplittedAndFormatted(result, privKey.getPrimeExponentQ()); + result.append("coefficient:"); + addSplittedAndFormatted(result, privKey.getCrtCoefficient()); + } else { + int len = pubKey.getModulus().bitLength(); + result.append("Modulus (").append(len).append(" bit):"); + addSplittedAndFormatted(result, pubKey.getModulus()); + result.append("Exponent: ").append(pubKey.getPublicExponent()).append(" (0x").append(pubKey.getPublicExponent().toString(16)).append(")\n"); + } + return getRuntime().newString(result.toString()); + } + + @JRubyMethod(name = {"export", "to_pem", "to_s"}, rest = true) + public IRubyObject export(IRubyObject[] args) { + StringWriter w = new StringWriter(); + org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 0, 2); + char[] passwd = null; + String algo = null; + if (args.length > 0 && !args[0].isNil()) { + algo = ((org.jruby.ext.openssl.Cipher) args[0]).getAlgorithm(); + if (args.length > 1 && !args[1].isNil()) { + passwd = args[1].toString().toCharArray(); + } + } + try { + if (privKey != null) { + PEMInputOutput.writeRSAPrivateKey(w, privKey, algo, passwd); + } else { + PEMInputOutput.writeRSAPublicKey(w, pubKey); + } + w.close(); + return getRuntime().newString(w.toString()); + } catch (NoClassDefFoundError ncdfe) { + throw newRSAError(getRuntime(), OpenSSLReal.bcExceptionMessage(ncdfe)); + } catch (IOException ioe) { + throw newRSAError(getRuntime(), ioe.getMessage()); + } + } + + private String getPadding(int padding) { + if(padding < 1 || padding > 4) { + throw newRSAError(getRuntime(), null); + } + // BC accepts "/NONE/*" but SunJCE doesn't. use "/ECB/*" + String p = "/ECB/PKCS1Padding"; + if(padding == 3) { + p = "/ECB/NoPadding"; + } else if(padding == 4) { + p = "/ECB/OAEPWithMD5AndMGF1Padding"; + } else if(padding == 2) { + p = "/ECB/ISO9796-1Padding"; + } + return p; + } + + @JRubyMethod(rest = true) + public IRubyObject private_encrypt(IRubyObject[] args) { + int padding = 1; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 1, 2) == 2 && !args[1].isNil()) { + padding = RubyNumeric.fix2int(args[1]); + } + String p = getPadding(padding); + RubyString buffer = args[0].convertToString(); + if (privKey == null) { + throw newRSAError(getRuntime(), "private key needed."); + } + try { + Cipher engine = Cipher.getInstance("RSA" + p); + engine.init(Cipher.ENCRYPT_MODE, privKey); + byte[] outp = engine.doFinal(buffer.getBytes()); + return RubyString.newString(getRuntime(), outp); + } catch (GeneralSecurityException gse) { + throw newRSAError(getRuntime(), gse.getMessage()); + } + } + + @JRubyMethod(rest = true) + public IRubyObject private_decrypt(IRubyObject[] args) { + int padding = 1; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 1, 2) == 2 && !args[1].isNil()) { + padding = RubyNumeric.fix2int(args[1]); + } + String p = getPadding(padding); + RubyString buffer = args[0].convertToString(); + if (privKey == null) { + throw newRSAError(getRuntime(), "private key needed."); + } + try { + Cipher engine = Cipher.getInstance("RSA" + p); + engine.init(Cipher.DECRYPT_MODE, privKey); + byte[] outp = engine.doFinal(buffer.getBytes()); + return RubyString.newString(getRuntime(), outp); + } catch (GeneralSecurityException gse) { + throw newRSAError(getRuntime(), gse.getMessage()); + } + } + + @JRubyMethod(rest = true) + public IRubyObject public_encrypt(IRubyObject[] args) { + int padding = 1; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 1, 2) == 2 && !args[1].isNil()) { + padding = RubyNumeric.fix2int(args[1]); + } + String p = getPadding(padding); + RubyString buffer = args[0].convertToString(); + try { + Cipher engine = Cipher.getInstance("RSA" + p); + engine.init(Cipher.ENCRYPT_MODE, pubKey); + byte[] outp = engine.doFinal(buffer.getBytes()); + return RubyString.newString(getRuntime(), outp); + } catch (GeneralSecurityException gse) { + throw newRSAError(getRuntime(), gse.getMessage()); + } + } + + @JRubyMethod(rest = true) + public IRubyObject public_decrypt(IRubyObject[] args) { + int padding = 1; + if (org.jruby.runtime.Arity.checkArgumentCount(getRuntime(), args, 1, 2) == 2 && !args[1].isNil()) { + padding = RubyNumeric.fix2int(args[1]); + } + String p = getPadding(padding); + RubyString buffer = args[0].convertToString(); + try { + Cipher engine = Cipher.getInstance("RSA" + p); + engine.init(Cipher.DECRYPT_MODE, pubKey); + byte[] outp = engine.doFinal(buffer.getBytes()); + return RubyString.newString(getRuntime(), outp); + } catch (GeneralSecurityException gse) { + throw newRSAError(getRuntime(), gse.getMessage()); + } + } + + @JRubyMethod(name="d=") + public synchronized IRubyObject set_d(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_d = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="p=") + public synchronized IRubyObject set_p(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_p = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="q=") + public synchronized IRubyObject set_q(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_q = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="dmp1=") + public synchronized IRubyObject set_dmp1(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_dmp1 = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="dmq1=") + public synchronized IRubyObject set_dmq1(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_dmq1 = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="iqmp=") + public synchronized IRubyObject set_iqmp(IRubyObject value) { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + rsa_iqmp = BN.getBigInteger(value); + generatePrivateKeyIfParams(); + return value; + } + + @JRubyMethod(name="iqmp") + public synchronized IRubyObject get_iqmp() { + BigInteger iqmp = null; + if (privKey != null) { + iqmp = privKey.getCrtCoefficient(); + } else { + iqmp = rsa_iqmp; + } + if (iqmp != null) { + return BN.newBN(getRuntime(), iqmp); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="dmp1") + public synchronized IRubyObject get_dmp1() { + BigInteger dmp1 = null; + if (privKey != null) { + dmp1 = privKey.getPrimeExponentP(); + } else { + dmp1 = rsa_dmp1; + } + if (dmp1 != null) { + return BN.newBN(getRuntime(), dmp1); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="dmq1") + public synchronized IRubyObject get_dmq1() { + BigInteger dmq1 = null; + if (privKey != null) { + dmq1 = privKey.getPrimeExponentQ(); + } else { + dmq1 = rsa_dmq1; + } + if (dmq1 != null) { + return BN.newBN(getRuntime(), dmq1); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="d") + public synchronized IRubyObject get_d() { + BigInteger d = null; + if (privKey != null) { + d = privKey.getPrivateExponent(); + } else { + d = rsa_d; + } + if (d != null) { + return BN.newBN(getRuntime(), d); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="p") + public synchronized IRubyObject get_p() { + BigInteger p = null; + if (privKey != null) { + p = privKey.getPrimeP(); + } else { + p = rsa_p; + } + if (p != null) { + return BN.newBN(getRuntime(), p); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="q") + public synchronized IRubyObject get_q() { + BigInteger q = null; + if (privKey != null) { + q = privKey.getPrimeQ(); + } else { + q = rsa_q; + } + if (q != null) { + return BN.newBN(getRuntime(), q); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="e") + public synchronized IRubyObject get_e() { + RSAPublicKey key; + BigInteger e; + if ((key = pubKey) != null) { + e = key.getPublicExponent(); + } else if(privKey != null) { + e = privKey.getPublicExponent(); + } else { + e = rsa_e; + } + if (e != null) { + return BN.newBN(getRuntime(), e); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="e=") + public synchronized IRubyObject set_e(IRubyObject value) { + rsa_e = BN.getBigInteger(value); + + if(privKey == null) { + generatePrivateKeyIfParams(); + } + if(pubKey == null) { + generatePublicKeyIfParams(); + } + return value; + } + + @JRubyMethod(name="n") + public synchronized IRubyObject get_n() { + RSAPublicKey key; + BigInteger n; + if ((key = pubKey) != null) { + n = key.getModulus(); + } else if(privKey != null) { + n = privKey.getModulus(); + } else { + n = rsa_n; + } + if (n != null) { + return BN.newBN(getRuntime(), n); + } + return getRuntime().getNil(); + } + + @JRubyMethod(name="n=") + public synchronized IRubyObject set_n(IRubyObject value) { + rsa_n = BN.getBigInteger(value); + + if(privKey == null) { + generatePrivateKeyIfParams(); + } + if(pubKey == null) { + generatePublicKeyIfParams(); + } + return value; + } + + private void generatePublicKeyIfParams() { + if (pubKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + BigInteger e, n; + if ((e = rsa_e) != null && (n = rsa_n) != null) { + KeyFactory fact; + try { + fact = KeyFactory.getInstance("RSA"); + } catch(Exception ex) { + throw getRuntime().newLoadError("unsupported key algorithm (RSA)"); + } + try { + pubKey = (RSAPublicKey)fact.generatePublic(new RSAPublicKeySpec(n, e)); + } catch (InvalidKeySpecException ex) { + throw newRSAError(getRuntime(), "invalid parameters"); + } + rsa_e = null; + rsa_n = null; + } + } + + private void generatePrivateKeyIfParams() { + if (privKey != null) { + throw newRSAError(getRuntime(), "illegal modification"); + } + if (rsa_e != null && rsa_n != null && rsa_p != null && rsa_q != null && rsa_d != null && rsa_dmp1 != null && rsa_dmq1 != null && rsa_iqmp != null) { + KeyFactory fact; + try { + fact = KeyFactory.getInstance("RSA"); + } catch(Exception ex) { + throw getRuntime().newLoadError("unsupported key algorithm (RSA)"); + } + try { + privKey = (RSAPrivateCrtKey)fact.generatePrivate(new RSAPrivateCrtKeySpec(rsa_n, rsa_e, rsa_d, rsa_p, rsa_q, rsa_dmp1, rsa_dmq1, rsa_iqmp)); + } catch (InvalidKeySpecException ex) { + throw newRSAError(getRuntime(), "invalid parameters"); + } + rsa_n = null; + rsa_e = null; + rsa_d = null; + rsa_p = null; + rsa_q = null; + rsa_dmp1 = null; + rsa_dmq1 = null; + rsa_iqmp = null; + } + } +}// PKeyRSA diff --git a/src/org/jruby/ext/openssl/Random.java b/src/org/jruby/ext/openssl/Random.java new file mode 100644 index 00000000000..66e9d553143 --- /dev/null +++ b/src/org/jruby/ext/openssl/Random.java @@ -0,0 +1,103 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.SecureRandom; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class Random { + private final static class RandomHolder { + public java.util.Random[] randomizers; + } + public static void createRandom(Ruby runtime, RubyModule ossl) { + RubyModule rand = ossl.defineModuleUnder("Random"); + + RubyClass osslError = (RubyClass)ossl.getConstant("OpenSSLError"); + rand.defineClassUnder("RandomError",osslError,osslError.getAllocator()); + + rand.defineAnnotatedMethods(Random.class); + + RandomHolder holder = new RandomHolder(); + holder.randomizers = new java.util.Random[]{new java.util.Random(), new SecureRandom()}; + rand.dataWrapStruct(holder); + } + + @JRubyMethod(meta=true) + public static IRubyObject seed(IRubyObject recv, IRubyObject arg) { + return recv.getRuntime().getNil(); + } + @JRubyMethod(meta=true) + public static IRubyObject load_random_file(IRubyObject recv, IRubyObject arg) { + return recv.getRuntime().getNil(); + } + @JRubyMethod(meta=true) + public static IRubyObject write_random_file(IRubyObject recv, IRubyObject arg) { + return recv.getRuntime().getNil(); + } + + @JRubyMethod(meta=true) + public static IRubyObject random_bytes(IRubyObject recv, IRubyObject arg) { + return generate(recv, arg, 1); + } + + @JRubyMethod(meta=true) + public static IRubyObject pseudo_bytes(IRubyObject recv, IRubyObject arg) { + return generate(recv, arg, 0); + } + + private static RubyString generate(IRubyObject recv, IRubyObject arg, int ix) { + RandomHolder holder = (RandomHolder)recv.dataGetStruct(); + int len = RubyNumeric.fix2int(arg); + if (len < 0 || len > Integer.MAX_VALUE) { + throw recv.getRuntime().newArgumentError("negative string size (or size too big)"); + } + byte[] buf = new byte[len]; + holder.randomizers[ix].nextBytes(buf); + return RubyString.newString(recv.getRuntime(), new ByteList(buf,false)); + } + + @JRubyMethod(meta=true) + public static IRubyObject egd(IRubyObject recv, IRubyObject arg) { + return recv.getRuntime().getNil(); + } + @JRubyMethod(meta=true) + public static IRubyObject egd_bytes(IRubyObject recv, IRubyObject arg1, IRubyObject arg2) { + return recv.getRuntime().getNil(); + } +} diff --git a/src/org/jruby/ext/openssl/Request.java b/src/org/jruby/ext/openssl/Request.java new file mode 100644 index 00000000000..9d350a1b43d --- /dev/null +++ b/src/org/jruby/ext/openssl/Request.java @@ -0,0 +1,328 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.io.IOException; +import java.io.StringWriter; +import java.security.GeneralSecurityException; +import java.security.PublicKey; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERString; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class Request extends RubyObject { + private static final long serialVersionUID = -5551557929791764918L; + + private static ObjectAllocator REQUEST_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new Request(runtime, klass); + } + }; + + public static void createRequest(Ruby runtime, RubyModule mX509) { + RubyClass cRequest = mX509.defineClassUnder("Request",runtime.getObject(),REQUEST_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("RequestError",openSSLError,openSSLError.getAllocator()); + + cRequest.defineAnnotatedMethods(Request.class); + } + + private IRubyObject version; + private IRubyObject subject; + private IRubyObject public_key; + private boolean valid = false; + + private List attrs; + + private PKCS10CertificationRequestExt req; + + public Request(Ruby runtime, RubyClass type) { + super(runtime,type); + attrs = new ArrayList(); + } + + @JRubyMethod(name="initialize", frame=true, rest=true) + public IRubyObject _initialize(IRubyObject[] args, Block block) { + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,0,1) == 0) { + return this; + } + + byte[] req_bytes = OpenSSLImpl.readX509PEM(args[0]); + req = new PKCS10CertificationRequestExt(req_bytes); + version = getRuntime().newFixnum(req.getVersion()); + + String algo = null; + byte[] enc = null; + try { + PublicKey pkey = (PublicKey) OpenSSLReal.getWithBCProvider(new OpenSSLReal.Callable() { + + public Object call() throws GeneralSecurityException { + return req.getPublicKey("BC"); + } + }); + algo = pkey.getAlgorithm(); + enc = pkey.getEncoded(); + } catch (GeneralSecurityException gse) { + throw newX509ReqError(getRuntime(), gse.getMessage()); + } + + if("RSA".equalsIgnoreCase(algo)) { + this.public_key = Utils.newRubyInstance(getRuntime(), "OpenSSL::PKey::RSA", RubyString.newString(getRuntime(), enc)); + } else if("DSA".equalsIgnoreCase(algo)) { + this.public_key = Utils.newRubyInstance(getRuntime(), "OpenSSL::PKey::DSA", RubyString.newString(getRuntime(), enc)); + } else { + throw getRuntime().newLoadError("not implemented algo for public key: " + algo); + } + org.bouncycastle.asn1.x509.X509Name subName = req.getCertificationRequestInfo().getSubject(); + subject = Utils.newRubyInstance(getRuntime(), "OpenSSL::X509::Name"); + DERSequence subNameD = (DERSequence)subName.toASN1Object(); + for(int i=0;i iter = attrs.iterator();iter.hasNext();) { + v1.add(((Attribute)iter.next()).toASN1()); + } + try { + // PKCS10CertificationRequestExt depends BC. + OpenSSLReal.doWithBCProvider(new OpenSSLReal.Runnable() { + + public void run() throws GeneralSecurityException { + req = new PKCS10CertificationRequestExt(digAlg + "WITH" + keyAlg, + ((X509Name) subject).getRealName(), + ((PKey) public_key).getPublicKey(), + new DERSet(v1), + ((PKey) key).getPrivateKey(), + "BC"); + } + }); + } catch (GeneralSecurityException gse) { + throw newX509ReqError(getRuntime(), gse.getMessage()); + } + req.setVersion(RubyNumeric.fix2int(version)); + valid = true; + return this; + } + + @JRubyMethod + public IRubyObject verify(IRubyObject key) { + try { + return valid && req.verify(((PKey)(key.callMethod(getRuntime().getCurrentContext(),"public_key"))).getPublicKey()) ? getRuntime().getTrue() : getRuntime().getFalse(); + } catch(Exception e) { + return getRuntime().getFalse(); + } + } + + @JRubyMethod + public IRubyObject attributes() { + return getRuntime().newArray(attrs); + } + + @SuppressWarnings("unchecked") + @JRubyMethod(name="attributes=") + public IRubyObject set_attributes(IRubyObject val) { + valid = false; + attrs.clear(); + attrs.addAll(((RubyArray)val).getList()); + if(req != null) { + ASN1EncodableVector v1 = new ASN1EncodableVector(); + for(Iterator iter = attrs.iterator();iter.hasNext();) { + v1.add(((Attribute)iter.next()).toASN1()); + } + req.setAttributes(new DERSet(v1)); + } + return val; + } + + @JRubyMethod + public IRubyObject add_attribute(IRubyObject val) { + valid = false; + attrs.add(val); + if(req != null) { + ASN1EncodableVector v1 = new ASN1EncodableVector(); + for(Iterator iter = attrs.iterator();iter.hasNext();) { + v1.add(((Attribute)iter.next()).toASN1()); + } + req.setAttributes(new DERSet(v1)); + } + return getRuntime().getNil(); + } + + private static RaiseException newX509ReqError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::X509::RequestError", message); + } +}// Request diff --git a/src/org/jruby/ext/openssl/SSL.java b/src/org/jruby/ext/openssl/SSL.java new file mode 100644 index 00000000000..46cd504bb65 --- /dev/null +++ b/src/org/jruby/ext/openssl/SSL.java @@ -0,0 +1,94 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.exceptions.RaiseException; + +/** + * @author Ola Bini + */ +public class SSL { + + public static final int VERIFY_NONE = 0x00; + public static final int VERIFY_PEER = 0x01; + public static final int VERIFY_FAIL_IF_NO_PEER_CERT = 0x02; + public static final int VERIFY_CLIENT_ONCE = 0x04; + + public static final long OP_ALL = 0x00000FFFL; + public static final long OP_NO_TICKET = 0x00004000L; + public static final long OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00010000L; + public static final long OP_SINGLE_ECDH_USE = 0x00080000L; + public static final long OP_SINGLE_DH_USE = 0x00100000L; + public static final long OP_EPHEMERAL_RSA = 0x00200000L; + public static final long OP_CIPHER_SERVER_PREFERENCE = 0x00400000L; + public static final long OP_TLS_ROLLBACK_BUG = 0x00800000L; + public static final long OP_NO_SSLv2 = 0x01000000L; // supported + public static final long OP_NO_SSLv3 = 0x02000000L; // supported + public static final long OP_NO_TLSv1 = 0x04000000L; // supported + public static final long OP_PKCS1_CHECK_1 = 0x08000000L; + public static final long OP_PKCS1_CHECK_2 = 0x10000000L; + public static final long OP_NETSCAPE_CA_DN_BUG = 0x20000000L; + public static final long OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x40000000L; + + public static void createSSL(Ruby runtime, RubyModule ossl) { + RubyModule mSSL = ossl.defineModuleUnder("SSL"); + RubyClass openSSLError = ossl.getClass("OpenSSLError"); + mSSL.defineClassUnder("SSLError",openSSLError,openSSLError.getAllocator()); + + SSLContext.createSSLContext(runtime,mSSL); + SSLSocket.createSSLSocket(runtime,mSSL); + + mSSL.setConstant("VERIFY_NONE", runtime.newFixnum(VERIFY_NONE)); + mSSL.setConstant("VERIFY_PEER", runtime.newFixnum(VERIFY_PEER)); + mSSL.setConstant("VERIFY_FAIL_IF_NO_PEER_CERT", runtime.newFixnum(VERIFY_FAIL_IF_NO_PEER_CERT)); + mSSL.setConstant("VERIFY_CLIENT_ONCE", runtime.newFixnum(VERIFY_CLIENT_ONCE)); + + mSSL.setConstant("OP_ALL", runtime.newFixnum(OP_ALL)); + mSSL.setConstant("OP_NO_TICKET", runtime.newFixnum(OP_NO_TICKET)); + mSSL.setConstant("OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", runtime.newFixnum(OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)); + mSSL.setConstant("OP_SINGLE_ECDH_USE", runtime.newFixnum(OP_SINGLE_ECDH_USE)); + mSSL.setConstant("OP_SINGLE_DH_USE", runtime.newFixnum(OP_SINGLE_DH_USE)); + mSSL.setConstant("OP_EPHEMERAL_RSA", runtime.newFixnum(OP_EPHEMERAL_RSA)); + mSSL.setConstant("OP_CIPHER_SERVER_PREFERENCE", runtime.newFixnum(OP_CIPHER_SERVER_PREFERENCE)); + mSSL.setConstant("OP_TLS_ROLLBACK_BUG", runtime.newFixnum(OP_TLS_ROLLBACK_BUG)); + mSSL.setConstant("OP_NO_SSLv2", runtime.newFixnum(OP_NO_SSLv2)); + mSSL.setConstant("OP_NO_SSLv3", runtime.newFixnum(OP_NO_SSLv3)); + mSSL.setConstant("OP_NO_TLSv1", runtime.newFixnum(OP_NO_TLSv1)); + mSSL.setConstant("OP_PKCS1_CHECK_1", runtime.newFixnum(OP_PKCS1_CHECK_1)); + mSSL.setConstant("OP_PKCS1_CHECK_2", runtime.newFixnum(OP_PKCS1_CHECK_2)); + mSSL.setConstant("OP_NETSCAPE_CA_DN_BUG", runtime.newFixnum(OP_NETSCAPE_CA_DN_BUG)); + mSSL.setConstant("OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG", runtime.newFixnum(OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)); + } + + public static RaiseException newSSLError(Ruby runtime, Throwable t) { + throw Utils.newError(runtime, "OpenSSL::SSL::SSLError", t.getMessage()); + } +}// SSL diff --git a/src/org/jruby/ext/openssl/SSLContext.java b/src/org/jruby/ext/openssl/SSLContext.java new file mode 100644 index 00000000000..72199dd5b69 --- /dev/null +++ b/src/org/jruby/ext/openssl/SSLContext.java @@ -0,0 +1,731 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.GeneralSecurityException; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.net.ssl.SSLEngine; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.common.IRubyWarnings.ID; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.Certificate; +import org.jruby.ext.openssl.x509store.Name; +import org.jruby.ext.openssl.x509store.Store; +import org.jruby.ext.openssl.x509store.StoreContext; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.ext.openssl.x509store.X509Object; +import org.jruby.ext.openssl.x509store.X509Utils; +import org.jruby.javasupport.util.RuntimeHelpers; +import org.jruby.runtime.Arity; +import org.jruby.runtime.Block; +import org.jruby.runtime.BlockCallback; +import org.jruby.runtime.CallBlock; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class SSLContext extends RubyObject { + private static final long serialVersionUID = -6203496135962974777L; + + private final static String[] ctx_attrs = { + "cert", "key", "client_ca", "ca_file", "ca_path", + "timeout", "verify_mode", "verify_depth", + "verify_callback", "options", "cert_store", "extra_chain_cert", + "client_cert_cb", "tmp_dh_callback", "session_id_context"}; + + // Mapping table for OpenSSL's SSL_METHOD -> JSSE's SSLContext algorithm. + private final static Map SSL_VERSION_OSSL2JSSE; + // Mapping table for JSEE's enabled protocols for the algorithm. + private final static Map ENABLED_PROTOCOLS; + + static { + SSL_VERSION_OSSL2JSSE = new HashMap(); + ENABLED_PROTOCOLS = new HashMap(); + + SSL_VERSION_OSSL2JSSE.put("TLSv1", "TLSv1"); + SSL_VERSION_OSSL2JSSE.put("TLSv1_server", "TLSv1"); + SSL_VERSION_OSSL2JSSE.put("TLSv1_client", "TLSv1"); + ENABLED_PROTOCOLS.put("TLSv1", new String[] { "TLSv1" }); + + SSL_VERSION_OSSL2JSSE.put("SSLv2", "SSLv2"); + SSL_VERSION_OSSL2JSSE.put("SSLv2_server", "SSLv2"); + SSL_VERSION_OSSL2JSSE.put("SSLv2_client", "SSLv2"); + ENABLED_PROTOCOLS.put("SSLv2", new String[] { "SSLv2" }); + + SSL_VERSION_OSSL2JSSE.put("SSLv3", "SSLv3"); + SSL_VERSION_OSSL2JSSE.put("SSLv3_server", "SSLv3"); + SSL_VERSION_OSSL2JSSE.put("SSLv3_client", "SSLv3"); + ENABLED_PROTOCOLS.put("SSLv3", new String[] { "SSLv3" }); + + SSL_VERSION_OSSL2JSSE.put("SSLv23", "SSL"); + SSL_VERSION_OSSL2JSSE.put("SSLv23_server", "SSL"); + SSL_VERSION_OSSL2JSSE.put("SSLv23_client", "SSL"); + ENABLED_PROTOCOLS.put("SSL", new String[] { "SSLv2", "SSLv3", "TLSv1" }); + + // Followings(TLS, TLSv1.1) are JSSE only methods at present. Let's allow user to use it. + + SSL_VERSION_OSSL2JSSE.put("TLS", "TLS"); + ENABLED_PROTOCOLS.put("TLS", new String[] { "TLSv1", "TLSv1.1" }); + + SSL_VERSION_OSSL2JSSE.put("TLSv1.1", "TLSv1.1"); + ENABLED_PROTOCOLS.put("TLSv1.1", new String[] { "TLSv1.1" }); + } + + private static ObjectAllocator SSLCONTEXT_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new SSLContext(runtime, klass); + } + }; + + public static void createSSLContext(Ruby runtime, RubyModule mSSL) { + ThreadContext context = runtime.getCurrentContext(); + RubyClass cSSLContext = mSSL.defineClassUnder("SSLContext",runtime.getObject(),SSLCONTEXT_ALLOCATOR); + for(int i=0;i(); + for (X509Cert ele : convertToX509Certs(value)) { + internalCtx.extraChainCert.add(ele.getAuxCert()); + } + } + + value = getInstanceVariable("@key"); + PKey key = null; + if (value != null && !value.isNil()) { + Utils.checkKind(getRuntime(), value, "OpenSSL::PKey::PKey"); + key = (PKey) value; + } else { + key = getCallbackKey(); + } + value = getInstanceVariable("@cert"); + X509Cert cert = null; + if (value != null && !value.isNil()) { + Utils.checkKind(getRuntime(), value, "OpenSSL::X509::Certificate"); + cert = (X509Cert) value; + } else { + cert = getCallbackCert(); + } + if (key != null && cert != null) { + internalCtx.keyAlgorithm = key.getAlgorithm(); + internalCtx.privateKey = key.getPrivateKey(); + internalCtx.cert = cert.getAuxCert(); + } + + value = getInstanceVariable("@client_ca"); + if (value != null && !value.isNil()) { + if (value.respondsTo("each")) { + for (X509Cert ele : convertToX509Certs(value)) { + internalCtx.clientCa.add(ele.getAuxCert()); + } + } else { + Utils.checkKind(getRuntime(), value, "OpenSSL::X509::Certificate"); + internalCtx.clientCa.add(((X509Cert) value).getAuxCert()); + } + } + + String caFile = getCaFile(); + String caPath = getCaPath(); + if (caFile != null || caPath != null) { + try { + if (internalCtx.store.loadLocations(caFile, caPath) == 0) { + getRuntime().getWarnings().warn(ID.MISCELLANEOUS, "can't set verify locations"); + } + } catch (Exception e) { + throw newSSLError(getRuntime(), e.getMessage()); + } + } + + value = getInstanceVariable("@verify_mode"); + if (value != null && !value.isNil()) { + internalCtx.verifyMode = RubyNumeric.fix2int(value); + } else { + internalCtx.verifyMode = SSL.VERIFY_NONE; + } + value = getInstanceVariable("@verify_callback"); + if (value != null && !value.isNil()) { + internalCtx.store.setExtraData(1, value); + } + + value = getInstanceVariable("@timeout"); + if (value != null && !value.isNil()) { + internalCtx.timeout = RubyNumeric.fix2int(value); + } + + value = getInstanceVariable("@verify_depth"); + if (value != null && !value.isNil()) { + internalCtx.store.setDepth(RubyNumeric.fix2int(value)); + } + + /* TODO: should be implemented for SSLSession + val = ossl_sslctx_get_sess_id_ctx(self); + if (!NIL_P(val)){ + StringValue(val); + if (!SSL_CTX_set_session_id_context(ctx, (unsigned char *)RSTRING_PTR(val), + RSTRING_LEN(val))){ + ossl_raise(eSSLError, "SSL_CTX_set_session_id_context:"); + } + } + + if (RTEST(rb_iv_get(self, "@session_get_cb"))) { + SSL_CTX_sess_set_get_cb(ctx, ossl_sslctx_session_get_cb); + OSSL_Debug("SSL SESSION get callback added"); + } + if (RTEST(rb_iv_get(self, "@session_new_cb"))) { + SSL_CTX_sess_set_new_cb(ctx, ossl_sslctx_session_new_cb); + OSSL_Debug("SSL SESSION new callback added"); + } + if (RTEST(rb_iv_get(self, "@session_remove_cb"))) { + SSL_CTX_sess_set_remove_cb(ctx, ossl_sslctx_session_remove_cb); + OSSL_Debug("SSL SESSION remove callback added"); + } + + val = rb_iv_get(self, "@servername_cb"); + if (!NIL_P(val)) { + SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb); + OSSL_Debug("SSL TLSEXT servername callback added"); + } + */ + + try { + internalCtx.init(); + } catch(GeneralSecurityException gse) { + throw newSSLError(getRuntime(), gse.getMessage()); + } + return getRuntime().getTrue(); + } + + @JRubyMethod + public IRubyObject ciphers() { + List list = new ArrayList(); + Ruby rt = getRuntime(); + try { + String[] supported = getCipherSuites(createDummySSLEngine()); + List ciphs = CipherStrings.getMatchingCiphers(ciphers, supported); + for (CipherStrings.Def def : ciphs) { + RubyArray ele = getRuntime().newArray(4); + ele.set(0, rt.newString(def.name)); + ele.set(1, rt.newString(sslVersionString(def.algorithms))); + ele.set(2, rt.newFixnum(def.strength_bits)); + ele.set(3, rt.newFixnum(def.alg_bits)); + list.add(ele); + } + } catch (GeneralSecurityException gse) { + throw newSSLError(getRuntime(), gse.getMessage()); + } + return rt.newArray(list); + } + + @JRubyMethod(name = "ciphers=") + public IRubyObject set_ciphers(IRubyObject val) { + if (val.isNil()) { + ciphers = CipherStrings.SSL_DEFAULT_CIPHER_LIST; + } else if (val instanceof RubyArray) { + StringBuilder builder = new StringBuilder(); + String sep = ""; + for (IRubyObject obj : ((RubyArray) val).toJavaArray()) { + builder.append(sep).append(obj.toString()); + sep = ":"; + } + ciphers = builder.toString(); + } else { + ciphers = val.convertToString().toString(); + if (ciphers.equals("DEFAULT")) { + ciphers = CipherStrings.SSL_DEFAULT_CIPHER_LIST; + } + } + RubyArray ary = (RubyArray)ciphers(); + if (ary.size() == 0) { + throw newSSLError(getRuntime(), "no cipher match"); + } + return val; + } + + @JRubyMethod(name = "ssl_version=") + public IRubyObject set_ssl_version(IRubyObject val) { + RubyString str = val.convertToString(); + String given = str.toString(); + String mapped = SSL_VERSION_OSSL2JSSE.get(given); + if (mapped == null) { + throw newSSLError(getRuntime(), String.format("unknown SSL method `%s'.", given)); + } + protocol = mapped; + protocolForServer = protocolForClient = true; + if (given.endsWith("_client")) { + protocolForServer = false; + } + if (given.endsWith("_server")) { + protocolForClient = false; + } + return str; + } + + boolean isProtocolForServer() { + return protocolForServer; + } + + boolean isProtocolForClient() { + return protocolForClient; + } + + int getLastVerifyResult() { + return verifyResult; + } + + void setLastVerifyResult(int verifyResult) { + this.verifyResult = verifyResult; + } + + SSLEngine createDummySSLEngine() throws GeneralSecurityException { + javax.net.ssl.SSLContext ctx = javax.net.ssl.SSLContext.getInstance(protocol); + ctx.init(null, null, null); + return ctx.createSSLEngine(); + } + + // should keep SSLContext as a member for introducin SSLSession. later... + SSLEngine createSSLEngine(String peerHost, int peerPort) throws NoSuchAlgorithmException, KeyManagementException { + SSLEngine engine = internalCtx.getSSLContext().createSSLEngine(peerHost, peerPort); + engine.setEnabledCipherSuites(getCipherSuites(engine)); + engine.setEnabledProtocols(getEnabledProtocols(engine)); + return engine; + } + + private String[] getCipherSuites(SSLEngine engine) { + List ciphs = CipherStrings.getMatchingCiphers(ciphers, engine.getSupportedCipherSuites()); + String[] result = new String[ciphs.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = ciphs.get(i).cipherSuite; + } + return result; + } + + private String[] getEnabledProtocols(SSLEngine engine) { + List candidates = new ArrayList(); + long options = getOptions(); + if (ENABLED_PROTOCOLS.get(protocol) != null) { + for (String enabled : ENABLED_PROTOCOLS.get(protocol)) { + if (((options & SSL.OP_NO_SSLv2) != 0) && enabled.equals("SSLv2")) { + continue; + } + if (((options & SSL.OP_NO_SSLv3) != 0) && enabled.equals("SSLv3")) { + continue; + } + if (((options & SSL.OP_NO_TLSv1) != 0) && enabled.equals("TLSv1")) { + continue; + } + for (String allowed : engine.getEnabledProtocols()) { + if (allowed.equals(enabled)) { + candidates.add(allowed); + } + } + } + } + return candidates.toArray(new String[candidates.size()]); + } + + private String sslVersionString(long bits) { + StringBuilder sb = new StringBuilder(); + boolean first = true; + if ((bits & CipherStrings.SSL_SSLV3) != 0) { + if (!first) { + sb.append("/"); + } + first = false; + sb.append("TLSv1/SSLv3"); + } + if ((bits & CipherStrings.SSL_SSLV2) != 0) { + if (!first) { + sb.append("/"); + } + first = false; + sb.append("SSLv2"); + } + return sb.toString(); + } + + private PKey getCallbackKey() { + if (t_key != null) { + return t_key; + } + initFromCallback(); + return t_key; + } + + private X509Cert getCallbackCert() { + if (t_cert != null) { + return t_cert; + } + initFromCallback(); + return t_cert; + } + + private void initFromCallback() { + IRubyObject value = getInstanceVariable("@client_cert_cb"); + if (value != null && !value.isNil()) { + IRubyObject out = value.callMethod(getRuntime().getCurrentContext(), "call", this); + Utils.checkKind(getRuntime(), out, "Array"); + IRubyObject cert = (IRubyObject) ((RubyArray) out).getList().get(0); + IRubyObject key = (IRubyObject) ((RubyArray) out).getList().get(1); + Utils.checkKind(getRuntime(), cert, "OpenSSL::X509::Certificate"); + Utils.checkKind(getRuntime(), key, "OpenSSL::PKey::PKey"); + t_cert = (X509Cert) cert; + t_key = (PKey) key; + } + } + + private X509Store getCertStore() { + IRubyObject value = getInstanceVariable("@cert_store"); + if (value != null && !value.isNil() && (value instanceof X509Store)) { + Utils.checkKind(getRuntime(), value, "OpenSSL::X509::Store"); + return (X509Store) value; + } else { + return null; + } + } + + private String getCaFile() { + IRubyObject value = getInstanceVariable("@ca_file"); + if (value != null && !value.isNil()) { + return value.convertToString().toString(); + } else { + return null; + } + } + + private String getCaPath() { + IRubyObject value = getInstanceVariable("@ca_path"); + if (value != null && !value.isNil()) { + return value.convertToString().toString(); + } else { + return null; + } + } + + private long getOptions() { + IRubyObject value = getInstanceVariable("@options"); + if (value != null && !value.isNil()) { + return RubyNumeric.fix2long(value); + } else { + return 0; + } + } + + private X509Cert[] convertToX509Certs(IRubyObject value) { + final ArrayList result = new ArrayList(); + ThreadContext ctx = getRuntime().getCurrentContext(); + RuntimeHelpers.invoke(ctx, value, "each", CallBlock.newCallClosure(value, value.getMetaClass(), Arity.NO_ARGUMENTS, new BlockCallback() { + + public IRubyObject call(ThreadContext context, IRubyObject[] args, Block block) { + Utils.checkKind(getRuntime(), args[0], "OpenSSL::X509::Certificate"); + result.add((X509Cert) args[0]); + return context.getRuntime().getNil(); + } + }, ctx)); + return result.toArray(new X509Cert[0]); + } + + /** + * c: SSL_CTX + */ + private class InternalContext { + + Store store = null; + int verifyMode = SSL.VERIFY_NONE; + X509AuxCertificate cert = null; + String keyAlgorithm = null; + PrivateKey privateKey = null; + List extraChainCert = null; + List clientCa = new ArrayList(); + int timeout = 0; + String protocol = null; + boolean protocolForServer = true; + boolean protocolForClient = true; + private javax.net.ssl.SSLContext sslCtx = null; + + void setLastVerifyResultInternal(int lastVerifyResult) { + setLastVerifyResult(lastVerifyResult); + } + + javax.net.ssl.SSLContext getSSLContext() { + return sslCtx; + } + + void init() throws GeneralSecurityException { + KM km = new KM(this); + TM tm = new TM(this); + sslCtx = javax.net.ssl.SSLContext.getInstance(protocol); + if (protocolForClient) { + sslCtx.getClientSessionContext().setSessionTimeout(timeout); + } + if (protocolForServer) { + sslCtx.getServerSessionContext().setSessionTimeout(timeout); + } + sslCtx.init(new javax.net.ssl.KeyManager[]{km}, new javax.net.ssl.TrustManager[]{tm}, null); + } + + // part of ssl_verify_cert_chain + StoreContext createStoreContext(String purpose) { + if (store == null) { + return null; + } + StoreContext ctx = new StoreContext(); + if (ctx.init(store, null, null) == 0) { + return null; + } + // for verify_cb + ctx.setExtraData(1, store.getExtraData(1)); + if (purpose != null) { + ctx.setDefault(purpose); + } + ctx.param.inherit(store.param); + return ctx; + } + } + + private static class KM extends javax.net.ssl.X509ExtendedKeyManager { + + private final InternalContext ctx; + + public KM(InternalContext ctx) { + super(); + this.ctx = ctx; + } + + @Override + public String chooseEngineClientAlias(String[] keyType, java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine) { + if (ctx == null) { + return null; + } + if (ctx.privateKey == null) { + return null; + } + for (int i = 0; i < keyType.length; i++) { + if (keyType[i].equalsIgnoreCase(ctx.keyAlgorithm)) { + return keyType[i]; + } + } + return null; + } + + @Override + public String chooseEngineServerAlias(String keyType, java.security.Principal[] issuers, javax.net.ssl.SSLEngine engine) { + if (ctx == null || ctx.privateKey == null) { + return null; + } + if (keyType.equalsIgnoreCase(ctx.keyAlgorithm)) { + return keyType; + } + return null; + } + + public String chooseClientAlias(String[] keyType, java.security.Principal[] issuers, java.net.Socket socket) { + return null; + } + + public String chooseServerAlias(String keyType, java.security.Principal[] issuers, java.net.Socket socket) { + return null; + } + + // c: ssl3_output_cert_chain + public java.security.cert.X509Certificate[] getCertificateChain(String alias) { + if (ctx == null) { + return null; + } + ArrayList chain = new ArrayList(); + if (ctx.extraChainCert != null) { + chain.addAll(ctx.extraChainCert); + } else if (ctx.cert != null) { + StoreContext storeCtx = ctx.createStoreContext(null); + X509AuxCertificate x = ctx.cert; + while (true) { + chain.add(x); + if (x.getIssuerDN().equals(x.getSubjectDN())) { + break; + } + try { + Name xn = new Name(x.getIssuerX500Principal()); + X509Object[] s_obj = new X509Object[1]; + if (storeCtx.getBySubject(X509Utils.X509_LU_X509, xn, s_obj) <= 0) { + break; + } + x = ((Certificate) s_obj[0]).x509; + } catch (Exception e) { + break; + } + } + } + return chain.toArray(new java.security.cert.X509Certificate[0]); + } + + public String[] getClientAliases(String keyType, java.security.Principal[] issuers) { + return null; + } + + public java.security.PrivateKey getPrivateKey(String alias) { + if (ctx == null || ctx.privateKey == null) { + return null; + } + return ctx.privateKey; + } + + public String[] getServerAliases(String keyType, java.security.Principal[] issuers) { + return null; + } + } + + private static class TM implements javax.net.ssl.X509TrustManager { + + private InternalContext ctx; + + public TM(InternalContext ctx) { + super(); + this.ctx = ctx; + } + + public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + checkTrusted("ssl_client", chain); + } + + public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException { + checkTrusted("ssl_server", chain); + } + + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + if (ctx == null) { + return null; + } + ArrayList chain = new ArrayList(); + chain.addAll(ctx.clientCa); + return chain.toArray(new java.security.cert.X509Certificate[0]); + } + + // c: ssl_verify_cert_chain + private void checkTrusted(String purpose, X509Certificate[] chain) throws CertificateException { + if (ctx == null) { + throw new CertificateException("uninitialized trust manager"); + } + if (chain != null && chain.length > 0) { + if ((ctx.verifyMode & SSL.VERIFY_PEER) != 0) { + // verify_peer + StoreContext storeCtx = ctx.createStoreContext(purpose); + if (storeCtx == null) { + throw new CertificateException("couldn't initialize store"); + } + storeCtx.setCertificate(chain[0]); + storeCtx.setChain(chain); + verifyChain(storeCtx); + } + } else { + if ((ctx.verifyMode & SSL.VERIFY_FAIL_IF_NO_PEER_CERT) != 0) { + // fail if no peer cert + throw new CertificateException("no peer certificate"); + } + } + } + + private void verifyChain(StoreContext storeCtx) throws CertificateException { + try { + int ok = storeCtx.verifyCertificate(); + ctx.setLastVerifyResultInternal(storeCtx.error); + if (ok == 0) { + throw new CertificateException("certificate verify failed"); + } + } catch (Exception e) { + throw new CertificateException("certificate verify failed", e); + } + } + } +}// SSLContext diff --git a/src/org/jruby/ext/openssl/SSLSocket.java b/src/org/jruby/ext/openssl/SSLSocket.java new file mode 100644 index 00000000000..f8aed9b60c3 --- /dev/null +++ b/src/org/jruby/ext/openssl/SSLSocket.java @@ -0,0 +1,668 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.IOException; +import java.net.Socket; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.Selector; +import java.nio.channels.SocketChannel; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.util.Set; + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLHandshakeException; +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSession; + +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyIO; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyObjectAdapter; +import org.jruby.RubyString; +import org.jruby.RubyThread; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.X509Utils; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.Arity; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class SSLSocket extends RubyObject { + private static final long serialVersionUID = -2276327900350542644L; + + private static ObjectAllocator SSLSOCKET_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new SSLSocket(runtime, klass); + } + }; + + private static RubyObjectAdapter api = JavaEmbedUtils.newObjectAdapter(); + + public static void createSSLSocket(Ruby runtime, RubyModule mSSL) { + ThreadContext context = runtime.getCurrentContext(); + RubyClass cSSLSocket = mSSL.defineClassUnder("SSLSocket",runtime.getObject(),SSLSOCKET_ALLOCATOR); + + cSSLSocket.addReadWriteAttribute(context, "io"); + cSSLSocket.addReadWriteAttribute(context, "context"); + cSSLSocket.addReadWriteAttribute(context, "sync_close"); + cSSLSocket.defineAlias("to_io","io"); + + cSSLSocket.defineAnnotatedMethods(SSLSocket.class); + } + + public SSLSocket(Ruby runtime, RubyClass type) { + super(runtime,type); + verifyResult = X509Utils.V_OK; + } + + public static RaiseException newSSLError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::SSL::SSLError", message, false); + } + + private org.jruby.ext.openssl.SSLContext rubyCtx; + private SSLEngine engine; + private RubyIO io = null; + + private ByteBuffer peerAppData; + private ByteBuffer peerNetData; + private ByteBuffer netData; + private ByteBuffer dummy; + + private boolean initialHandshake = false; + + private SSLEngineResult.HandshakeStatus hsStatus; + private SSLEngineResult.Status status = null; + + int verifyResult; + + @JRubyMethod(name = "initialize", rest = true, frame = true) + public IRubyObject _initialize(IRubyObject[] args, Block unused) { + if (Arity.checkArgumentCount(getRuntime(), args, 1, 2) == 1) { + RubyClass sslContext = Utils.getClassFromPath(getRuntime(), "OpenSSL::SSL::SSLContext"); + rubyCtx = (org.jruby.ext.openssl.SSLContext) api.callMethod(sslContext, "new"); + } else { + rubyCtx = (org.jruby.ext.openssl.SSLContext) args[1]; + } + Utils.checkKind(getRuntime(), args[0], "IO"); + io = (RubyIO) args[0]; + api.callMethod(this, "io=", io); + // This is a bit of a hack: SSLSocket should share code with RubyBasicSocket, which always sets sync to true. + // Instead we set it here for now. + api.callMethod(io, "sync=", getRuntime().getTrue()); + api.callMethod(this, "context=", rubyCtx); + api.callMethod(this, "sync_close=", getRuntime().getFalse()); + rubyCtx.setup(); + return api.callSuper(this, args); + } + + private void ossl_ssl_setup() throws NoSuchAlgorithmException, KeyManagementException, IOException { + if(null == engine) { + Socket socket = getSocketChannel().socket(); + String peerHost = socket.getInetAddress().getHostName(); + int peerPort = socket.getPort(); + engine = rubyCtx.createSSLEngine(peerHost, peerPort); + SSLSession session = engine.getSession(); + peerNetData = ByteBuffer.allocate(session.getPacketBufferSize()); + peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize()); + netData = ByteBuffer.allocate(session.getPacketBufferSize()); + peerNetData.limit(0); + peerAppData.limit(0); + netData.limit(0); + dummy = ByteBuffer.allocate(0); + } + } + + @JRubyMethod + public IRubyObject connect(ThreadContext context) { + Ruby runtime = context.getRuntime(); + if (!rubyCtx.isProtocolForClient()) { + throw newSSLError(runtime, "called a function you should not call"); + } + try { + ossl_ssl_setup(); + engine.setUseClientMode(true); + engine.beginHandshake(); + hsStatus = engine.getHandshakeStatus(); + initialHandshake = true; + doHandshake(); + } catch(SSLHandshakeException e) { + // unlike server side, client should close outbound channel even if + // we have remaining data to be sent. + forceClose(); + Throwable v = e; + while(v.getCause() != null && (v instanceof SSLHandshakeException)) { + v = v.getCause(); + } + throw SSL.newSSLError(runtime, v); + } catch (NoSuchAlgorithmException ex) { + forceClose(); + throw SSL.newSSLError(runtime, ex); + } catch (KeyManagementException ex) { + forceClose(); + throw SSL.newSSLError(runtime, ex); + } catch (IOException ex) { + forceClose(); + throw SSL.newSSLError(runtime, ex); + } + return this; + } + + @JRubyMethod + public IRubyObject accept(ThreadContext context) { + Ruby runtime = context.getRuntime(); + if (!rubyCtx.isProtocolForServer()) { + throw newSSLError(runtime, "called a function you should not call"); + } + try { + int vfy = 0; + ossl_ssl_setup(); + engine.setUseClientMode(false); + if(!rubyCtx.isNil() && !rubyCtx.callMethod(context,"verify_mode").isNil()) { + vfy = RubyNumeric.fix2int(rubyCtx.callMethod(context,"verify_mode")); + if(vfy == 0) { //VERIFY_NONE + engine.setNeedClientAuth(false); + engine.setWantClientAuth(false); + } + if((vfy & 1) != 0) { //VERIFY_PEER + engine.setWantClientAuth(true); + } + if((vfy & 2) != 0) { //VERIFY_FAIL_IF_NO_PEER_CERT + engine.setNeedClientAuth(true); + } + } + engine.beginHandshake(); + hsStatus = engine.getHandshakeStatus(); + initialHandshake = true; + doHandshake(); + } catch(SSLHandshakeException e) { + throw SSL.newSSLError(runtime, e); + } catch (NoSuchAlgorithmException ex) { + throw SSL.newSSLError(runtime, ex); + } catch (KeyManagementException ex) { + throw SSL.newSSLError(runtime, ex); + } catch (IOException ex) { + throw SSL.newSSLError(runtime, ex); + } + return this; + } + + @JRubyMethod + public IRubyObject verify_result() { + if (engine == null) { + getRuntime().getWarnings().warn("SSL session is not started yet."); + return getRuntime().getNil(); + } + return getRuntime().newFixnum(verifyResult); + } + + // This select impl is a copy of RubyThread.select, then blockingLock is + // removed. This impl just set + // SelectableChannel.configureBlocking(false) permanently instead of setting + // temporarily. SSLSocket requires wrapping IO to be selectable so it should + // be OK to set configureBlocking(false) permanently. + private void waitSelect(int operations) throws IOException { + if (!(io.getChannel() instanceof SelectableChannel)) { + return; + } + Ruby runtime = getRuntime(); + RubyThread thread = runtime.getCurrentContext().getThread(); + + SelectableChannel selectable = (SelectableChannel)io.getChannel(); + selectable.configureBlocking(false); + SelectionKey key = null; + Selector selector = null; + try { + io.addBlockingThread(thread); + selector = runtime.getSelectorPool().get(); + + key = selectable.register(selector, operations); + + thread.beforeBlockingCall(); + int result = selector.select(); + + // check for thread events, in case we've been woken up to die + thread.pollThreadEvents(); + + if (result == 1) { + Set keySet = selector.selectedKeys(); + + if (keySet.iterator().next() == key) { + return; + } + } + } catch (IOException ioe) { + throw runtime.newRuntimeError("Error with selector: " + ioe.getMessage()); + } finally { + // Note: I don't like ignoring these exceptions, but it's + // unclear how likely they are to happen or what damage we + // might do by ignoring them. Note that the pieces are separate + // so that we can ensure one failing does not affect the others + // running. + + // clean up the key in the selector + try { + if (key != null) key.cancel(); + if (selector != null) selector.selectNow(); + } catch (Exception e) { + // ignore + } + + // shut down and null out the selector + try { + if (selector != null) { + runtime.getSelectorPool().put(selector); + } + } catch (Exception e) { + // ignore + } + + // remove this thread as a blocker against the given IO + io.removeBlockingThread(thread); + + // clear thread state from blocking call + thread.afterBlockingCall(); + } + } + + private void doHandshake() throws IOException { + while (true) { + SSLEngineResult res; + waitSelect(SelectionKey.OP_READ | SelectionKey.OP_WRITE); + if(hsStatus == SSLEngineResult.HandshakeStatus.FINISHED) { + if (initialHandshake) { + finishInitialHandshake(); + } + return; + } else if(hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK) { + doTasks(); + } else if(hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP) { + if(readAndUnwrap() == -1 && hsStatus != SSLEngineResult.HandshakeStatus.FINISHED) { + throw new SSLHandshakeException("Socket closed"); + } + // during initialHandshake, calling readAndUnwrap that results UNDERFLOW + // does not mean writable. we explicitly wait for readable channel to avoid + // busy loop. + if (initialHandshake && status == SSLEngineResult.Status.BUFFER_UNDERFLOW) { + waitSelect(SelectionKey.OP_READ); + } + } else if(hsStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP) { + if (netData.hasRemaining()) { + while(flushData()) {} + } + netData.clear(); + res = engine.wrap(dummy, netData); + hsStatus = res.getHandshakeStatus(); + netData.flip(); + flushData(); + } else { + assert false : "doHandshake() should never reach the NOT_HANDSHAKING state"; + return; + } + } + } + + private void doTasks() { + Runnable task; + while ((task = engine.getDelegatedTask()) != null) { + task.run(); + } + hsStatus = engine.getHandshakeStatus(); + verifyResult = rubyCtx.getLastVerifyResult(); + } + + private boolean flushData() throws IOException { + try { + writeToChannel(netData); + } catch (IOException ioe) { + netData.position(netData.limit()); + throw ioe; + } + if (netData.hasRemaining()) { + return false; + } else { + return true; + } + } + + private int writeToChannel(ByteBuffer buffer) throws IOException { + int totalWritten = 0; + while (buffer.hasRemaining()) { + totalWritten += getSocketChannel().write(buffer); + } + return totalWritten; + } + + private void finishInitialHandshake() { + initialHandshake = false; + } + + public int write(ByteBuffer src) throws SSLException, IOException { + if(initialHandshake) { + throw new IOException("Writing not possible during handshake"); + } + if(netData.hasRemaining()) { + // TODO; remove + // This protect should be propagated from + // http://www.javadocexamples.com/java_source/ssl/SSLChannel.java.html + // to avoid IO selecting problem under MT. + // We have different model of selecting so it's safe to be removed I think. + throw new IOException("Another thread may be writing"); + } + netData.clear(); + SSLEngineResult res = engine.wrap(src, netData); + netData.flip(); + flushData(); + return res.bytesConsumed(); + } + + public int read(ByteBuffer dst) throws IOException { + if(initialHandshake) { + return 0; + } + if (engine.isInboundDone()) { + return -1; + } + if (!peerAppData.hasRemaining()) { + int appBytesProduced = readAndUnwrap(); + if (appBytesProduced == -1 || appBytesProduced == 0) { + return appBytesProduced; + } + } + int limit = Math.min(peerAppData.remaining(), dst.remaining()); + peerAppData.get(dst.array(), dst.arrayOffset(), limit); + dst.position(dst.arrayOffset() + limit); + return limit; + } + + private int readAndUnwrap() throws IOException { + int bytesRead = getSocketChannel().read(peerNetData); + if (bytesRead == -1) { + if (!peerNetData.hasRemaining() || (status == SSLEngineResult.Status.BUFFER_UNDERFLOW)) { + closeInbound(); + return -1; + } + // inbound channel has been already closed but closeInbound() must + // be defered till the last engine.unwrap() call. + // peerNetData could not be empty. + } + peerAppData.clear(); + peerNetData.flip(); + SSLEngineResult res; + do { + res = engine.unwrap(peerNetData, peerAppData); + } while (res.getStatus() == SSLEngineResult.Status.OK && + res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP && + res.bytesProduced() == 0); + if(res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED) { + finishInitialHandshake(); + } + if(peerAppData.position() == 0 && + res.getStatus() == SSLEngineResult.Status.OK && + peerNetData.hasRemaining()) { + res = engine.unwrap(peerNetData, peerAppData); + } + status = res.getStatus(); + hsStatus = res.getHandshakeStatus(); + if (bytesRead == -1 && !peerNetData.hasRemaining()) { + // now it's safe to call closeInbound(). + closeInbound(); + } + if(status == SSLEngineResult.Status.CLOSED) { + doShutdown(); + return -1; + } + peerNetData.compact(); + peerAppData.flip(); + if(!initialHandshake && (hsStatus == SSLEngineResult.HandshakeStatus.NEED_TASK || + hsStatus == SSLEngineResult.HandshakeStatus.NEED_WRAP || + hsStatus == SSLEngineResult.HandshakeStatus.FINISHED)) { + doHandshake(); + } + return peerAppData.remaining(); + } + + private void closeInbound() { + try { + engine.closeInbound(); + } catch (SSLException ssle) { + // ignore any error on close. possibly an error like this; + // Inbound closed before receiving peer's close_notify: possible truncation attack? + } + } + + private void doShutdown() throws IOException { + if (engine.isOutboundDone()) { + return; + } + netData.clear(); + try { + engine.wrap(dummy, netData); + } catch(Exception e1) { + return; + } + netData.flip(); + flushData(); + } + + @JRubyMethod(rest = true, required = 1, optional = 1) + public IRubyObject sysread(ThreadContext context, IRubyObject[] args) { + Ruby runtime = context.getRuntime(); + int len = RubyNumeric.fix2int(args[0]); + RubyString str = null; + + if (args.length == 2 && !args[1].isNil()) { + str = args[1].convertToString(); + } else { + str = getRuntime().newString(""); + } + if(len == 0) { + str.clear(); + return str; + } + if (len < 0) { + throw runtime.newArgumentError("negative string size (or size too big)"); + } + + try { + // So we need to make sure to only block when there is no data left to process + if(engine == null || !(peerAppData.hasRemaining() || peerNetData.position() > 0)) { + waitSelect(SelectionKey.OP_READ); + } + + ByteBuffer dst = ByteBuffer.allocate(len); + int rr = -1; + // ensure >0 bytes read; sysread is blocking read. + while (rr <= 0) { + if (engine == null) { + rr = getSocketChannel().read(dst); + } else { + rr = read(dst); + } + if (rr == -1) { + throw getRuntime().newEOFError(); + } + } + byte[] bss = new byte[rr]; + dst.position(dst.position() - rr); + dst.get(bss); + str.setValue(new ByteList(bss)); + return str; + } catch (IOException ioe) { + throw getRuntime().newIOError(ioe.getMessage()); + } + } + + @JRubyMethod + public IRubyObject syswrite(ThreadContext context, IRubyObject arg) { + Ruby runtime = context.getRuntime(); + try { + checkClosed(); + waitSelect(SelectionKey.OP_WRITE); + byte[] bls = arg.convertToString().getBytes(); + ByteBuffer b1 = ByteBuffer.wrap(bls); + int written; + if(engine == null) { + written = writeToChannel(b1); + } else { + written = write(b1); + } + ((RubyIO)api.callMethod(this,"io")).flush(); + + return getRuntime().newFixnum(written); + } catch (IOException ioe) { + throw runtime.newIOError(ioe.getMessage()); + } + } + + private void checkClosed() { + if (!getSocketChannel().isOpen()) { + throw getRuntime().newIOError("closed stream"); + } + } + + // do shutdown even if we have remaining data to be sent. + // call this when you get an exception from client side. + private void forceClose() { + close(true); + } + + private void close(boolean force) { + if (engine == null) throw getRuntime().newEOFError(); + engine.closeOutbound(); + if (!force && netData.hasRemaining()) { + return; + } else { + try { + doShutdown(); + } catch (IOException ex) { + // ignore? + } + } + } + + @JRubyMethod + public IRubyObject sysclose() { + // no need to try shutdown when it's a server + close(rubyCtx.isProtocolForClient()); + ThreadContext tc = getRuntime().getCurrentContext(); + if(callMethod(tc,"sync_close").isTrue()) { + callMethod(tc,"io").callMethod(tc,"close"); + } + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject cert() { + try { + Certificate[] cert = engine.getSession().getLocalCertificates(); + if (cert.length > 0) { + return X509Cert.wrap(getRuntime(), cert[0]); + } + } catch (CertificateEncodingException ex) { + throw X509Cert.newCertificateError(getRuntime(), ex); + } + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject peer_cert() { + try { + Certificate[] cert = engine.getSession().getPeerCertificates(); + if (cert.length > 0) { + return X509Cert.wrap(getRuntime(), cert[0]); + } + } catch (CertificateEncodingException ex) { + throw X509Cert.newCertificateError(getRuntime(), ex); + } catch (SSLPeerUnverifiedException ex) { + if (getRuntime().isVerbose()) { + getRuntime().getWarnings().warning(String.format("%s: %s", ex.getClass().getName(), ex.getMessage())); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject peer_cert_chain() { + try { + javax.security.cert.Certificate[] certs = engine.getSession().getPeerCertificateChain(); + + RubyArray arr = getRuntime().newArray(certs.length); + for(int i = 0 ; i < certs.length; i++ ) { + arr.add(X509Cert.wrap(getRuntime(), certs[i])); + } + return arr; + } catch (javax.security.cert.CertificateEncodingException e) { + throw X509Cert.newCertificateError(getRuntime(), e); + } catch (SSLPeerUnverifiedException ex) { + if (getRuntime().isVerbose()) { + getRuntime().getWarnings().warning(String.format("%s: %s", ex.getClass().getName(), ex.getMessage())); + } + } + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject cipher() { + return getRuntime().newString(engine.getSession().getCipherSuite()); + } + + @JRubyMethod + public IRubyObject state() { + System.err.println("WARNING: unimplemented method called: SSLSocket#state"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject pending() { + System.err.println("WARNING: unimplemented method called: SSLSocket#pending"); + return getRuntime().getNil(); + } + + private SocketChannel getSocketChannel() { + return (SocketChannel) io.getChannel(); + } +}// SSLSocket diff --git a/src/org/jruby/ext/openssl/SimpleSecretKey.java b/src/org/jruby/ext/openssl/SimpleSecretKey.java new file mode 100644 index 00000000000..79ef9dd286e --- /dev/null +++ b/src/org/jruby/ext/openssl/SimpleSecretKey.java @@ -0,0 +1,53 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import javax.crypto.SecretKey; + +/** + * @author Ola Bini + */ +public class SimpleSecretKey implements SecretKey { + private static final long serialVersionUID = 1L; + + private final String algorithm; + private final byte[] value; + public SimpleSecretKey(String algorithm, byte[] value) { + this.algorithm = algorithm; + this.value = value; + } + public String getAlgorithm() { + return algorithm; + } + public byte[] getEncoded() { + return value; + } + public String getFormat() { + return "RAW"; + } +}// SimpleSecretKey diff --git a/src/org/jruby/ext/openssl/Utils.java b/src/org/jruby/ext/openssl/Utils.java new file mode 100644 index 00000000000..d05ece95b53 --- /dev/null +++ b/src/org/jruby/ext/openssl/Utils.java @@ -0,0 +1,98 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.exceptions.RaiseException; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class Utils { + private Utils() {} + public static String toHex(byte[] val) { + StringBuffer out = new StringBuffer(); + for(int i=0,j=val.length;i + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyModule; + +/** + * @author Ola Bini + */ +public class X509 { + public static void createX509(Ruby runtime, RubyModule ossl) { + RubyModule mX509 = ossl.defineModuleUnder("X509"); + + X509Name.createX509Name(runtime,mX509); + X509Cert.createX509Cert(runtime,mX509); + X509Extensions.createX509Ext(runtime,mX509); + X509CRL.createX509CRL(runtime,mX509); + X509Revoked.createX509Revoked(runtime,mX509); + X509Store.createX509Store(runtime,mX509); + Request.createRequest(runtime,mX509); + Attribute.createAttribute(runtime,mX509); + + mX509.setConstant("V_OK",runtime.newFixnum(0)); + mX509.setConstant("V_ERR_UNABLE_TO_GET_ISSUER_CERT",runtime.newFixnum(2)); + mX509.setConstant("V_ERR_UNABLE_TO_GET_CRL",runtime.newFixnum(3)); + mX509.setConstant("V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE",runtime.newFixnum(4)); + mX509.setConstant("V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE",runtime.newFixnum(5)); + mX509.setConstant("V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY",runtime.newFixnum(6)); + mX509.setConstant("V_ERR_CERT_SIGNATURE_FAILURE",runtime.newFixnum(7)); + mX509.setConstant("V_ERR_CRL_SIGNATURE_FAILURE",runtime.newFixnum(8)); + mX509.setConstant("V_ERR_CERT_NOT_YET_VALID",runtime.newFixnum(9)); + mX509.setConstant("V_ERR_CERT_HAS_EXPIRED",runtime.newFixnum(10)); + mX509.setConstant("V_ERR_CRL_NOT_YET_VALID",runtime.newFixnum(11)); + mX509.setConstant("V_ERR_CRL_HAS_EXPIRED",runtime.newFixnum(12)); + mX509.setConstant("V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD",runtime.newFixnum(13)); + mX509.setConstant("V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD",runtime.newFixnum(14)); + mX509.setConstant("V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD",runtime.newFixnum(15)); + mX509.setConstant("V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD",runtime.newFixnum(16)); + mX509.setConstant("V_ERR_OUT_OF_MEM",runtime.newFixnum(17)); + mX509.setConstant("V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT",runtime.newFixnum(18)); + mX509.setConstant("V_ERR_SELF_SIGNED_CERT_IN_CHAIN",runtime.newFixnum(19)); + mX509.setConstant("V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY",runtime.newFixnum(20)); + mX509.setConstant("V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE",runtime.newFixnum(21)); + mX509.setConstant("V_ERR_CERT_CHAIN_TOO_LONG",runtime.newFixnum(22)); + mX509.setConstant("V_ERR_CERT_REVOKED",runtime.newFixnum(23)); + mX509.setConstant("V_ERR_INVALID_CA",runtime.newFixnum(24)); + mX509.setConstant("V_ERR_PATH_LENGTH_EXCEEDED",runtime.newFixnum(25)); + mX509.setConstant("V_ERR_INVALID_PURPOSE",runtime.newFixnum(26)); + mX509.setConstant("V_ERR_CERT_UNTRUSTED",runtime.newFixnum(27)); + mX509.setConstant("V_ERR_CERT_REJECTED",runtime.newFixnum(28)); + mX509.setConstant("V_ERR_SUBJECT_ISSUER_MISMATCH",runtime.newFixnum(29)); + mX509.setConstant("V_ERR_AKID_SKID_MISMATCH",runtime.newFixnum(30)); + mX509.setConstant("V_ERR_AKID_ISSUER_SERIAL_MISMATCH",runtime.newFixnum(31)); + mX509.setConstant("V_ERR_KEYUSAGE_NO_CERTSIGN",runtime.newFixnum(32)); + mX509.setConstant("V_ERR_APPLICATION_VERIFICATION",runtime.newFixnum(50)); + mX509.setConstant("V_FLAG_CRL_CHECK",runtime.newFixnum(4)); + mX509.setConstant("V_FLAG_CRL_CHECK_ALL",runtime.newFixnum(8)); + mX509.setConstant("PURPOSE_SSL_CLIENT",runtime.newFixnum(1)); + mX509.setConstant("PURPOSE_SSL_SERVER",runtime.newFixnum(2)); + mX509.setConstant("PURPOSE_NS_SSL_SERVER",runtime.newFixnum(3)); + mX509.setConstant("PURPOSE_SMIME_SIGN",runtime.newFixnum(4)); + mX509.setConstant("PURPOSE_SMIME_ENCRYPT",runtime.newFixnum(5)); + mX509.setConstant("PURPOSE_CRL_SIGN",runtime.newFixnum(6)); + mX509.setConstant("PURPOSE_ANY",runtime.newFixnum(7)); + mX509.setConstant("PURPOSE_OCSP_HELPER",runtime.newFixnum(8)); + mX509.setConstant("TRUST_COMPAT",runtime.newFixnum(1)); + mX509.setConstant("TRUST_SSL_CLIENT",runtime.newFixnum(2)); + mX509.setConstant("TRUST_SSL_SERVER",runtime.newFixnum(3)); + mX509.setConstant("TRUST_EMAIL",runtime.newFixnum(4)); + mX509.setConstant("TRUST_OBJECT_SIGN",runtime.newFixnum(5)); + mX509.setConstant("TRUST_OCSP_SIGN",runtime.newFixnum(6)); + mX509.setConstant("TRUST_OCSP_REQUEST",runtime.newFixnum(7)); + + // These should eventually point to correct things. + mX509.setConstant("DEFAULT_CERT_AREA", runtime.newString("/usr/lib/ssl")); + mX509.setConstant("DEFAULT_CERT_DIR", runtime.newString("/usr/lib/ssl/certs")); + mX509.setConstant("DEFAULT_CERT_FILE", runtime.newString("/usr/lib/ssl/cert.pem")); + mX509.setConstant("DEFAULT_CERT_DIR_ENV", runtime.newString("SSL_CERT_DIR")); + mX509.setConstant("DEFAULT_CERT_FILE_ENV", runtime.newString("SSL_CERT_FILE")); + mX509.setConstant("DEFAULT_PRIVATE_DIR", runtime.newString("/usr/lib/ssl/private")); + } +}// X509 diff --git a/src/org/jruby/ext/openssl/X509CRL.java b/src/org/jruby/ext/openssl/X509CRL.java new file mode 100644 index 00000000000..f2b9fadf2c5 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509CRL.java @@ -0,0 +1,462 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.cert.CRLException; +import java.security.cert.CertificateFactory; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DERBoolean; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.x509.X509V2CRLGenerator; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.RubyTime; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class X509CRL extends RubyObject { + private static final long serialVersionUID = -2463300006179688577L; + + private static ObjectAllocator X509CRL_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509CRL(runtime, klass); + } + }; + + public static void createX509CRL(Ruby runtime, RubyModule mX509) { + RubyClass cX509CRL = mX509.defineClassUnder("CRL",runtime.getObject(),X509CRL_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("CRLError",openSSLError,openSSLError.getAllocator()); + + cX509CRL.defineAnnotatedMethods(X509CRL.class); + } + + private IRubyObject version; + private IRubyObject issuer; + private IRubyObject last_update; + private IRubyObject next_update; + private IRubyObject revoked; + private List extensions; + + private IRubyObject sig_alg; + + private boolean changed = true; + + private X509V2CRLGenerator generator = new X509V2CRLGenerator(); + private java.security.cert.X509CRL crl; + + private DERObject crl_v; + + java.security.cert.X509CRL getCRL() { + return crl; + } + + public X509CRL(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + @JRubyMethod(name="initialize", rest=true, frame=true) + public IRubyObject _initialize(IRubyObject[] args, Block block) { + extensions = new ArrayList(); + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,0,1) == 0) { + version = getRuntime().getNil(); + issuer = getRuntime().getNil(); + last_update = getRuntime().getNil(); + next_update = getRuntime().getNil(); + revoked = getRuntime().newArray(); + return this; + } + + ByteArrayInputStream bis = new ByteArrayInputStream(args[0].convertToString().getBytes()); + try { + // SunJCE throws java.security.cert.CRLException: Invalid encoding of AuthorityKeyIdentifierExtension. + // FIXME: use BC for now. + CertificateFactory cf = OpenSSLReal.getX509CertificateFactoryBC(); + crl = (java.security.cert.X509CRL) cf.generateCRL(bis); + } catch (GeneralSecurityException gse) { + throw newX509CRLError(getRuntime(), gse.getMessage()); + } + + byte[] crl_bytes = OpenSSLImpl.readX509PEM(args[0]); + try { + crl_v = new ASN1InputStream(new ByteArrayInputStream(crl_bytes)).readObject(); + } catch (IOException ioe) { + throw newX509CRLError(getRuntime(), ioe.getMessage()); + } + + DEREncodable v0 = ((DERSequence)(((DERSequence)crl_v).getObjectAt(0))).getObjectAt(0); + if(v0 instanceof DERInteger) { + set_version(getRuntime().newFixnum(((DERInteger)v0).getValue().intValue())); + } else { + set_version(getRuntime().newFixnum(2)); + } + set_last_update(RubyTime.newTime(getRuntime(),crl.getThisUpdate().getTime())); + set_next_update(RubyTime.newTime(getRuntime(),crl.getNextUpdate().getTime())); + RubyString name = RubyString.newString(getRuntime(), crl.getIssuerX500Principal().getEncoded()); + set_issuer(Utils.newRubyInstance(getRuntime(), "OpenSSL::X509::Name", name)); + + revoked = getRuntime().newArray(); + + DERSequence seqa = (DERSequence)((DERSequence)crl_v).getObjectAt(0); + DERObject maybe_ext = (DERObject)seqa.getObjectAt(seqa.size()-1); + if(maybe_ext instanceof DERTaggedObject && ((DERTaggedObject)maybe_ext).getTagNo() == 0) { + DERSequence exts = (DERSequence)((DERTaggedObject)maybe_ext).getObject(); + for(int i=0;i0) { + sbe.append(IND8).append("CRL extensions\n"); + for(Iterator iter = extensions.iterator();iter.hasNext();) { + X509Extensions.Extension ext = (X509Extensions.Extension)iter.next(); + DERObjectIdentifier oiden = ext.getRealOid(); + sbe.append(IND12).append(ASN1.o2a(getRuntime(),oiden)).append(": "); + if(ext.getRealCritical()) { + sbe.append("critical"); + } + sbe.append("\n"); + sbe.append(IND16).append(ext.value()).append("\n"); + } + } + /* + 114 rev = X509_CRL_get_REVOKED(x); + 115 + 116 if(sk_X509_REVOKED_num(rev) > 0) + 117 BIO_printf(out, "Revoked Certificates:\n"); + 118 else BIO_printf(out, "No Revoked Certificates.\n"); + 119 + 120 for(i = 0; i < sk_X509_REVOKED_num(rev); i++) { + 121 r = sk_X509_REVOKED_value(rev, i); + 122 BIO_printf(out," Serial Number: "); + 123 i2a_ASN1_INTEGER(out,r->serialNumber); + 124 BIO_printf(out,"\n Revocation Date: "); + 125 ASN1_TIME_print(out,r->revocationDate); + 126 BIO_printf(out,"\n"); + 127 X509V3_extensions_print(out, "CRL entry extensions", + 128 r->extensions, 0, 8); + 129 } + 130 X509_signature_print(out, x->sig_alg, x->signature); + 131 + */ + return getRuntime().newString(sbe.toString()); + } + + @JRubyMethod + public IRubyObject version() { + return this.version; + } + + @JRubyMethod(name="version=") + public IRubyObject set_version(IRubyObject val) { + if(!val.equals(this.version)) { + changed = true; + } + this.version = val; + return val; + } + + @JRubyMethod + public IRubyObject signature_algorithm() { + return sig_alg; + } + + @JRubyMethod + public IRubyObject issuer() { + return this.issuer; + } + + @JRubyMethod(name="issuer=") + public IRubyObject set_issuer(IRubyObject val) { + if(!val.equals(this.issuer)) { + changed = true; + } + this.issuer = val; + generator.setIssuerDN(((X509Name)issuer).getRealName()); + return val; + } + + @JRubyMethod + public IRubyObject last_update() { + return this.last_update; + } + + @JRubyMethod(name="last_update=") + public IRubyObject set_last_update(IRubyObject val) { + changed = true; + last_update = val.callMethod(getRuntime().getCurrentContext(),"getutc"); + ((RubyTime)last_update).setMicroseconds(0); + generator.setThisUpdate(((RubyTime)last_update).getJavaDate()); + this.last_update = val; + return val; + } + + @JRubyMethod + public IRubyObject next_update() { + return this.next_update; + } + + @JRubyMethod(name="next_update=") + public IRubyObject set_next_update(IRubyObject val) { + changed = true; + next_update = val.callMethod(getRuntime().getCurrentContext(),"getutc"); + ((RubyTime)next_update).setMicroseconds(0); + generator.setNextUpdate(((RubyTime)next_update).getJavaDate()); + this.next_update = val; + return val; + } + + @JRubyMethod + public IRubyObject revoked() { + return this.revoked; + } + + @JRubyMethod(name="revoked=") + public IRubyObject set_revoked(IRubyObject val) { + changed = true; + this.revoked = val; + return val; + } + + @JRubyMethod + public IRubyObject add_revoked(IRubyObject val) { + changed = true; + this.revoked.callMethod(getRuntime().getCurrentContext(),"<<",val); + return val; + } + + @JRubyMethod + public IRubyObject extensions() { + return getRuntime().newArray(this.extensions); + } + + @SuppressWarnings("unchecked") + @JRubyMethod(name="extensions=") + public IRubyObject set_extensions(IRubyObject val) { + this.extensions = ((RubyArray)val).getList(); + return val; + } + + @JRubyMethod + public IRubyObject add_extension(IRubyObject val) { + this.extensions.add(val); + return val; + } + + @JRubyMethod + public IRubyObject sign(final IRubyObject key, IRubyObject digest) { + //System.err.println("WARNING: unimplemented method called: CRL#sign"); + // Have to obey some artificial constraints of the OpenSSL implementation. Stupid. + String keyAlg = ((PKey)key).getAlgorithm(); + String digAlg = ((Digest)digest).getShortAlgorithm(); + + if(("DSA".equalsIgnoreCase(keyAlg) && "MD5".equalsIgnoreCase(digAlg)) || + ("RSA".equalsIgnoreCase(keyAlg) && "DSS1".equals(((Digest)digest).name().toString())) || + ("DSA".equalsIgnoreCase(keyAlg) && "SHA1".equals(((Digest)digest).name().toString()))) { + throw newX509CRLError(getRuntime(), null); + } + + sig_alg = getRuntime().newString(digAlg); + generator.setSignatureAlgorithm(digAlg + "WITH" + keyAlg); + + for (IRubyObject obj : ((RubyArray)revoked).toJavaArray()) { + X509Revoked rev = (X509Revoked)obj; // TODO: can throw CCE + BigInteger serial = new BigInteger(rev.callMethod(getRuntime().getCurrentContext(),"serial").toString()); + IRubyObject t1 = rev.callMethod(getRuntime().getCurrentContext(),"time").callMethod(getRuntime().getCurrentContext(),"getutc"); + ((RubyTime)t1).setMicroseconds(0); + // Extensions ignored, for now + generator.addCRLEntry(serial,((RubyTime)t1).getJavaDate(),new org.bouncycastle.asn1.x509.X509Extensions(new Hashtable())); + } + + try { + for (Iterator iter = extensions.iterator(); iter.hasNext();) { + X509Extensions.Extension ag = (X509Extensions.Extension) iter.next(); + generator.addExtension(ag.getRealOid(), ag.getRealCritical(), ag.getRealValueBytes()); + } + } catch (IOException ioe) { + throw newX509CRLError(getRuntime(), ioe.getMessage()); + } + try { + // X509V2CRLGenerator(generator) depends BC. + OpenSSLReal.doWithBCProvider(new OpenSSLReal.Runnable() { + + public void run() throws GeneralSecurityException { + crl = generator.generate(((PKey) key).getPrivateKey(), "BC"); + } + }); + } catch (GeneralSecurityException gse) { + throw newX509CRLError(getRuntime(), gse.getMessage()); + } + + try { + crl_v = new ASN1InputStream(new ByteArrayInputStream(crl.getEncoded())).readObject(); + } catch (CRLException crle) { + throw newX509CRLError(getRuntime(), crle.getMessage()); + } catch (IOException ioe) { + throw newX509CRLError(getRuntime(), ioe.getMessage()); + } + DERSequence v1 = (DERSequence)(((DERSequence)crl_v).getObjectAt(0)); + ASN1EncodableVector build1 = new ASN1EncodableVector(); + int copyIndex = 0; + if(v1.getObjectAt(0) instanceof DERInteger) { + copyIndex++; + } + build1.add(new DERInteger(new java.math.BigInteger(version.toString()))); + while(copyIndex < v1.size()) { + build1.add(v1.getObjectAt(copyIndex++)); + } + ASN1EncodableVector build2 = new ASN1EncodableVector(); + build2.add(new DERSequence(build1)); + build2.add(((DERSequence)crl_v).getObjectAt(1)); + build2.add(((DERSequence)crl_v).getObjectAt(2)); + crl_v = new DERSequence(build2); + changed = false; + return this; + } + + @JRubyMethod + public IRubyObject verify(final IRubyObject key) { + if (changed) { + return getRuntime().getFalse(); + } + try { + crl.verify(((PKey) key).getPublicKey()); + return getRuntime().getTrue(); + } catch (Exception ignored) { + return getRuntime().getFalse(); + } + + } + + private static RaiseException newX509CRLError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::X509::CRLError", message); + } +}// X509CRL diff --git a/src/org/jruby/ext/openssl/X509Cert.java b/src/org/jruby/ext/openssl/X509Cert.java new file mode 100644 index 00000000000..40ec6bfd044 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509Cert.java @@ -0,0 +1,535 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.bouncycastle.x509.X509V3CertificateGenerator; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.RubyTime; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.impl.ASN1Registry; +import org.jruby.ext.openssl.x509store.PEMInputOutput; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class X509Cert extends RubyObject { + private static final long serialVersionUID = 5626619026058595493L; + + private static ObjectAllocator X509CERT_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509Cert(runtime, klass); + } + }; + + public static void createX509Cert(Ruby runtime, RubyModule mX509) { + RubyClass cX509Cert = mX509.defineClassUnder("Certificate",runtime.getObject(),X509CERT_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("CertificateError",openSSLError,openSSLError.getAllocator()); + + cX509Cert.defineAnnotatedMethods(X509Cert.class); + } + + public X509Cert(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private IRubyObject serial; + private IRubyObject not_before; + private IRubyObject not_after; + private IRubyObject issuer; + private IRubyObject subject; + private IRubyObject public_key; + + private IRubyObject sig_alg; + private IRubyObject version; + + private List extensions; + + private boolean changed = true; + + private X509V3CertificateGenerator generator = new X509V3CertificateGenerator(); + private X509Certificate cert; + private String public_key_algorithm; + private byte[] public_key_encoded; + + X509AuxCertificate getAuxCert() { + if(null == cert) { + return null; + } + if(cert instanceof X509AuxCertificate) { + return (X509AuxCertificate)cert; + } + return new X509AuxCertificate(cert); + } + + public static IRubyObject wrap(Ruby runtime, Certificate c) throws CertificateEncodingException { + RubyClass cr = Utils.getClassFromPath(runtime, "OpenSSL::X509::Certificate"); + return cr.callMethod(runtime.getCurrentContext(), "new", RubyString.newString(runtime, c.getEncoded())); + } + + // this is the javax.security counterpart of the previous wrap method + public static IRubyObject wrap(Ruby runtime, javax.security.cert.Certificate c) throws javax.security.cert.CertificateEncodingException { + RubyClass cr = Utils.getClassFromPath(runtime, "OpenSSL::X509::Certificate"); + return cr.callMethod(runtime.getCurrentContext(), "new", RubyString.newString(runtime, c.getEncoded())); + } + + @JRubyMethod(name="initialize", optional = 1, frame=true) + public IRubyObject initialize(ThreadContext context, IRubyObject[] args, Block unusedBlock) { + Ruby runtime = context.getRuntime(); + extensions = new ArrayList(); + if(args.length == 0) { + return this; + } + byte[] bytes = OpenSSLImpl.readX509PEM(args[0]); + ByteArrayInputStream bis = new ByteArrayInputStream(bytes); + + CertificateFactory cf; + + RubyModule ossl = runtime.getModule("OpenSSL"); + RubyModule x509 = (RubyModule)ossl.getConstant("X509"); + IRubyObject x509Name = x509.getConstant("Name"); + + try { + cf = CertificateFactory.getInstance("X.509"); + cert = (X509Certificate)cf.generateCertificate(bis); + } catch (CertificateException ex) { + throw newCertificateError(runtime, ex); + } + if (cert == null) { + throw newCertificateError(runtime, (String) null); + } + + set_serial(RubyNumeric.str2inum(runtime,runtime.newString(cert.getSerialNumber().toString()),10)); + set_not_before(RubyTime.newTime(runtime,cert.getNotBefore().getTime())); + set_not_after(RubyTime.newTime(runtime,cert.getNotAfter().getTime())); + set_subject(x509Name.callMethod(context,"new",RubyString.newString(runtime, cert.getSubjectX500Principal().getEncoded()))); + set_issuer(x509Name.callMethod(context,"new",RubyString.newString(runtime, cert.getIssuerX500Principal().getEncoded()))); + + String algorithm = cert.getPublicKey().getAlgorithm(); + set_public_key(algorithm, cert.getPublicKey().getEncoded()); + + IRubyObject extFact = ((RubyClass)(x509.getConstant("ExtensionFactory"))).callMethod(context,"new"); + extFact.callMethod(context,"subject_certificate=",this); + + Set crit = cert.getCriticalExtensionOIDs(); + if (crit != null) { + for (Iterator iter = crit.iterator(); iter.hasNext();) { + String critOid = iter.next(); + byte[] value = cert.getExtensionValue(critOid); + IRubyObject rValue = ASN1.decode(ossl.getConstant("ASN1"), runtime.newString(new ByteList(value, false))).callMethod(context, "value"); + X509Extensions.Extension ext = (X509Extensions.Extension) x509.getConstant("Extension").callMethod(context, "new", + new IRubyObject[] { runtime.newString(critOid), rValue, runtime.getTrue() }); + add_extension(ext); + } + } + + Set ncrit = cert.getNonCriticalExtensionOIDs(); + if (ncrit != null) { + for (Iterator iter = ncrit.iterator(); iter.hasNext();) { + String ncritOid = iter.next(); + byte[] value = cert.getExtensionValue(ncritOid); + // TODO: wired. J9 returns null for an OID given in getNonCriticalExtensionOIDs() + if (value != null) { + IRubyObject rValue = ASN1.decode(ossl.getConstant("ASN1"), runtime.newString(new ByteList(value, false))).callMethod(context, "value"); + X509Extensions.Extension ext = (X509Extensions.Extension) x509.getConstant("Extension").callMethod(context, "new", + new IRubyObject[] { runtime.newString(ncritOid), rValue, runtime.getFalse() }); + add_extension(ext); + } + } + } + changed = false; + + return this; + } + + //Lazy method for public key instantiation + private void set_public_key(String algorithm, byte[] encoded) { + this.public_key_algorithm = algorithm; + this.public_key_encoded = encoded; + } + + public static RaiseException newCertificateError(Ruby runtime, Exception ex) { + return newCertificateError(runtime, ex.getMessage()); + } + + public static RaiseException newCertificateError(Ruby runtime, String message) { + throw Utils.newError(runtime, "OpenSSL::X509::CertificateError", message); + } + + @Override + @JRubyMethod + public IRubyObject initialize_copy(IRubyObject obj) { + if(this == obj) { + return this; + } + checkFrozen(); + return this; + } + + @JRubyMethod + public IRubyObject to_der() { + try { + return RubyString.newString(getRuntime(), cert.getEncoded()); + } catch (CertificateEncodingException ex) { + throw newCertificateError(getRuntime(), ex); + } + } + + @JRubyMethod(name={"to_pem","to_s"}) + public IRubyObject to_pem() { + try { + StringWriter w = new StringWriter(); + PEMInputOutput.writeX509Certificate(w, getAuxCert()); + w.close(); + return getRuntime().newString(w.toString()); + } catch (IOException ex) { + throw getRuntime().newIOErrorFromException(ex); + } + } + + @JRubyMethod + public IRubyObject to_text() { + return getRuntime().newString(getAuxCert().toString()); + } + + @Override + @JRubyMethod + public IRubyObject inspect() { + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject version() { + return version; + } + + @JRubyMethod(name="version=") + public IRubyObject set_version(IRubyObject arg) { + if(!arg.equals(this.version)) { + changed = true; + } + this.version = arg; + return arg; + } + + @JRubyMethod + public IRubyObject signature_algorithm() { + return sig_alg; + } + + @JRubyMethod + public IRubyObject serial() { + return serial; + } + + @JRubyMethod(name="serial=") + public IRubyObject set_serial(IRubyObject num) { + if(!num.equals(this.serial)) { + changed = true; + } + serial = num; + String s = serial.toString(); + + BigInteger bi; + if (s.equals("0")) { // MRI compatibility: allow 0 serial number + bi = BigInteger.ONE; + } else { + bi = new BigInteger(s); + } + generator.setSerialNumber(bi); + return num; + } + + @JRubyMethod + public IRubyObject subject() { + return subject; + } + + @JRubyMethod(name="subject=") + public IRubyObject set_subject(IRubyObject arg) { + if(!arg.equals(this.subject)) { + changed = true; + } + subject = arg; + generator.setSubjectDN(((X509Name)subject).getRealName()); + return arg; + } + + @JRubyMethod + public IRubyObject issuer() { + return issuer; + } + + @JRubyMethod(name="issuer=") + public IRubyObject set_issuer(IRubyObject arg) { + if(!arg.equals(this.issuer)) { + changed = true; + } + issuer = arg; + generator.setIssuerDN(((X509Name)issuer).getRealName()); + return arg; + } + + @JRubyMethod + public IRubyObject not_before() { + return not_before; + } + + @JRubyMethod(name="not_before=") + public IRubyObject set_not_before(IRubyObject arg) { + changed = true; + not_before = arg.callMethod(getRuntime().getCurrentContext(),"getutc"); + ((RubyTime)not_before).setMicroseconds(0); + generator.setNotBefore(((RubyTime)not_before).getJavaDate()); + return arg; + } + + @JRubyMethod + public IRubyObject not_after() { + return not_after; + } + + @JRubyMethod(name="not_after=") + public IRubyObject set_not_after(IRubyObject arg) { + changed = true; + not_after = arg.callMethod(getRuntime().getCurrentContext(),"getutc"); + ((RubyTime)not_after).setMicroseconds(0); + generator.setNotAfter(((RubyTime)not_after).getJavaDate()); + return arg; + } + + @JRubyMethod + public IRubyObject public_key() { + if (public_key == null) { + lazyInitializePublicKey(); + } + return public_key.callMethod(getRuntime().getCurrentContext(), "public_key"); + } + + @JRubyMethod(name="public_key=") + public IRubyObject set_public_key(IRubyObject arg) { + Utils.checkKind(getRuntime(), arg, "OpenSSL::PKey::PKey"); + if(!arg.equals(this.public_key)) { + changed = true; + } + public_key = arg; + generator.setPublicKey(((PKey)public_key).getPublicKey()); + return arg; + } + + private void lazyInitializePublicKey() { + if (public_key_encoded == null || public_key_algorithm == null) { + throw new IllegalStateException("lazy public key initialization failed"); + } + RubyModule ossl = getRuntime().getModule("OpenSSL"); + RubyModule pkey = (RubyModule) ossl.getConstant("PKey"); + ThreadContext tc = getRuntime().getCurrentContext(); + boolean backupChanged = changed; + if ("RSA".equalsIgnoreCase(public_key_algorithm)) { + set_public_key(pkey.getConstant("RSA").callMethod(tc, "new", RubyString.newString(getRuntime(), public_key_encoded))); + } else if ("DSA".equalsIgnoreCase(public_key_algorithm)) { + set_public_key(pkey.getConstant("DSA").callMethod(tc, "new", RubyString.newString(getRuntime(), public_key_encoded))); + } else { + throw newCertificateError(getRuntime(), "The algorithm " + public_key_algorithm + " is unsupported for public keys"); + } + changed = backupChanged; + } + + @JRubyMethod + public IRubyObject sign(ThreadContext context, final IRubyObject key, IRubyObject digest) { + Ruby runtime = context.getRuntime(); + + // Have to obey some artificial constraints of the OpenSSL implementation. Stupid. + String keyAlg = ((PKey)key).getAlgorithm(); + String digAlg = ((Digest)digest).getShortAlgorithm(); + String digName = ((Digest)digest).name().toString(); + + if(("DSA".equalsIgnoreCase(keyAlg) && "MD5".equalsIgnoreCase(digAlg)) || + ("RSA".equalsIgnoreCase(keyAlg) && "DSS1".equals(digName))) { + throw newCertificateError(runtime, "signature_algorithm not supported"); + } + + for(Iterator iter = extensions.iterator();iter.hasNext();) { + X509Extensions.Extension ag = (X509Extensions.Extension)iter.next(); + try { + byte[] bytes = ag.getRealValueBytes(); + generator.addExtension(ag.getRealOid(),ag.getRealCritical(),bytes); + } catch (IOException ioe) { + throw runtime.newIOErrorFromException(ioe); + } + } + + generator.setSignatureAlgorithm(digAlg + "WITH" + keyAlg); + if (public_key == null) { + lazyInitializePublicKey(); + } + try { + // X509V3CertificateGenerator depends BC. + OpenSSLReal.doWithBCProvider(new OpenSSLReal.Runnable() { + + public void run() throws GeneralSecurityException { + cert = generator.generate(((PKey) key).getPrivateKey(), "BC"); + } + }); + } catch (GeneralSecurityException gse) { + throw newCertificateError(getRuntime(), gse.getMessage()); + } + if (cert == null) { + throw newCertificateError(runtime, (String) null); + } + String name = ASN1Registry.o2a(cert.getSigAlgOID()); + if (name == null) { + name = cert.getSigAlgOID(); + } + sig_alg = runtime.newString(name); + changed = false; + return this; + } + + @JRubyMethod + public IRubyObject verify(IRubyObject key) { + if(changed) { + return getRuntime().getFalse(); + } + try { + cert.verify(((PKey)key).getPublicKey()); + return getRuntime().getTrue(); + } catch (CertificateException ce) { + throw newCertificateError(getRuntime(), ce); + } catch (NoSuchAlgorithmException nsae) { + throw newCertificateError(getRuntime(), nsae); + } catch (NoSuchProviderException nspe) { + throw newCertificateError(getRuntime(), nspe); + } catch (SignatureException se) { + throw newCertificateError(getRuntime(), se); + } catch(InvalidKeyException e) { + return getRuntime().getFalse(); + } + } + + @JRubyMethod + public IRubyObject check_private_key(IRubyObject arg) { + PKey key = (PKey)arg; + PublicKey pkey = key.getPublicKey(); + PublicKey certPubKey = getAuxCert().getPublicKey(); + if (certPubKey.equals(pkey)) + return getRuntime().getTrue(); + return getRuntime().getFalse(); + } + + @JRubyMethod + public IRubyObject extensions() { + return getRuntime().newArray(extensions); + } + + @SuppressWarnings("unchecked") + @JRubyMethod(name="extensions=") + public IRubyObject set_extensions(IRubyObject arg) { + extensions = new ArrayList(((RubyArray)arg).getList()); + return arg; + } + + @JRubyMethod + public IRubyObject add_extension(IRubyObject arg) { + changed = true; + DERObjectIdentifier oid = ((X509Extensions.Extension)arg).getRealOid(); + if(oid.equals(new DERObjectIdentifier("2.5.29.17"))) { + boolean one = true; + for(Iterator iter = extensions.iterator();iter.hasNext();) { + X509Extensions.Extension ag = (X509Extensions.Extension)iter.next(); + if(ag.getRealOid().equals(new DERObjectIdentifier("2.5.29.17"))) { + ASN1EncodableVector v1 = new ASN1EncodableVector(); + + try { + GeneralName[] n1 = GeneralNames.getInstance(new ASN1InputStream(ag.getRealValueBytes()).readObject()).getNames(); + GeneralName[] n2 = GeneralNames.getInstance(new ASN1InputStream(((X509Extensions.Extension)arg).getRealValueBytes()).readObject()).getNames(); + + for(int i=0;i + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DERBoolean; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERIA5String; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERString; +import org.bouncycastle.asn1.DERUnknownTag; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.GeneralNames; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.impl.ASN1Registry; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; +import org.jruby.util.ByteList; + +/** + * @author Ola Bini + */ +public class X509Extensions { + public static void createX509Ext(Ruby runtime, RubyModule mX509) { + RubyClass cX509ExtFactory = mX509.defineClassUnder("ExtensionFactory",runtime.getObject(),ExtensionFactory.ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("ExtensionError",openSSLError,openSSLError.getAllocator()); + + cX509ExtFactory.attr_reader(runtime.getCurrentContext(), new IRubyObject[]{runtime.newString("issuer_certificate"),runtime.newString("subject_certificate"), + runtime.newString("subject_request"),runtime.newString("crl"), + runtime.newString("config")}); + + cX509ExtFactory.defineAnnotatedMethods(ExtensionFactory.class); + + RubyClass cX509Ext = mX509.defineClassUnder("Extension",runtime.getObject(),Extension.ALLOCATOR); + cX509Ext.defineAnnotatedMethods(Extension.class); + } + + public static class ExtensionFactory extends RubyObject { + private static final long serialVersionUID = 3180447029639456500L; + + public static ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new ExtensionFactory(runtime, klass); + } + }; + + public ExtensionFactory(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + @JRubyMethod(rest=true,frame=true) + public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { + org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,0,4); + if(args.length > 0 && !args[0].isNil()) { + set_issuer_cert(args[0]); + } + if(args.length > 1 && !args[1].isNil()) { + set_subject_cert(args[1]); + } + if(args.length > 2 && !args[2].isNil()) { + set_subject_req(args[2]); + } + if(args.length > 3 && !args[3].isNil()) { + set_crl(args[3]); + } + return this; + } + + @JRubyMethod(name="issuer_certificate=") + public IRubyObject set_issuer_cert(IRubyObject arg) { + setInstanceVariable("@issuer_certificate",arg); + return arg; + } + + @JRubyMethod(name="subject_certificate=") + public IRubyObject set_subject_cert(IRubyObject arg) { + setInstanceVariable("@subject_certificate",arg); + return arg; + } + + @JRubyMethod(name="subject_request=") + public IRubyObject set_subject_req(IRubyObject arg) { + setInstanceVariable("@subject_request",arg); + return arg; + } + + @JRubyMethod(name="crl=") + public IRubyObject set_crl(IRubyObject arg) { + setInstanceVariable("@crl",arg); + return arg; + } + + @JRubyMethod(name="config=") + public IRubyObject set_config(IRubyObject arg) { + setInstanceVariable("@config",arg); + return arg; + } + + private DERObjectIdentifier getObjectIdentifier(String nameOrOid) { + Object val1 = ASN1.getOIDLookup(getRuntime()).get(nameOrOid.toLowerCase()); + if(null != val1) { + return (DERObjectIdentifier)val1; + } + DERObjectIdentifier val2 = new DERObjectIdentifier(nameOrOid); + return val2; + } + + private static boolean isHexDigit(char c) { + return ('0'<=c && c<='9') || ('A'<= c && c <= 'F') || ('a'<= c && c <= 'f'); + } + + private boolean isHexString(String str ){ + for(int i = 0; i< str.length(); i++) { + if (!isHexDigit(str.charAt(i))) return false; + } + return true; + } + + @JRubyMethod(rest=true) + public IRubyObject create_ext(IRubyObject[] args) { + IRubyObject critical = getRuntime().getFalse(); + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,2,3) == 3 && !args[2].isNil()) { + critical = args[2]; + } + String oid = args[0].toString(); + String valuex = args[1].toString(); + Object value = valuex; + + DERObjectIdentifier r_oid = null; + + try { + r_oid = getObjectIdentifier(oid); + } catch(IllegalArgumentException e) { + r_oid = null; + } + if (null == r_oid) { + throw newX509ExtError(getRuntime(), "unknown OID `" + oid + "'"); + } + + ThreadContext tc = getRuntime().getCurrentContext(); + Extension ext = (Extension) Utils.newRubyInstance(getRuntime(), "OpenSSL::X509::Extension"); + + if(valuex.startsWith("critical,")) { + critical = getRuntime().getTrue(); + valuex = valuex.substring(9).trim(); + } + + if(r_oid.equals(new DERObjectIdentifier("2.5.29.14"))) { //subjectKeyIdentifier + if("hash".equalsIgnoreCase(valuex)) { + IRubyObject pkey = getInstanceVariable("@subject_certificate").callMethod(tc,"public_key"); + IRubyObject val = null; + if(pkey instanceof PKeyRSA) { + val = pkey.callMethod(tc,"to_der"); + } else { + val = ASN1.decode(getRuntime().getClassFromPath("OpenSSL::ASN1"), pkey.callMethod(tc, "to_der")).callMethod(tc, "value") + .callMethod(tc, "[]", getRuntime().newFixnum(1)).callMethod(tc, "value"); + } + byte[] b = getSHA1Digest(getRuntime(), val.convertToString().getBytes()); + value = new String(ByteList.plain(new DEROctetString(b).getDEREncoded())); + } else if(valuex.length() == 20 || !isHexString(valuex)) { + value = new String(ByteList.plain(new DEROctetString(ByteList.plain(valuex)).getDEREncoded())); + } else { + StringBuffer nstr = new StringBuffer(); + for(int i = 0; i < valuex.length(); i+=2) { + if(i+1 >= valuex.length()) { + throw newX509ExtError(getRuntime(), oid + " = " + value + ": odd number of digits"); + } + + char c1 = valuex.charAt(i); + char c2 = valuex.charAt(i+1); + if(isHexDigit(c1) && isHexDigit(c2)) { + nstr.append(Character.toUpperCase(c1)).append(Character.toUpperCase(c2)); + } else { + throw newX509ExtError(getRuntime(), oid + " = " + value + ": illegal hex digit"); + } + while((i+2) < valuex.length() && valuex.charAt(i+2) == ':') { + i++; + } + } + String v = nstr.toString(); + byte[] arr = new byte[v.length()/2]; + for(int i=0;i 3 && spl[i].substring(0,3).equalsIgnoreCase("CA:")) { + asnv.add(new DERBoolean("TRUE".equalsIgnoreCase(spl[i].substring(3).trim()))); + } + } + for(int i=0;i 8 && spl[i].substring(0,8).equalsIgnoreCase("pathlen:")) { + asnv.add(new DERInteger(Integer.parseInt(spl[i].substring(8).trim()))); + } + } + value = new String(ByteList.plain(new DERSequence(asnv).getDEREncoded())); + } else if(r_oid.equals(new DERObjectIdentifier("2.5.29.15"))) { //keyUsage + byte[] inp = null; + try { + String[] exx = valuex.split(":"); + if(exx != null) { + inp = new byte[exx.length]; + for(int i=0;i-1; i--) { + if(inp[i] == 0) { + unused += 8; + } else { + byte a2 = inp[i]; + int x = 8; + while(a2 != 0) { + a2 <<= 1; + x--; + } + unused += x; + break; + } + } + + value = new String(ByteList.plain(new DERBitString(inp,unused).getDEREncoded())); + } else if(r_oid.equals(new DERObjectIdentifier("2.16.840.1.113730.1.1"))) { //nsCertType + byte v = 0; + if (valuex.length() < 3) { + byte[] inp = ByteList.plain(valuex); + v = inp[0]; + } else { + String[] spl = valuex.split(","); + for (int i = 0; i < spl.length; i++) { + spl[i] = spl[i].trim(); + } + for (int i = 0; i < spl.length; i++) { + if ("SSL Client".equals(spl[i]) || "client".equals(spl[i])) { + v |= (byte) 128; + } else if ("SSL Server".equals(spl[i]) || "server".equals(spl[i])) { + v |= (byte) 64; + } else if ("S/MIME".equals(spl[i]) || "email".equals(spl[i])) { + v |= (byte) 32; + } else if ("Object Signing".equals(spl[i]) || "objsign".equals(spl[i])) { + v |= (byte) 16; + } else if ("Unused".equals(spl[i]) || "reserved".equals(spl[i])) { + v |= (byte) 8; + } else if ("SSL CA".equals(spl[i]) || "sslCA".equals(spl[i])) { + v |= (byte) 4; + } else if ("S/MIME CA".equals(spl[i]) || "emailCA".equals(spl[i])) { + v |= (byte) 2; + } else if ("Object Signing CA".equals(spl[i]) || "objCA".equals(spl[i])) { + v |= (byte) 1; + } else { + throw newX509ExtError(getRuntime(), oid + " = " + valuex + ": unknown bit string argument"); + } + } + } + int unused = 0; + if (v == 0) { + unused += 8; + } else { + byte a2 = v; + int x = 8; + while (a2 != 0) { + a2 <<= 1; + x--; + } + unused += x; + } + value = new DERBitString(new byte[] { v }, unused); + } else if(r_oid.equals(new DERObjectIdentifier("2.5.29.17"))) { //subjectAltName + if(valuex.startsWith("DNS:")) { + value = new String(ByteList.plain(new GeneralNames(new GeneralName(GeneralName.dNSName,new DERIA5String(valuex.substring(4)))).getDEREncoded())); + } else if(valuex.startsWith("IP:")) { + String[] numbers = valuex.substring(3).split("\\."); + byte[] bs = new byte[4]; + bs[0] = (byte) (Integer.parseInt(numbers[0]) & 0xff); + bs[1] = (byte) (Integer.parseInt(numbers[1]) & 0xff); + bs[2] = (byte) (Integer.parseInt(numbers[2]) & 0xff); + bs[3] = (byte) (Integer.parseInt(numbers[3]) & 0xff); + value = new String(ByteList.plain(new GeneralNames(new GeneralName(GeneralName.iPAddress,new DEROctetString(bs))).getDEREncoded())); + } else if(valuex.startsWith("IP Address:")) { + String[] numbers = valuex.substring(11).split("\\."); + byte[] bs = new byte[4]; + bs[0] = (byte) (Integer.parseInt(numbers[0]) & 0xff); + bs[1] = (byte) (Integer.parseInt(numbers[1]) & 0xff); + bs[2] = (byte) (Integer.parseInt(numbers[2]) & 0xff); + bs[3] = (byte) (Integer.parseInt(numbers[3]) & 0xff); + value = new String(ByteList.plain(new GeneralNames(new GeneralName(GeneralName.iPAddress,new DEROctetString(bs))).getDEREncoded())); + } + } else if(r_oid.equals(new DERObjectIdentifier("2.5.29.37"))) { //extendedKeyUsage + String[] spl = valuex.split(", ?"); + ASN1EncodableVector vector = new ASN1EncodableVector(); + for(String name : spl) { + vector.add(ASN1Registry.sym2oid(name)); + } + value = new DERSequence(vector); + } else { + value = new DEROctetString(new DEROctetString(ByteList.plain(valuex)).getDEREncoded()); + } + + ext.setRealOid(r_oid); + ext.setRealValue(value); + ext.setRealCritical(critical.isTrue()); + + return ext; + } + } + + private static byte[] getSHA1Digest(Ruby runtime, byte[] bytes) { + try { + return MessageDigest.getInstance("SHA-1").digest(bytes); + } catch (GeneralSecurityException gse) { + throw newX509ExtError(runtime, gse.getMessage()); + } + } + + public static class Extension extends RubyObject { + private static final long serialVersionUID = -1160318458085651926L; + + public static ObjectAllocator ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new Extension(runtime, klass); + } + }; + + public Extension(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + private DERObjectIdentifier oid; + private Object value; + private boolean critical; + + void setRealOid(DERObjectIdentifier oid) { + this.oid = oid; + } + + void setRealValue(Object value) { + this.value = value; + } + + void setRealCritical(boolean critical) { + this.critical = critical; + } + + DERObjectIdentifier getRealOid() { + return oid; + } + + Object getRealValue() { + return value; + } + + byte[] getRealValueBytes() throws IOException { + if((value instanceof RubyString)) { + return ((RubyString) value).convertToString().getBytes(); + } else if(value instanceof String) { + return ByteList.plain((String) value); + } else if(value instanceof DEROctetString) { + return ((DEROctetString)value).getOctets(); + } else if(value instanceof DEREncodable) { + return ((ASN1Encodable)value).getEncoded(); + } else { + return ((ASN1.ASN1Data)value).toASN1().getDEREncoded(); + } + } + + boolean getRealCritical() { + return critical; + } + + DERObjectIdentifier getObjectIdentifier(String nameOrOid) { + Object val1 = ASN1.getOIDLookup(getRuntime()).get(nameOrOid.toLowerCase()); + if(null != val1) { + return (DERObjectIdentifier)val1; + } + DERObjectIdentifier val2 = new DERObjectIdentifier(nameOrOid); + return val2; + } + + @JRubyMethod(name = "initialize", rest = true) + public IRubyObject _initialize(IRubyObject[] args) { + byte[] octets = null; + if (args.length == 1) { + try { + ASN1InputStream is = new ASN1InputStream(OpenSSLImpl.to_der_if_possible(args[0]).convertToString().getBytes()); + Object obj = is.readObject(); + ASN1Sequence seq = (ASN1Sequence) obj; + setRealOid((DERObjectIdentifier) (seq.getObjectAt(0))); + setRealCritical(((DERBoolean) (seq.getObjectAt(1))).isTrue()); + octets = ((DEROctetString) (seq.getObjectAt(2))).getOctets(); + } catch (IOException ioe) { + throw newX509ExtError(getRuntime(), ioe.getMessage()); + } + } else if (args.length > 1) { + setRealOid(getObjectIdentifier(args[0].toString())); + setRealValue(args[1]); + } + if (args.length > 2) { + setRealCritical(args[2].isTrue()); + } + if (args.length > 0 && octets != null) { + setRealValue(new String(ByteList.plain(octets))); + } + return this; + } + + @JRubyMethod(name="oid=") + public IRubyObject set_oid(IRubyObject arg) { + System.err.println("WARNING: calling ext#oid="); + return getRuntime().getNil(); + } + + @JRubyMethod(name="value=") + public IRubyObject set_value(IRubyObject arg) { + System.err.println("WARNING: calling ext#value="); + return getRuntime().getNil(); + } + + @JRubyMethod(name="critical=") + public IRubyObject set_critical(IRubyObject arg) { + System.err.println("WARNING: calling ext#critical="); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject oid() { + Object val = ASN1.getSymLookup(getRuntime()).get(oid); + if(null == val) { + val = oid.toString(); + } + return getRuntime().newString((String)(val)); + } + + @JRubyMethod + public IRubyObject value() { + Ruby runtime = getRuntime(); + try { + if (getRealOid().equals(new DERObjectIdentifier("2.5.29.19"))) { //basicConstraints + ASN1Sequence seq2 = (ASN1Sequence) (new ASN1InputStream(getRealValueBytes()).readObject()); + String c = ""; + String path = ""; + if (seq2.size() > 0) { + c = "CA:" + (((DERBoolean) (seq2.getObjectAt(0))).isTrue() ? "TRUE" : "FALSE"); + } + if (seq2.size() > 1) { + path = ", pathlen:" + seq2.getObjectAt(1).toString(); + } + return runtime.newString(c + path); + } else if (getRealOid().equals(new DERObjectIdentifier("2.5.29.15"))) { //keyUsage + byte[] bx = getRealValueBytes(); + byte[] bs = new byte[bx.length - 2]; + System.arraycopy(bx, 2, bs, 0, bs.length); + byte b1 = 0; + byte b2 = bs[0]; + if (bs.length > 1) { + b1 = bs[1]; + } + StringBuffer sbe = new StringBuffer(); + String sep = ""; + if ((b2 & (byte) 128) != 0) { + sbe.append(sep).append("Decipher Only"); + sep = ", "; + } + if ((b1 & (byte) 128) != 0) { + sbe.append(sep).append("Digital Signature"); + sep = ", "; + } + if ((b1 & (byte) 64) != 0) { + sbe.append(sep).append("Non Repudiation"); + sep = ", "; + } + if ((b1 & (byte) 32) != 0) { + sbe.append(sep).append("Key Encipherment"); + sep = ", "; + } + if ((b1 & (byte) 16) != 0) { + sbe.append(sep).append("Data Encipherment"); + sep = ", "; + } + if ((b1 & (byte) 8) != 0) { + sbe.append(sep).append("Key Agreement"); + sep = ", "; + } + if ((b1 & (byte) 4) != 0) { + sbe.append(sep).append("Key Cert Sign"); + sep = ", "; + } + if ((b1 & (byte) 2) != 0) { + sbe.append(sep).append("cRLSign"); + sep = ", "; + } + if ((b1 & (byte) 1) != 0) { + sbe.append(sep).append("Encipher Only"); + } + return runtime.newString(sbe.toString()); + } else if (getRealOid().equals(new DERObjectIdentifier("2.16.840.1.113730.1.1"))) { //nsCertType + byte[] bx = getRealValueBytes(); + byte b = bx[0]; + StringBuffer sbe = new StringBuffer(); + String sep = ""; + if ((b & (byte) 128) != 0) { + sbe.append(sep).append("SSL Client"); + sep = ", "; + } + if ((b & (byte) 64) != 0) { + sbe.append(sep).append("SSL Servern"); + sep = ", "; + } + if ((b & (byte) 32) != 0) { + sbe.append(sep).append("S/MIME"); + sep = ", "; + } + if ((b & (byte) 16) != 0) { + sbe.append(sep).append("Object Signing"); + sep = ", "; + } + if ((b & (byte) 8) != 0) { + sbe.append(sep).append("Unused"); + sep = ", "; + } + if ((b & (byte) 4) != 0) { + sbe.append(sep).append("SSL CA"); + sep = ", "; + } + if ((b & (byte) 2) != 0) { + sbe.append(sep).append("S/MIME CA"); + sep = ", "; + } + if ((b & (byte) 1) != 0) { + sbe.append(sep).append("Object Signing CA"); + } + return runtime.newString(sbe.toString()); + } else if (getRealOid().equals(new DERObjectIdentifier("2.5.29.14"))) { //subjectKeyIdentifier + byte[] b1 = getRealValueBytes(); + byte[] b2 = new byte[b1.length - 2]; + System.arraycopy(b1, 2, b2, 0, b2.length); + return runtime.newString(Utils.toHex(b2, ':')); + } else if (getRealOid().equals(new DERObjectIdentifier("2.5.29.35"))) { // authorityKeyIdentifier + DERSequence seq = (DERSequence) (new ASN1InputStream(getRealValueBytes()).readObject()); + StringBuffer out1 = new StringBuffer(); + if (seq.size() > 0) { + out1.append("keyid:"); + DERObject keyid = seq.getObjectAt(0).getDERObject(); + if (keyid instanceof DEROctetString) { + out1.append(Utils.toHex(((DEROctetString) keyid).getOctets(), ':')); + } else { + out1.append(Utils.toHex(keyid.getDEREncoded(), ':')); + } + } + return runtime.newString(out1.toString()); + } else if (getRealOid().equals(new DERObjectIdentifier("2.5.29.21"))) { // CRLReason + switch (RubyNumeric.fix2int(((IRubyObject) value).callMethod(runtime.getCurrentContext(), "value"))) { + case 0: + return runtime.newString("Unspecified"); + case 1: + return runtime.newString("Key Compromise"); + case 2: + return runtime.newString("CA Compromise"); + case 3: + return runtime.newString("Affiliation Changed"); + case 4: + return runtime.newString("Superseded"); + case 5: + return runtime.newString("Cessation Of Operation"); + case 6: + return runtime.newString("Certificate Hold"); + case 8: + return runtime.newString("Remove From CRL"); + case 9: + return runtime.newString("Privilege Withdrawn"); + default: + return runtime.newString("Unspecified"); + } + } else if (getRealOid().equals(new DERObjectIdentifier("2.5.29.17"))) { //subjectAltName + try { + DERObject seq = new ASN1InputStream(getRealValueBytes()).readObject(); + GeneralName[] n1 = null; + if (seq instanceof DERUnknownTag) { + n1 = new GeneralName[]{GeneralName.getInstance(seq)}; + } else if (seq instanceof org.bouncycastle.asn1.DERTaggedObject) { + n1 = new GeneralName[]{GeneralName.getInstance(seq)}; + } else { + n1 = GeneralNames.getInstance(seq).getNames(); + } + StringBuffer sbe = new StringBuffer(); + String sep = ""; + for (int i = 0; i < n1.length; i++) { + sbe.append(sep); + if (n1[i].getTagNo() == GeneralName.dNSName) { + sbe.append("DNS:"); + sbe.append(((DERString) n1[i].getName()).getString()); + } else if (n1[i].getTagNo() == GeneralName.iPAddress) { + sbe.append("IP Address:"); + byte[] bs = ((DEROctetString) n1[i].getName()).getOctets(); + String sep2 = ""; + for (int j = 0; j < bs.length; j++) { + sbe.append(sep2); + sbe.append(((int) bs[j]) & 0xff); + sep2 = "."; + } + } else { + sbe.append(n1[i].toString()); + } + sep = ", "; + } + return runtime.newString(sbe.toString()); + } catch (Exception e) { + return runtime.newString(getRealValue().toString()); + } + } else { + try { + return ASN1.decode(runtime.getClassFromPath("OpenSSL::ASN1"), RubyString.newString(runtime, getRealValueBytes())) + .callMethod(runtime.getCurrentContext(), "value").callMethod(runtime.getCurrentContext(), "to_s"); + } catch (Exception e) { + return runtime.newString(getRealValue().toString()); + } + } + } catch (IOException ioe) { + throw newX509ExtError(runtime, ioe.getMessage()); + } + } + + @JRubyMethod(name="critical?") + public IRubyObject critical_p() { + return critical ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @JRubyMethod + public IRubyObject to_der() { + ASN1EncodableVector all = new ASN1EncodableVector(); + try { + all.add(getRealOid()); + all.add(getRealCritical() ? DERBoolean.TRUE : DERBoolean.FALSE); + all.add(new DEROctetString(getRealValueBytes())); + return RubyString.newString(getRuntime(), new DERSequence(all).getDEREncoded()); + } catch (IOException ioe) { + throw newX509ExtError(getRuntime(), ioe.getMessage()); + } + } + } + + private static RaiseException newX509ExtError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::X509::ExtensionError", message); + } +}// X509Extensions diff --git a/src/org/jruby/ext/openssl/X509Name.java b/src/org/jruby/ext/openssl/X509Name.java new file mode 100644 index 00000000000..2b2d30e4e30 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509Name.java @@ -0,0 +1,420 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Vector; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERString; +import org.bouncycastle.asn1.DERTags; +import org.bouncycastle.asn1.x509.X509DefaultEntryConverter; +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyHash; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyString; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.Name; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class X509Name extends RubyObject { + private static final long serialVersionUID = -226196051911335103L; + + private static ObjectAllocator X509NAME_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509Name(runtime, klass); + } + }; + + public static void createX509Name(Ruby runtime, RubyModule mX509) { + RubyClass cX509Name = mX509.defineClassUnder("Name",runtime.getObject(),X509NAME_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("NameError",openSSLError,openSSLError.getAllocator()); + + cX509Name.defineAnnotatedMethods(X509Name.class); + + cX509Name.setConstant("COMPAT",runtime.newFixnum(COMPAT)); + cX509Name.setConstant("RFC2253",runtime.newFixnum(RFC2253)); + cX509Name.setConstant("ONELINE",runtime.newFixnum(ONELINE)); + cX509Name.setConstant("MULTILINE",runtime.newFixnum(MULTILINE)); + + cX509Name.setConstant("DEFAULT_OBJECT_TYPE",runtime.newFixnum(DERTags.UTF8_STRING)); + + RubyHash hash = new RubyHash(runtime, runtime.newFixnum(DERTags.UTF8_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("C"),runtime.newFixnum(DERTags.PRINTABLE_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("countryName"),runtime.newFixnum(DERTags.PRINTABLE_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("serialNumber"),runtime.newFixnum(DERTags.PRINTABLE_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("dnQualifier"),runtime.newFixnum(DERTags.PRINTABLE_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("DC"),runtime.newFixnum(DERTags.IA5_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("domainComponent"),runtime.newFixnum(DERTags.IA5_STRING)); + hash.op_aset(runtime.getCurrentContext(), runtime.newString("emailAddress"),runtime.newFixnum(DERTags.IA5_STRING)); + cX509Name.setConstant("OBJECT_TYPE_TEMPLATE", hash); + } + + public static final int COMPAT = 0; + public static final int RFC2253 = 17892119; + public static final int ONELINE = 8520479; + public static final int MULTILINE = 44302342; + + public X509Name(Ruby runtime, RubyClass type) { + super(runtime,type); + oids = new ArrayList(); + values = new ArrayList(); + types = new ArrayList(); + } + + private List oids; + private List values; + private List types; + + void addEntry(Object oid, Object value, Object type) { + oids.add(oid); + values.add(value); + types.add(type); + } + + public static X509Name create(Ruby runtime, org.bouncycastle.asn1.x509.X509Name realName) { + X509Name name = new X509Name(runtime, Utils.getClassFromPath(runtime, "OpenSSL::X509::Name")); + name.fromASN1Sequence((ASN1Sequence)realName.getDERObject()); + return name; + } + + void fromASN1Sequence(ASN1Sequence seq) { + oids = new ArrayList(); + values = new ArrayList(); + types = new ArrayList(); + for (Enumeration enumRdn = seq.getObjects(); enumRdn.hasMoreElements();) { + ASN1Set rdn = (ASN1Set) enumRdn.nextElement(); + for (Enumeration enumTypeAndValue = rdn.getObjects(); enumTypeAndValue.hasMoreElements();) { + ASN1Sequence typeAndValue = (ASN1Sequence) enumTypeAndValue.nextElement(); + oids.add(typeAndValue.getObjectAt(0)); + if (typeAndValue.getObjectAt(1) instanceof DERString) { + values.add(((DERString) typeAndValue.getObjectAt(1)).getString()); + } else { + values.add(null); + } + types.add(getRuntime().newFixnum(ASN1.idForClass(typeAndValue.getObjectAt(1).getClass()))); + } + } + } + + @JRubyMethod(rest=true, frame=true) + public IRubyObject initialize(IRubyObject[] args, Block unusedBlock) { + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,0,2) == 0) { + return this; + } + IRubyObject arg = args[0]; + IRubyObject template = getRuntime().getNil(); + if(args.length > 1) { + template = args[1]; + } + IRubyObject tmp = (arg instanceof RubyArray) ? arg : getRuntime().getNil(); + if(!tmp.isNil()) { + if(template.isNil()) { + template = getRuntime().getClassFromPath("OpenSSL::X509::Name").getConstant("OBJECT_TYPE_TEMPLATE"); + } + for (IRubyObject obj : ((RubyArray)tmp).toJavaArray()) { + RubyArray arr = (RubyArray) obj; + IRubyObject[] ele = arr.toJavaArray(); + IRubyObject[] entry = new IRubyObject[3]; + if (ele.length > 1) { + entry[0] = ele[0]; + entry[1] = ele[1]; + } + if (ele.length > 2) { + entry[2] = ele[2]; + } + if (entry[2] == null || entry[2].isNil()) { + entry[2] = template.callMethod(getRuntime().getCurrentContext(),"[]",entry[0]); + } + if (entry[2] == null || entry[2].isNil()) { + entry[2] = getRuntime().getClassFromPath("OpenSSL::X509::Name").getConstant("DEFAULT_OBJECT_TYPE"); + } + add_entry(entry); + } + } else { + try { + fromASN1Sequence((ASN1Sequence)new ASN1InputStream(OpenSSLImpl.to_der_if_possible(arg).convertToString().getBytes()).readObject()); + } catch(Exception e) { + System.err.println("exception in init for X509Name: " + e); + } + } + return this; + } + + /* + private void printASN(org.bouncycastle.asn1.DERObject obj) { + printASN(obj,0); + } + private void printASN(org.bouncycastle.asn1.DERObject obj, int indent) { + if(obj instanceof org.bouncycastle.asn1.ASN1Sequence) { + for(int i=0;i 2 && !args[2].isNil()) { + type = args[2]; + } + DERObjectIdentifier oid_v; + try { + oid_v = getObjectIdentifier(oid); + } catch (IllegalArgumentException e) { + throw newX509NameError(getRuntime(), "invalid field name: " + e.getMessage()); + } + if (null == oid_v) { + throw newX509NameError(getRuntime(), null); + } + oids.add(oid_v); + values.add(value); + types.add(type); + return this; + } + + @JRubyMethod(name="to_s", rest=true) + public IRubyObject _to_s(IRubyObject[] args) { + /* +Should follow parameters like this: +if 0 (COMPAT): +irb(main):025:0> x.to_s(OpenSSL::X509::Name::COMPAT) +=> "CN=ola.bini, O=sweden/streetAddress=sweden, O=sweden/2.5.4.43343=sweden" +irb(main):026:0> x.to_s(OpenSSL::X509::Name::ONELINE) +=> "CN = ola.bini, O = sweden, streetAddress = sweden, O = sweden, 2.5.4.43343 = sweden" +irb(main):027:0> x.to_s(OpenSSL::X509::Name::MULTILINE) +=> "commonName = ola.bini\norganizationName = sweden\nstreetAddress = sweden\norganizationName = sweden\n2.5.4.43343 = sweden" +irb(main):028:0> x.to_s(OpenSSL::X509::Name::RFC2253) +=> "2.5.4.43343=#0C0673776564656E,O=sweden,streetAddress=sweden,O=sweden,CN=ola.bini" +else +=> /CN=ola.bini/O=sweden/streetAddress=sweden/O=sweden/2.5.4.43343=sweden + + */ + + int flag = -1; + if(args.length > 0 && !args[0].isNil()) { + flag = RubyNumeric.fix2int(args[0]); + } + + StringBuffer sb = new StringBuffer(); + Map lookup = ASN1.getSymLookup(getRuntime()); + Iterator oiter = null; + Iterator viter = null; + if(flag == RFC2253) { + List ao = new ArrayList(oids); + List av = new ArrayList(values); + java.util.Collections.reverse(ao); + java.util.Collections.reverse(av); + oiter = ao.iterator(); + viter = av.iterator(); + } else { + oiter = oids.iterator(); + viter = values.iterator(); + } + + String sep = ""; + for(;oiter.hasNext();) { + DERObjectIdentifier oid = (DERObjectIdentifier)oiter.next(); + String val = (String)viter.next(); + String outOid = lookup.get(oid); + if(null == outOid) { + outOid = oid.toString(); + } + if(flag == RFC2253) { + sb.append(sep).append(outOid).append("=").append(val); + sep = ","; + } else { + sb.append("/").append(outOid).append("=").append(val); + } + } + return getRuntime().newString(sb.toString()); + } + + @Override + @JRubyMethod + public RubyArray to_a() { + List entries = new ArrayList(); + Map lookup = ASN1.getSymLookup(getRuntime()); + Iterator oiter = oids.iterator(); + Iterator viter = values.iterator(); + Iterator titer = types.iterator(); + for(;oiter.hasNext();) { + DERObjectIdentifier oid = (DERObjectIdentifier)oiter.next(); + String val = (String)viter.next(); + String outOid = lookup.get(oid); + if(null == outOid) { + outOid = "UNDEF"; + } + IRubyObject type = (IRubyObject)titer.next(); + entries.add(getRuntime().newArrayNoCopy(new IRubyObject[]{getRuntime().newString(outOid),getRuntime().newString(val),type})); + } + return getRuntime().newArray(entries); + } + + @JRubyMethod(name={"cmp","<=>"}) + public IRubyObject cmp(IRubyObject other) { + if(eql_p(other).isTrue()) { + return RubyFixnum.zero(getRuntime()); + } + + return RubyFixnum.one(getRuntime()); + } + + org.bouncycastle.asn1.x509.X509Name getRealName() { + return new org.bouncycastle.asn1.x509.X509Name(new Vector(oids),new Vector(values)); + } + + @Override + @JRubyMethod(name="eql?") + public IRubyObject eql_p(IRubyObject other) { + if(!(other instanceof X509Name)) { + return getRuntime().getFalse(); + } + X509Name o = (X509Name)other; + org.bouncycastle.asn1.x509.X509Name nm = new org.bouncycastle.asn1.x509.X509Name(new Vector(oids),new Vector(values)); + org.bouncycastle.asn1.x509.X509Name o_nm = new org.bouncycastle.asn1.x509.X509Name(new Vector(o.oids),new Vector(o.values)); + return nm.equals(o_nm) ? getRuntime().getTrue() : getRuntime().getFalse(); + } + + @Override + @JRubyMethod + public RubyFixnum hash() { + Name name = new Name(new org.bouncycastle.asn1.x509.X509Name(new Vector(oids),new Vector(values))); + return getRuntime().newFixnum(name.hash()); + } + + @JRubyMethod + public IRubyObject to_der() { + DERSequence seq = null; + if(oids.size()>0) { + ASN1EncodableVector vec = new ASN1EncodableVector(); + ASN1EncodableVector sVec = new ASN1EncodableVector(); + DERObjectIdentifier lstOid = null; + for (int i = 0; i != oids.size(); i++) { + ASN1EncodableVector v = new ASN1EncodableVector(); + DERObjectIdentifier oid = (DERObjectIdentifier)oids.get(i); + v.add(oid); + String str = (String)values.get(i); + v.add(convert(oid,str,RubyNumeric.fix2int(((RubyFixnum)types.get(i))))); + if (lstOid == null) { + sVec.add(new DERSequence(v)); + } else { + vec.add(new DERSet(sVec)); + sVec = new ASN1EncodableVector(); + sVec.add(new DERSequence(v)); + } + lstOid = oid; + } + vec.add(new DERSet(sVec)); + seq = new DERSequence(vec); + } else { + seq = new DERSequence(); + } + + return RubyString.newString(getRuntime(), seq.getDEREncoded()); + } + + private DERObject convert(DERObjectIdentifier oid, String value, int type) { + try { + Class clzz = ASN1.classForId(type); + if (clzz != null) { + java.lang.reflect.Constructor ctor = clzz.getConstructor(new Class[]{String.class}); + if (null != ctor) { + return (DERObject) ctor.newInstance(new Object[]{value}); + } + } + return new X509DefaultEntryConverter().getConvertedValue(oid, value); + } catch (Exception e) { + throw newX509NameError(getRuntime(), e.getMessage()); + } + } + + private static RaiseException newX509NameError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::X509::NameError", message); + } +}// X509Name diff --git a/src/org/jruby/ext/openssl/X509Revoked.java b/src/org/jruby/ext/openssl/X509Revoked.java new file mode 100644 index 00000000000..eb442228979 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509Revoked.java @@ -0,0 +1,113 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyObject; +import org.jruby.anno.JRubyMethod; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class X509Revoked extends RubyObject { + private static final long serialVersionUID = 1L; + + private static ObjectAllocator X509REVOKED_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509Revoked(runtime, klass); + } + }; + + public static void createX509Revoked(Ruby runtime, RubyModule mX509) { + RubyClass cX509Rev = mX509.defineClassUnder("Revoked",runtime.getObject(),X509REVOKED_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("RevokedError",openSSLError,openSSLError.getAllocator()); + + cX509Rev.defineAnnotatedMethods(X509Revoked.class); + } + + private IRubyObject serial; + private IRubyObject extensions; + private IRubyObject time; + + public X509Revoked(Ruby runtime, RubyClass type) { + super(runtime,type); + } + + @JRubyMethod(name="initialize",rest=true,frame=true) + public IRubyObject _initialize(IRubyObject[] args, Block unusedBlock) { + serial = getRuntime().getNil(); + time = getRuntime().getNil(); + extensions = getRuntime().newArray(); + return this; + } + + @JRubyMethod + public IRubyObject serial() { + return this.serial; + } + + @JRubyMethod(name="serial=") + public IRubyObject set_serial(IRubyObject val) { + this.serial = val; + return val; + } + + @JRubyMethod + public IRubyObject time() { + return this.time; + } + + @JRubyMethod(name="time=") + public IRubyObject set_time(IRubyObject val) { + this.time = val; + return val; + } + + @JRubyMethod + public IRubyObject extensions() { + return this.extensions; + } + + @JRubyMethod(name="extensions=") + public IRubyObject set_extensions(IRubyObject val) { + this.extensions = val; + return val; + } + + @JRubyMethod + public IRubyObject add_extension(IRubyObject val) { + this.extensions.callMethod(getRuntime().getCurrentContext(),"<<",val); + return val; + } +}// X509Revoked diff --git a/src/org/jruby/ext/openssl/X509Store.java b/src/org/jruby/ext/openssl/X509Store.java new file mode 100644 index 00000000000..b7fac2498e4 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509Store.java @@ -0,0 +1,247 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import org.jruby.Ruby; +import org.jruby.RubyBoolean; +import org.jruby.RubyClass; +import org.jruby.RubyFixnum; +import org.jruby.RubyHash; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.ext.openssl.x509store.Store; +import org.jruby.ext.openssl.x509store.StoreContext; +import org.jruby.ext.openssl.x509store.X509Utils; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.ThreadContext; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class X509Store extends RubyObject { + private static final long serialVersionUID = 7987156710610206194L; + + private static ObjectAllocator X509STORE_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509Store(runtime, klass); + } + }; + + public static void createX509Store(Ruby runtime, RubyModule mX509) { + ThreadContext context = runtime.getCurrentContext(); + RubyClass cX509Store = mX509.defineClassUnder("Store",runtime.getObject(),X509STORE_ALLOCATOR); + RubyClass openSSLError = runtime.getModule("OpenSSL").getClass("OpenSSLError"); + mX509.defineClassUnder("StoreError",openSSLError,openSSLError.getAllocator()); + cX509Store.addReadWriteAttribute(context, "verify_callback"); + cX509Store.addReadWriteAttribute(context, "error"); + cX509Store.addReadWriteAttribute(context, "error_string"); + cX509Store.addReadWriteAttribute(context, "chain"); + + cX509Store.defineAnnotatedMethods(X509Store.class); + + X509StoreCtx.createX509StoreCtx(runtime, mX509); + } + + private RubyClass cStoreError; + private RubyClass cStoreContext; + + public X509Store(Ruby runtime, RubyClass type) { + super(runtime,type); + store = new Store(); + cStoreError = Utils.getClassFromPath(runtime, "OpenSSL::X509::StoreError"); + cStoreContext = Utils.getClassFromPath(runtime, "OpenSSL::X509::StoreContext"); + } + + private Store store; + + Store getStore() { + return store; + } + + private void raise(String msg) { + throw new RaiseException(getRuntime(),cStoreError, msg, true); + } + + @JRubyMethod(name="initialize", rest=true, frame=true) + public IRubyObject _initialize(IRubyObject[] args, Block block) { + store.setVerifyCallbackFunction(ossl_verify_cb); + this.set_verify_callback(getRuntime().getNil()); + this.setInstanceVariable("@flags",RubyFixnum.zero(getRuntime())); + this.setInstanceVariable("@purpose",RubyFixnum.zero(getRuntime())); + this.setInstanceVariable("@trust",RubyFixnum.zero(getRuntime())); + + this.setInstanceVariable("@error",getRuntime().getNil()); + this.setInstanceVariable("@error_string",getRuntime().getNil()); + this.setInstanceVariable("@chain",getRuntime().getNil()); + this.setInstanceVariable("@time",getRuntime().getNil()); + return this; + } + + @JRubyMethod(name="verify_callback=") + public IRubyObject set_verify_callback(IRubyObject cb) { + store.setExtraData(1, cb); + this.setInstanceVariable("@verify_callback", cb); + return cb; + } + + @JRubyMethod(name="flags=") + public IRubyObject set_flags(IRubyObject arg) { + store.setFlags(RubyNumeric.fix2long(arg)); + return arg; + } + + @JRubyMethod(name="purpose=") + public IRubyObject set_purpose(IRubyObject arg) { + store.setPurpose(RubyNumeric.fix2int(arg)); + return arg; + } + + @JRubyMethod(name="trust=") + public IRubyObject set_trust(IRubyObject arg) { + store.setTrust(RubyNumeric.fix2int(arg)); + return arg; + } + + @JRubyMethod(name="time=") + public IRubyObject set_time(IRubyObject arg) { + setInstanceVariable("@time",arg); + return arg; + } + + @JRubyMethod + public IRubyObject add_path(IRubyObject arg) { + getRuntime().getWarnings().warn("unimplemented method called: Store#add_path"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject add_file(IRubyObject arg) { + String file = arg.toString(); + try { + store.loadLocations(file, null); + } catch (Exception e) { + raise("loading file failed: " + e.getMessage()); + } + return this; + } + + @JRubyMethod + public IRubyObject set_default_paths() { + try { + RubyHash env = (RubyHash)getRuntime().getObject().fastGetConstant("ENV"); + String file = (String)env.get(getRuntime().newString(X509Utils.getDefaultCertificateFileEnvironment())); + store.loadLocations(file, null); + String path = (String)env.get(getRuntime().newString(X509Utils.getDefaultCertificateDirectoryEnvironment())); + store.loadLocations(null, path); + } + catch(Exception e) { + raise("setting default path failed: " + e.getMessage()); + } + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject add_cert(IRubyObject _cert) { + X509AuxCertificate cert = (_cert instanceof X509Cert) ? ((X509Cert)_cert).getAuxCert() : (X509AuxCertificate)null; + if(store.addCertificate(cert) != 1) { + raise(null); + } + return this; + } + + @JRubyMethod + public IRubyObject add_crl(IRubyObject arg) { + java.security.cert.X509CRL crl = (arg instanceof X509CRL) ? ((X509CRL)arg).getCRL() : null; + if(store.addCRL(crl) != 1) { + raise(null); + } + return this; + } + + @JRubyMethod(rest=true, frame=true) + public IRubyObject verify(IRubyObject[] args, Block block) { + IRubyObject cert, chain; + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,1,2) == 2) { + chain = args[1]; + } else { + chain = getRuntime().getNil(); + } + cert = args[0]; + IRubyObject proc, result; + X509StoreCtx ctx = (X509StoreCtx)cStoreContext.callMethod(getRuntime().getCurrentContext(),"new",new IRubyObject[]{this,cert,chain}); + if (block.isGiven()) { + proc = getRuntime().newProc(Block.Type.PROC, block); + } else { + proc = getInstanceVariable("@verify_callback"); + } + ctx.setInstanceVariable("@verify_callback",proc); + result = ctx.callMethod(getRuntime().getCurrentContext(),"verify"); + this.setInstanceVariable("@error",ctx.error()); + this.setInstanceVariable("@error_string",ctx.error_string()); + this.setInstanceVariable("@chain",ctx.chain()); + return result; + } + + public final static Store.VerifyCallbackFunction ossl_verify_cb = new Store.VerifyCallbackFunction() { + + public int call(Object a1, Object a2) throws Exception { + StoreContext ctx = (StoreContext) a2; + int ok = ((Integer) a1).intValue(); + IRubyObject proc = (IRubyObject) ctx.getExtraData(1); + if (null == proc) { + proc = (IRubyObject) ctx.ctx.getExtraData(0); + } + if (null == proc) { + return ok; + } + if (!proc.isNil()) { + Ruby rt = proc.getRuntime(); + RubyClass cStoreContext = Utils.getClassFromPath(rt, "OpenSSL::X509::StoreContext"); + X509StoreCtx rctx = new X509StoreCtx(rt, cStoreContext, ctx); + RubyBoolean rok = rt.newBoolean(ok != 0); + IRubyObject ret = proc.callMethod(rt.getCurrentContext(), "call", new IRubyObject[]{rok, rctx}); + if (ret.isTrue()) { + ctx.setError(X509Utils.V_OK); + ok = 1; + } else { + if (ctx.getError() == X509Utils.V_OK) { + ctx.setError(X509Utils.V_ERR_CERT_REJECTED); + } + ok = 0; + } + } + return ok; + } + }; +}// X509Store diff --git a/src/org/jruby/ext/openssl/X509StoreCtx.java b/src/org/jruby/ext/openssl/X509StoreCtx.java new file mode 100644 index 00000000000..e84e786f8a9 --- /dev/null +++ b/src/org/jruby/ext/openssl/X509StoreCtx.java @@ -0,0 +1,228 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006, 2007 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl; + +import java.security.cert.CertificateEncodingException; +import java.util.ArrayList; +import java.util.List; + +import org.jruby.Ruby; +import org.jruby.RubyArray; +import org.jruby.RubyClass; +import org.jruby.RubyModule; +import org.jruby.RubyNumeric; +import org.jruby.RubyObject; +import org.jruby.RubyObjectAdapter; +import org.jruby.RubyString; +import org.jruby.RubyTime; +import org.jruby.anno.JRubyMethod; +import org.jruby.exceptions.RaiseException; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.ext.openssl.x509store.Store; +import org.jruby.ext.openssl.x509store.StoreContext; +import org.jruby.javasupport.JavaEmbedUtils; +import org.jruby.runtime.Block; +import org.jruby.runtime.ObjectAllocator; +import org.jruby.runtime.builtin.IRubyObject; + +/** + * @author Ola Bini + */ +public class X509StoreCtx extends RubyObject { + private static final long serialVersionUID = 2029690161026120504L; + + private static ObjectAllocator X509STORECTX_ALLOCATOR = new ObjectAllocator() { + public IRubyObject allocate(Ruby runtime, RubyClass klass) { + return new X509StoreCtx(runtime, klass); + } + }; + + private static RubyObjectAdapter api = JavaEmbedUtils.newObjectAdapter(); + + public static void createX509StoreCtx(Ruby runtime, RubyModule mX509) { + RubyClass cX509StoreContext = mX509.defineClassUnder("StoreContext",runtime.getObject(),X509STORECTX_ALLOCATOR); + cX509StoreContext.defineAnnotatedMethods(X509StoreCtx.class); + } + + private StoreContext ctx; + private RubyClass cX509Cert; + + public X509StoreCtx(Ruby runtime, RubyClass type) { + super(runtime, type); + ctx = new StoreContext(); + cX509Cert = Utils.getClassFromPath(runtime, "OpenSSL::X509::Certificate"); + } + + // constructor for creating callback parameter object of verify_cb + X509StoreCtx(Ruby runtime, RubyClass type, StoreContext ctx) { + super(runtime, type); + this.ctx = ctx; + cX509Cert = Utils.getClassFromPath(runtime, "OpenSSL::X509::Certificate"); + } + + @JRubyMethod(name="initialize", rest=true, frame=true) + public IRubyObject _initialize(IRubyObject[] args, Block block) { + IRubyObject store; + IRubyObject cert = getRuntime().getNil(); + IRubyObject chain = getRuntime().getNil(); + Store x509st; + X509AuxCertificate x509 = null; + List x509s = new ArrayList(); + + if(org.jruby.runtime.Arity.checkArgumentCount(getRuntime(),args,1,3) > 1) { + cert = args[1]; + } + if(args.length > 2) { + chain = args[2]; + } + store = args[0]; + x509st = ((X509Store)store).getStore(); + if(!cert.isNil()) { + x509 = ((X509Cert)cert).getAuxCert(); + } + if(!chain.isNil()) { + x509s = new ArrayList(); + for (IRubyObject obj : ((RubyArray)chain).toJavaArray()) { + x509s.add(((X509Cert)obj).getAuxCert()); + } + } + if(ctx.init(x509st,x509,x509s) != 1) { + throw newStoreError(getRuntime(), null); + } + IRubyObject t = api.getInstanceVariable(store,"@time"); + if(!t.isNil()) { + set_time(t); + } + api.setInstanceVariable(this, "@verify_callback", api.getInstanceVariable(store, "@verify_callback")); + api.setInstanceVariable(this, "@cert", cert); + return this; + } + + @JRubyMethod + public IRubyObject verify() { + ctx.setExtraData(1, getInstanceVariable("@verify_callback")); + try { + int result = ctx.verifyCertificate(); + return result != 0 ? getRuntime().getTrue() : getRuntime().getFalse(); + } catch (Exception e) { + // TODO: define suitable exception for jopenssl and catch it. + throw newStoreError(getRuntime(), e.getMessage()); + } + } + + @JRubyMethod + public IRubyObject chain() { + List chain = ctx.getChain(); + if (chain == null) { + return getRuntime().getNil(); + } + List ary = new ArrayList(); + try { + for (X509AuxCertificate x509 : chain) { + ary.add(cX509Cert.callMethod(getRuntime().getCurrentContext(), "new", RubyString.newString(getRuntime(), x509.getEncoded()))); + } + } catch (CertificateEncodingException cee) { + throw newStoreError(getRuntime(), cee.getMessage()); + } + return getRuntime().newArray(ary); + } + + @JRubyMethod + public IRubyObject error() { + return getRuntime().newFixnum(ctx.getError()); + } + + @JRubyMethod(name="error=") + public IRubyObject set_error(IRubyObject arg) { + ctx.setError(RubyNumeric.fix2int(arg)); + return arg; + } + + @JRubyMethod + public IRubyObject error_string() { + int err = ctx.getError(); + return getRuntime().newString(org.jruby.ext.openssl.x509store.X509Utils.verifyCertificateErrorString(err)); + } + + @JRubyMethod + public IRubyObject error_depth() { + System.err.println("WARNING: unimplemented method called: StoreContext#error_depth"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject current_cert() { + Ruby rt = getRuntime(); + X509AuxCertificate x509 = ctx.getCurrentCertificate(); + try { + return cX509Cert.callMethod(rt.getCurrentContext(), "new", RubyString.newString(rt, x509.getEncoded())); + } catch (CertificateEncodingException cee) { + throw newStoreError(getRuntime(), cee.getMessage()); + } + } + + @JRubyMethod + public IRubyObject current_crl() { + System.err.println("WARNING: unimplemented method called: StoreContext#current_crl"); + return getRuntime().getNil(); + } + + @JRubyMethod + public IRubyObject cleanup() { + System.err.println("WARNING: unimplemented method called: StoreContext#cleanup"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="flags=") + public IRubyObject set_flags(IRubyObject arg) { + System.err.println("WARNING: unimplemented method called: StoreContext#set_flags"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="purpose=") + public IRubyObject set_purpose(IRubyObject arg) { + System.err.println("WARNING: unimplemented method called: StoreContext#set_purpose"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="trust=") + public IRubyObject set_trust(IRubyObject arg) { + System.err.println("WARNING: unimplemented method called: StoreContext#set_trust"); + return getRuntime().getNil(); + } + + @JRubyMethod(name="time=") + public IRubyObject set_time(IRubyObject arg) { + ctx.setTime(0,((RubyTime)arg).getJavaDate()); + return arg; + } + + private static RaiseException newStoreError(Ruby runtime, String message) { + return Utils.newError(runtime, "OpenSSL::X509::StoreError", message); + } +}// X509StoreCtx diff --git a/src/org/jruby/ext/openssl/impl/ASN1Registry.java b/src/org/jruby/ext/openssl/impl/ASN1Registry.java new file mode 100644 index 00000000000..e489d0044ac --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/ASN1Registry.java @@ -0,0 +1,5151 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.util.HashMap; +import java.util.Map; +import org.bouncycastle.asn1.DERObjectIdentifier; + +/** + * + * @author Ola Bini + */ +public class ASN1Registry { + @SuppressWarnings("unchecked") + private static Map SYM_TO_OID = new HashMap(org.bouncycastle.asn1.x509.X509Name.DefaultLookUp); + @SuppressWarnings("unchecked") + private static Map OID_TO_SYM = new HashMap(org.bouncycastle.asn1.x509.X509Name.DefaultSymbols); + private static Map OID_TO_NID = new HashMap(); + private static Map NID_TO_OID = new HashMap(); + private static Map NID_TO_SN = new HashMap(); + private static Map NID_TO_LN = new HashMap(); + + public static Integer obj2nid(String oid) { + return obj2nid(new DERObjectIdentifier(oid)); + } + + public static String ln2oid(String ln) { + return SYM_TO_OID.get(ln.toLowerCase()).getId(); + } + + public static Integer obj2nid(DERObjectIdentifier oid) { + return OID_TO_NID.get(oid); + } + + public static String o2a(String oid) { + return o2a(new DERObjectIdentifier(oid)); + } + + public static String o2a(DERObjectIdentifier obj) { + Integer nid = obj2nid(obj); + String one = NID_TO_LN.get(nid); + if(one == null) { + one = NID_TO_SN.get(nid); + } + return one; + } + + public static DERObjectIdentifier sym2oid(String name) { + return SYM_TO_OID.get(name.toLowerCase()); + } + + public static int sym2nid(String name) { + return OID_TO_NID.get(SYM_TO_OID.get(name.toLowerCase())); + } + + public static String nid2ln(int nid) { + return nid2ln(Integer.valueOf(nid)); + } + + public static DERObjectIdentifier nid2obj(int nid) { + return NID_TO_OID.get(nid); + } + + public static String nid2ln(Integer nid) { + return NID_TO_LN.get(nid); + } + + static void addObject(int nid, String sn, String ln, String oid) { + if(null != oid && oid.length() > 2 && (null != sn || null != ln)) { + DERObjectIdentifier ident = new DERObjectIdentifier(oid); + if(sn != null) { + SYM_TO_OID.put(sn.toLowerCase(),ident); + } + if(ln != null) { + SYM_TO_OID.put(ln.toLowerCase(),ident); + } + OID_TO_SYM.put(ident,sn == null ? ln : sn); + OID_TO_NID.put(ident,nid); + NID_TO_OID.put(nid,ident); + NID_TO_SN.put(nid,sn); + NID_TO_LN.put(nid,ln); + } + } + + + public final static int NID_id_pkix = 127; + public final static String SN_id_pkix = "PKIX"; + public final static String OBJ_id_pkix = "1.3.6.1.5.5.7"; + + public final static int NID_id_ad = 176; + public final static String SN_id_ad = "id-ad"; + public final static String OBJ_id_ad = OBJ_id_pkix + ".48"; + + public final static int NID_ad_OCSP = 178; + public final static String SN_ad_OCSP = "OCSP"; + public final static String LN_ad_OCSP = "OCSP"; + public final static String OBJ_ad_OCSP = OBJ_id_ad + ".1"; + + public final static String OBJ_id_pkix_OCSP = OBJ_ad_OCSP; + + public final static int NID_iso = 181; + public final static String SN_iso = "ISO"; + public final static String LN_iso = "iso"; + public final static String OBJ_iso = "1"; + + public final static int NID_org = 379; + public final static String SN_org = "ORG"; + public final static String LN_org = "org"; + public final static String OBJ_org = OBJ_iso + ".3"; + + public final static int NID_dod = 380; + public final static String SN_dod = "DOD"; + public final static String LN_dod = "dod"; + public final static String OBJ_dod = OBJ_org + ".6"; + + public final static int NID_iana = 381; + public final static String SN_iana = "IANA"; + public final static String LN_iana = "iana"; + public final static String OBJ_iana = OBJ_dod + ".1"; + + public final static String OBJ_internet = OBJ_iana; + + public final static String OBJ_csor = "2.16.840.1.101.3"; + + public final static int NID_member_body = 182; + public final static String SN_member_body = "member-body"; + public final static String LN_member_body = "ISO Member Body"; + public final static String OBJ_member_body = OBJ_iso + ".2"; + + public final static int NID_ISO_US = 183; + public final static String SN_ISO_US = "ISO-US"; + public final static String LN_ISO_US = "ISO US Member Body"; + public final static String OBJ_ISO_US = OBJ_member_body + ".840"; + + public final static int NID_rsadsi = 1; + public final static String SN_rsadsi = "rsadsi"; + public final static String LN_rsadsi = "RSA Data Security, Inc."; + public final static String OBJ_rsadsi = OBJ_ISO_US + ".113549"; + + public final static int NID_pkcs = 2; + public final static String SN_pkcs = "pkcs"; + public final static String LN_pkcs = "RSA Data Security, Inc. PKCS"; + public final static String OBJ_pkcs = OBJ_rsadsi + ".1"; + + public final static String OBJ_pkcs12 = OBJ_pkcs + ".12"; + + public final static int NID_X9_57 = 184; + public final static String SN_X9_57 = "X9-57"; + public final static String LN_X9_57 = "X9.57"; + public final static String OBJ_X9_57 = OBJ_ISO_US + ".10040"; + + public final static int NID_ansi_X9_62 = 405; + public final static String SN_ansi_X9_62 = "ansi-X9-62"; + public final static String LN_ansi_X9_62 = "ANSI X9.62"; + public final static String OBJ_ansi_X9_62 = OBJ_ISO_US + ".10045"; + + public final static String OBJ_holdInstruction = OBJ_X9_57 + ".2"; + + public final static String OBJ_X9_62_id_fieldType = OBJ_ansi_X9_62 + ".1"; + + public final static String OBJ_X9_62_ellipticCurve = OBJ_ansi_X9_62 + ".3"; + + public final static String OBJ_X9_62_id_publicKeyType = OBJ_ansi_X9_62 + ".2"; + + public final static String OBJ_X9_62_id_ecSigType = OBJ_ansi_X9_62 + ".4"; + + public final static String OBJ_X9_62_primeCurve = OBJ_X9_62_ellipticCurve + ".1"; + + public final static String OBJ_X9_62_c_TwoCurve = OBJ_X9_62_ellipticCurve + ".0"; + + public final static String OBJ_nistAlgorithms = OBJ_csor + ".4"; + + public final static int NID_joint_iso_itu_t = 646; + public final static String SN_joint_iso_itu_t = "JOINT-ISO-ITU-T"; + public final static String LN_joint_iso_itu_t = "joint-iso-itu-t"; + public final static String OBJ_joint_iso_itu_t = "2"; + + public final static int NID_international_organizations = 647; + public final static String SN_international_organizations = "international-organizations"; + public final static String LN_international_organizations = "International Organizations"; + public final static String OBJ_international_organizations = OBJ_joint_iso_itu_t + ".23"; + + public final static int NID_wap = 678; + public final static String SN_wap = "wap"; + public final static String OBJ_wap = OBJ_international_organizations + ".43"; + + public final static int NID_wap_wsg = 679; + public final static String SN_wap_wsg = "wap-wsg"; + public final static String OBJ_wap_wsg = OBJ_wap + ".13"; + + public final static String OBJ_wap_wsg_idm_ecid = OBJ_wap_wsg + ".4"; + + public final static String OBJ_nist_hashalgs = OBJ_nistAlgorithms + ".2"; + + public final static String OBJ_pkcs12_Version1 = OBJ_pkcs12 + ".10"; + + public final static int NID_pkcs9 = 47; + public final static String SN_pkcs9 = "pkcs9"; + public final static String OBJ_pkcs9 = OBJ_pkcs + ".9"; + + public final static String OBJ_certTypes = OBJ_pkcs9 + ".22"; + + public final static String OBJ_crlTypes = OBJ_pkcs9 + ".23"; + + public final static int NID_identified_organization = 676; + public final static String SN_identified_organization = "identified-organization"; + public final static String OBJ_identified_organization = OBJ_iso + ".3"; + + public final static int NID_certicom_arc = 677; + public final static String SN_certicom_arc = "certicom-arc"; + public final static String OBJ_certicom_arc = OBJ_identified_organization + ".132"; + + public final static String OBJ_secg_ellipticCurve = OBJ_certicom_arc + ".0"; + + public final static String OBJ_aes = OBJ_nistAlgorithms + ".1"; + + public final static String OBJ_pkcs12_BagIds = OBJ_pkcs12_Version1 + ".1"; + + public final static String OBJ_dsa_with_sha2 = OBJ_nistAlgorithms + ".3"; + + public final static int NID_undef = 0; + public final static String SN_undef = "UNDEF"; + public final static String LN_undef = "undefined"; + public final static String OBJ_undef = "0"; + + public final static int NID_md2 = 3; + public final static String SN_md2 = "MD2"; + public final static String LN_md2 = "md2"; + public final static String OBJ_md2 = OBJ_rsadsi + ".2.2"; + + public final static int NID_md5 = 4; + public final static String SN_md5 = "MD5"; + public final static String LN_md5 = "md5"; + public final static String OBJ_md5 = OBJ_rsadsi + ".2.5"; + + public final static int NID_rc4 = 5; + public final static String SN_rc4 = "RC4"; + public final static String LN_rc4 = "rc4"; + public final static String OBJ_rc4 = OBJ_rsadsi + ".3.4"; + + public final static int NID_pkcs1 = 186; + public final static String SN_pkcs1 = "pkcs1"; + public final static String OBJ_pkcs1 = OBJ_pkcs + ".1"; + + public final static int NID_rsaEncryption = 6; + public final static String LN_rsaEncryption = "rsaEncryption"; + public final static String OBJ_rsaEncryption = OBJ_pkcs1 + ".1"; + + public final static int NID_md2WithRSAEncryption = 7; + public final static String SN_md2WithRSAEncryption = "RSA-MD2"; + public final static String LN_md2WithRSAEncryption = "md2WithRSAEncryption"; + public final static String OBJ_md2WithRSAEncryption = OBJ_pkcs1 + ".2"; + + public final static int NID_md5WithRSAEncryption = 8; + public final static String SN_md5WithRSAEncryption = "RSA-MD5"; + public final static String LN_md5WithRSAEncryption = "md5WithRSAEncryption"; + public final static String OBJ_md5WithRSAEncryption = OBJ_pkcs1 + ".4"; + + public final static int NID_pkcs5 = 187; + public final static String SN_pkcs5 = "pkcs5"; + public final static String OBJ_pkcs5 = OBJ_pkcs + ".5"; + + public final static int NID_pbeWithMD2AndDES_CBC = 9; + public final static String SN_pbeWithMD2AndDES_CBC = "PBE-MD2-DES"; + public final static String LN_pbeWithMD2AndDES_CBC = "pbeWithMD2AndDES-CBC"; + public final static String OBJ_pbeWithMD2AndDES_CBC = OBJ_pkcs5 + ".1"; + + public final static int NID_pbeWithMD5AndDES_CBC = 10; + public final static String SN_pbeWithMD5AndDES_CBC = "PBE-MD5-DES"; + public final static String LN_pbeWithMD5AndDES_CBC = "pbeWithMD5AndDES-CBC"; + public final static String OBJ_pbeWithMD5AndDES_CBC = OBJ_pkcs5 + ".3"; + + public final static int NID_X500 = 11; + public final static String SN_X500 = "X500"; + public final static String LN_X500 = "directory services (X.500)"; + public final static String OBJ_X500 = "2.5"; + + public final static int NID_X509 = 12; + public final static String SN_X509 = "X509"; + public final static String OBJ_X509 = OBJ_X500 + ".4"; + + public final static int NID_commonName = 13; + public final static String SN_commonName = "CN"; + public final static String LN_commonName = "commonName"; + public final static String OBJ_commonName = OBJ_X509 + ".3"; + + public final static int NID_countryName = 14; + public final static String SN_countryName = "C"; + public final static String LN_countryName = "countryName"; + public final static String OBJ_countryName = OBJ_X509 + ".6"; + + public final static int NID_localityName = 15; + public final static String SN_localityName = "L"; + public final static String LN_localityName = "localityName"; + public final static String OBJ_localityName = OBJ_X509 + ".7"; + + public final static int NID_stateOrProvinceName = 16; + public final static String SN_stateOrProvinceName = "ST"; + public final static String LN_stateOrProvinceName = "stateOrProvinceName"; + public final static String OBJ_stateOrProvinceName = OBJ_X509 + ".8"; + + public final static int NID_organizationName = 17; + public final static String SN_organizationName = "O"; + public final static String LN_organizationName = "organizationName"; + public final static String OBJ_organizationName = OBJ_X509 + ".10"; + + public final static int NID_organizationalUnitName = 18; + public final static String SN_organizationalUnitName = "OU"; + public final static String LN_organizationalUnitName = "organizationalUnitName"; + public final static String OBJ_organizationalUnitName = OBJ_X509 + ".11"; + + public final static int NID_X500algorithms = 378; + public final static String SN_X500algorithms = "X500algorithms"; + public final static String LN_X500algorithms = "directory services - algorithms"; + public final static String OBJ_X500algorithms = OBJ_X500 + ".8"; + + public final static int NID_rsa = 19; + public final static String SN_rsa = "RSA"; + public final static String LN_rsa = "rsa"; + public final static String OBJ_rsa = OBJ_X500algorithms + ".1.1"; + + public final static int NID_pkcs7 = 20; + public final static String SN_pkcs7 = "pkcs7"; + public final static String OBJ_pkcs7 = OBJ_pkcs + ".7"; + + public final static int NID_pkcs7_data = 21; + public final static String LN_pkcs7_data = "pkcs7-data"; + public final static String OBJ_pkcs7_data = OBJ_pkcs7 + ".1"; + + public final static int NID_pkcs7_signed = 22; + public final static String LN_pkcs7_signed = "pkcs7-signedData"; + public final static String OBJ_pkcs7_signed = OBJ_pkcs7 + ".2"; + + public final static int NID_pkcs7_enveloped = 23; + public final static String LN_pkcs7_enveloped = "pkcs7-envelopedData"; + public final static String OBJ_pkcs7_enveloped = OBJ_pkcs7 + ".3"; + + public final static int NID_pkcs7_signedAndEnveloped = 24; + public final static String LN_pkcs7_signedAndEnveloped = "pkcs7-signedAndEnvelopedData"; + public final static String OBJ_pkcs7_signedAndEnveloped = OBJ_pkcs7 + ".4"; + + public final static int NID_pkcs7_digest = 25; + public final static String LN_pkcs7_digest = "pkcs7-digestData"; + public final static String OBJ_pkcs7_digest = OBJ_pkcs7 + ".5"; + + public final static int NID_pkcs7_encrypted = 26; + public final static String LN_pkcs7_encrypted = "pkcs7-encryptedData"; + public final static String OBJ_pkcs7_encrypted = OBJ_pkcs7 + ".6"; + + public final static int NID_pkcs3 = 27; + public final static String SN_pkcs3 = "pkcs3"; + public final static String OBJ_pkcs3 = OBJ_pkcs + ".3"; + + public final static int NID_dhKeyAgreement = 28; + public final static String LN_dhKeyAgreement = "dhKeyAgreement"; + public final static String OBJ_dhKeyAgreement = OBJ_pkcs3 + ".1"; + + public final static int NID_algorithm = 376; + public final static String SN_algorithm = "algorithm"; + public final static String LN_algorithm = "algorithm"; + public final static String OBJ_algorithm = "1.3.14.3.2"; + + public final static int NID_des_ecb = 29; + public final static String SN_des_ecb = "DES-ECB"; + public final static String LN_des_ecb = "des-ecb"; + public final static String OBJ_des_ecb = OBJ_algorithm + ".6"; + + public final static int NID_des_cfb64 = 30; + public final static String SN_des_cfb64 = "DES-CFB"; + public final static String LN_des_cfb64 = "des-cfb"; + public final static String OBJ_des_cfb64 = OBJ_algorithm + ".9"; + + public final static int NID_des_cbc = 31; + public final static String SN_des_cbc = "DES-CBC"; + public final static String LN_des_cbc = "des-cbc"; + public final static String OBJ_des_cbc = OBJ_algorithm + ".7"; + + public final static int NID_des_ede_ecb = 32; + public final static String SN_des_ede_ecb = "DES-EDE"; + public final static String LN_des_ede_ecb = "des-ede"; + public final static String OBJ_des_ede_ecb = OBJ_algorithm + ".17"; + + public final static int NID_des_ede3_ecb = 33; + public final static String SN_des_ede3_ecb = "DES-EDE3"; + public final static String LN_des_ede3_ecb = "des-ede3"; + + public final static int NID_idea_cbc = 34; + public final static String SN_idea_cbc = "IDEA-CBC"; + public final static String LN_idea_cbc = "idea-cbc"; + public final static String OBJ_idea_cbc = "1.3.6.1.4.1.188.7.1.1.2"; + + public final static int NID_idea_cfb64 = 35; + public final static String SN_idea_cfb64 = "IDEA-CFB"; + public final static String LN_idea_cfb64 = "idea-cfb"; + + public final static int NID_idea_ecb = 36; + public final static String SN_idea_ecb = "IDEA-ECB"; + public final static String LN_idea_ecb = "idea-ecb"; + + public final static int NID_rc2_cbc = 37; + public final static String SN_rc2_cbc = "RC2-CBC"; + public final static String LN_rc2_cbc = "rc2-cbc"; + public final static String OBJ_rc2_cbc = OBJ_rsadsi + ".3.2"; + + public final static int NID_rc2_ecb = 38; + public final static String SN_rc2_ecb = "RC2-ECB"; + public final static String LN_rc2_ecb = "rc2-ecb"; + + public final static int NID_rc2_cfb64 = 39; + public final static String SN_rc2_cfb64 = "RC2-CFB"; + public final static String LN_rc2_cfb64 = "rc2-cfb"; + + public final static int NID_rc2_ofb64 = 40; + public final static String SN_rc2_ofb64 = "RC2-OFB"; + public final static String LN_rc2_ofb64 = "rc2-ofb"; + + public final static int NID_sha = 41; + public final static String SN_sha = "SHA"; + public final static String LN_sha = "sha"; + public final static String OBJ_sha = OBJ_algorithm + ".18"; + + public final static int NID_shaWithRSAEncryption = 42; + public final static String SN_shaWithRSAEncryption = "RSA-SHA"; + public final static String LN_shaWithRSAEncryption = "shaWithRSAEncryption"; + public final static String OBJ_shaWithRSAEncryption = OBJ_algorithm + ".15"; + + public final static int NID_des_ede_cbc = 43; + public final static String SN_des_ede_cbc = "DES-EDE-CBC"; + public final static String LN_des_ede_cbc = "des-ede-cbc"; + + public final static int NID_des_ede3_cbc = 44; + public final static String SN_des_ede3_cbc = "DES-EDE3-CBC"; + public final static String LN_des_ede3_cbc = "des-ede3-cbc"; + public final static String OBJ_des_ede3_cbc = OBJ_rsadsi + ".3.7"; + + public final static int NID_des_ofb64 = 45; + public final static String SN_des_ofb64 = "DES-OFB"; + public final static String LN_des_ofb64 = "des-ofb"; + public final static String OBJ_des_ofb64 = OBJ_algorithm + ".8"; + + public final static int NID_idea_ofb64 = 46; + public final static String SN_idea_ofb64 = "IDEA-OFB"; + public final static String LN_idea_ofb64 = "idea-ofb"; + + public final static int NID_pkcs9_emailAddress = 48; + public final static String LN_pkcs9_emailAddress = "emailAddress"; + public final static String OBJ_pkcs9_emailAddress = OBJ_pkcs9 + ".1"; + + public final static int NID_pkcs9_unstructuredName = 49; + public final static String LN_pkcs9_unstructuredName = "unstructuredName"; + public final static String OBJ_pkcs9_unstructuredName = OBJ_pkcs9 + ".2"; + + public final static int NID_pkcs9_contentType = 50; + public final static String LN_pkcs9_contentType = "contentType"; + public final static String OBJ_pkcs9_contentType = OBJ_pkcs9 + ".3"; + + public final static int NID_pkcs9_messageDigest = 51; + public final static String LN_pkcs9_messageDigest = "messageDigest"; + public final static String OBJ_pkcs9_messageDigest = OBJ_pkcs9 + ".4"; + + public final static int NID_pkcs9_signingTime = 52; + public final static String LN_pkcs9_signingTime = "signingTime"; + public final static String OBJ_pkcs9_signingTime = OBJ_pkcs9 + ".5"; + + public final static int NID_pkcs9_countersignature = 53; + public final static String LN_pkcs9_countersignature = "countersignature"; + public final static String OBJ_pkcs9_countersignature = OBJ_pkcs9 + ".6"; + + public final static int NID_pkcs9_challengePassword = 54; + public final static String LN_pkcs9_challengePassword = "challengePassword"; + public final static String OBJ_pkcs9_challengePassword = OBJ_pkcs9 + ".7"; + + public final static int NID_pkcs9_unstructuredAddress = 55; + public final static String LN_pkcs9_unstructuredAddress = "unstructuredAddress"; + public final static String OBJ_pkcs9_unstructuredAddress = OBJ_pkcs9 + ".8"; + + public final static int NID_pkcs9_extCertAttributes = 56; + public final static String LN_pkcs9_extCertAttributes = "extendedCertificateAttributes"; + public final static String OBJ_pkcs9_extCertAttributes = OBJ_pkcs9 + ".9"; + + public final static int NID_netscape = 57; + public final static String SN_netscape = "Netscape"; + public final static String LN_netscape = "Netscape Communications Corp."; + public final static String OBJ_netscape = "2.16.840.1.113730"; + + public final static int NID_netscape_cert_extension = 58; + public final static String SN_netscape_cert_extension = "nsCertExt"; + public final static String LN_netscape_cert_extension = "Netscape Certificate Extension"; + public final static String OBJ_netscape_cert_extension = OBJ_netscape + ".1"; + + public final static int NID_netscape_data_type = 59; + public final static String SN_netscape_data_type = "nsDataType"; + public final static String LN_netscape_data_type = "Netscape Data Type"; + public final static String OBJ_netscape_data_type = OBJ_netscape + ".2"; + + public final static int NID_des_ede_cfb64 = 60; + public final static String SN_des_ede_cfb64 = "DES-EDE-CFB"; + public final static String LN_des_ede_cfb64 = "des-ede-cfb"; + + public final static int NID_des_ede3_cfb64 = 61; + public final static String SN_des_ede3_cfb64 = "DES-EDE3-CFB"; + public final static String LN_des_ede3_cfb64 = "des-ede3-cfb"; + + public final static int NID_des_ede_ofb64 = 62; + public final static String SN_des_ede_ofb64 = "DES-EDE-OFB"; + public final static String LN_des_ede_ofb64 = "des-ede-ofb"; + + public final static int NID_des_ede3_ofb64 = 63; + public final static String SN_des_ede3_ofb64 = "DES-EDE3-OFB"; + public final static String LN_des_ede3_ofb64 = "des-ede3-ofb"; + + public final static int NID_sha1 = 64; + public final static String SN_sha1 = "SHA1"; + public final static String LN_sha1 = "sha1"; + public final static String OBJ_sha1 = OBJ_algorithm + ".26"; + + public final static int NID_sha1WithRSAEncryption = 65; + public final static String SN_sha1WithRSAEncryption = "RSA-SHA1"; + public final static String LN_sha1WithRSAEncryption = "sha1WithRSAEncryption"; + public final static String OBJ_sha1WithRSAEncryption = OBJ_pkcs1 + ".5"; + + public final static int NID_dsaWithSHA = 66; + public final static String SN_dsaWithSHA = "DSA-SHA"; + public final static String LN_dsaWithSHA = "dsaWithSHA"; + public final static String OBJ_dsaWithSHA = OBJ_algorithm + ".13"; + + public final static int NID_dsa_2 = 67; + public final static String SN_dsa_2 = "DSA-old"; + public final static String LN_dsa_2 = "dsaEncryption-old"; + public final static String OBJ_dsa_2 = OBJ_algorithm + ".12"; + + public final static int NID_pbeWithSHA1AndRC2_CBC = 68; + public final static String SN_pbeWithSHA1AndRC2_CBC = "PBE-SHA1-RC2-64"; + public final static String LN_pbeWithSHA1AndRC2_CBC = "pbeWithSHA1AndRC2-CBC"; + public final static String OBJ_pbeWithSHA1AndRC2_CBC = OBJ_pkcs5 + ".11"; + + public final static int NID_id_pbkdf2 = 69; + public final static String LN_id_pbkdf2 = "PBKDF2"; + public final static String OBJ_id_pbkdf2 = OBJ_pkcs5 + ".12"; + + public final static int NID_dsaWithSHA1_2 = 70; + public final static String SN_dsaWithSHA1_2 = "DSA-SHA1-old"; + public final static String LN_dsaWithSHA1_2 = "dsaWithSHA1-old"; + public final static String OBJ_dsaWithSHA1_2 = OBJ_algorithm + ".27"; + + public final static int NID_netscape_cert_type = 71; + public final static String SN_netscape_cert_type = "nsCertType"; + public final static String LN_netscape_cert_type = "Netscape Cert Type"; + public final static String OBJ_netscape_cert_type = OBJ_netscape_cert_extension + ".1"; + + public final static int NID_netscape_base_url = 72; + public final static String SN_netscape_base_url = "nsBaseUrl"; + public final static String LN_netscape_base_url = "Netscape Base Url"; + public final static String OBJ_netscape_base_url = OBJ_netscape_cert_extension + ".2"; + + public final static int NID_netscape_revocation_url = 73; + public final static String SN_netscape_revocation_url = "nsRevocationUrl"; + public final static String LN_netscape_revocation_url = "Netscape Revocation Url"; + public final static String OBJ_netscape_revocation_url = OBJ_netscape_cert_extension + ".3"; + + public final static int NID_netscape_ca_revocation_url = 74; + public final static String SN_netscape_ca_revocation_url = "nsCaRevocationUrl"; + public final static String LN_netscape_ca_revocation_url = "Netscape CA Revocation Url"; + public final static String OBJ_netscape_ca_revocation_url = OBJ_netscape_cert_extension + ".4"; + + public final static int NID_netscape_renewal_url = 75; + public final static String SN_netscape_renewal_url = "nsRenewalUrl"; + public final static String LN_netscape_renewal_url = "Netscape Renewal Url"; + public final static String OBJ_netscape_renewal_url = OBJ_netscape_cert_extension + ".7"; + + public final static int NID_netscape_ca_policy_url = 76; + public final static String SN_netscape_ca_policy_url = "nsCaPolicyUrl"; + public final static String LN_netscape_ca_policy_url = "Netscape CA Policy Url"; + public final static String OBJ_netscape_ca_policy_url = OBJ_netscape_cert_extension + ".8"; + + public final static int NID_netscape_ssl_server_name = 77; + public final static String SN_netscape_ssl_server_name = "nsSslServerName"; + public final static String LN_netscape_ssl_server_name = "Netscape SSL Server Name"; + public final static String OBJ_netscape_ssl_server_name = OBJ_netscape_cert_extension + ".12"; + + public final static int NID_netscape_comment = 78; + public final static String SN_netscape_comment = "nsComment"; + public final static String LN_netscape_comment = "Netscape Comment"; + public final static String OBJ_netscape_comment = OBJ_netscape_cert_extension + ".13"; + + public final static int NID_netscape_cert_sequence = 79; + public final static String SN_netscape_cert_sequence = "nsCertSequence"; + public final static String LN_netscape_cert_sequence = "Netscape Certificate Sequence"; + public final static String OBJ_netscape_cert_sequence = OBJ_netscape_data_type + ".5"; + + public final static int NID_desx_cbc = 80; + public final static String SN_desx_cbc = "DESX-CBC"; + public final static String LN_desx_cbc = "desx-cbc"; + + public final static int NID_id_ce = 81; + public final static String SN_id_ce = "id-ce"; + public final static String OBJ_id_ce = OBJ_X500 + ".29"; + + public final static int NID_subject_key_identifier = 82; + public final static String SN_subject_key_identifier = "subjectKeyIdentifier"; + public final static String LN_subject_key_identifier = "X509v3 Subject Key Identifier"; + public final static String OBJ_subject_key_identifier = OBJ_id_ce + ".14"; + + public final static int NID_key_usage = 83; + public final static String SN_key_usage = "keyUsage"; + public final static String LN_key_usage = "X509v3 Key Usage"; + public final static String OBJ_key_usage = OBJ_id_ce + ".15"; + + public final static int NID_private_key_usage_period = 84; + public final static String SN_private_key_usage_period = "privateKeyUsagePeriod"; + public final static String LN_private_key_usage_period = "X509v3 Private Key Usage Period"; + public final static String OBJ_private_key_usage_period = OBJ_id_ce + ".16"; + + public final static int NID_subject_alt_name = 85; + public final static String SN_subject_alt_name = "subjectAltName"; + public final static String LN_subject_alt_name = "X509v3 Subject Alternative Name"; + public final static String OBJ_subject_alt_name = OBJ_id_ce + ".17"; + + public final static int NID_issuer_alt_name = 86; + public final static String SN_issuer_alt_name = "issuerAltName"; + public final static String LN_issuer_alt_name = "X509v3 Issuer Alternative Name"; + public final static String OBJ_issuer_alt_name = OBJ_id_ce + ".18"; + + public final static int NID_basic_constraints = 87; + public final static String SN_basic_constraints = "basicConstraints"; + public final static String LN_basic_constraints = "X509v3 Basic Constraints"; + public final static String OBJ_basic_constraints = OBJ_id_ce + ".19"; + + public final static int NID_crl_number = 88; + public final static String SN_crl_number = "crlNumber"; + public final static String LN_crl_number = "X509v3 CRL Number"; + public final static String OBJ_crl_number = OBJ_id_ce + ".20"; + + public final static int NID_certificate_policies = 89; + public final static String SN_certificate_policies = "certificatePolicies"; + public final static String LN_certificate_policies = "X509v3 Certificate Policies"; + public final static String OBJ_certificate_policies = OBJ_id_ce + ".32"; + + public final static int NID_authority_key_identifier = 90; + public final static String SN_authority_key_identifier = "authorityKeyIdentifier"; + public final static String LN_authority_key_identifier = "X509v3 Authority Key Identifier"; + public final static String OBJ_authority_key_identifier = OBJ_id_ce + ".35"; + + public final static int NID_bf_cbc = 91; + public final static String SN_bf_cbc = "BF-CBC"; + public final static String LN_bf_cbc = "bf-cbc"; + public final static String OBJ_bf_cbc = "1.3.6.1.4.1.3029.1.2"; + + public final static int NID_bf_ecb = 92; + public final static String SN_bf_ecb = "BF-ECB"; + public final static String LN_bf_ecb = "bf-ecb"; + + public final static int NID_bf_cfb64 = 93; + public final static String SN_bf_cfb64 = "BF-CFB"; + public final static String LN_bf_cfb64 = "bf-cfb"; + + public final static int NID_bf_ofb64 = 94; + public final static String SN_bf_ofb64 = "BF-OFB"; + public final static String LN_bf_ofb64 = "bf-ofb"; + + public final static int NID_mdc2 = 95; + public final static String SN_mdc2 = "MDC2"; + public final static String LN_mdc2 = "mdc2"; + public final static String OBJ_mdc2 = OBJ_X500algorithms + ".3.101"; + + public final static int NID_mdc2WithRSA = 96; + public final static String SN_mdc2WithRSA = "RSA-MDC2"; + public final static String LN_mdc2WithRSA = "mdc2WithRSA"; + public final static String OBJ_mdc2WithRSA = OBJ_X500algorithms + ".3.100"; + + public final static int NID_rc4_40 = 97; + public final static String SN_rc4_40 = "RC4-40"; + public final static String LN_rc4_40 = "rc4-40"; + + public final static int NID_rc2_40_cbc = 98; + public final static String SN_rc2_40_cbc = "RC2-40-CBC"; + public final static String LN_rc2_40_cbc = "rc2-40-cbc"; + public final static String OBJ_rc2_40_cbc = OBJ_rsadsi + ".3.2"; + + public final static int NID_givenName = 99; + public final static String SN_givenName = "GN"; + public final static String LN_givenName = "givenName"; + public final static String OBJ_givenName = OBJ_X509 + ".42"; + + public final static int NID_surname = 100; + public final static String SN_surname = "SN"; + public final static String LN_surname = "surname"; + public final static String OBJ_surname = OBJ_X509 + ".4"; + + public final static int NID_initials = 101; + public final static String LN_initials = "initials"; + public final static String OBJ_initials = OBJ_X509 + ".43"; + + public final static int NID_crl_distribution_points = 103; + public final static String SN_crl_distribution_points = "crlDistributionPoints"; + public final static String LN_crl_distribution_points = "X509v3 CRL Distribution Points"; + public final static String OBJ_crl_distribution_points = OBJ_id_ce + ".31"; + + public final static int NID_md5WithRSA = 104; + public final static String SN_md5WithRSA = "RSA-NP-MD5"; + public final static String LN_md5WithRSA = "md5WithRSA"; + public final static String OBJ_md5WithRSA = OBJ_algorithm + ".3"; + + public final static int NID_serialNumber = 105; + public final static String LN_serialNumber = "serialNumber"; + public final static String OBJ_serialNumber = OBJ_X509 + ".5"; + + public final static int NID_title = 106; + public final static String LN_title = "title"; + public final static String OBJ_title = OBJ_X509 + ".12"; + + public final static int NID_description = 107; + public final static String LN_description = "description"; + public final static String OBJ_description = OBJ_X509 + ".13"; + + public final static int NID_cast5_cbc = 108; + public final static String SN_cast5_cbc = "CAST5-CBC"; + public final static String LN_cast5_cbc = "cast5-cbc"; + public final static String OBJ_cast5_cbc = OBJ_ISO_US + ".113533.7.66.10"; + + public final static int NID_cast5_ecb = 109; + public final static String SN_cast5_ecb = "CAST5-ECB"; + public final static String LN_cast5_ecb = "cast5-ecb"; + + public final static int NID_cast5_cfb64 = 110; + public final static String SN_cast5_cfb64 = "CAST5-CFB"; + public final static String LN_cast5_cfb64 = "cast5-cfb"; + + public final static int NID_cast5_ofb64 = 111; + public final static String SN_cast5_ofb64 = "CAST5-OFB"; + public final static String LN_cast5_ofb64 = "cast5-ofb"; + + public final static int NID_pbeWithMD5AndCast5_CBC = 112; + public final static String LN_pbeWithMD5AndCast5_CBC = "pbeWithMD5AndCast5CBC"; + public final static String OBJ_pbeWithMD5AndCast5_CBC = OBJ_ISO_US + ".113533.7.66.12"; + + public final static int NID_X9cm = 185; + public final static String SN_X9cm = "X9cm"; + public final static String LN_X9cm = "X9.57 CM ?"; + public final static String OBJ_X9cm = OBJ_X9_57 + ".4"; + + public final static int NID_dsaWithSHA1 = 113; + public final static String SN_dsaWithSHA1 = "DSA-SHA1"; + public final static String LN_dsaWithSHA1 = "dsaWithSHA1"; + public final static String OBJ_dsaWithSHA1 = OBJ_X9cm + ".3"; + + public final static int NID_md5_sha1 = 114; + public final static String SN_md5_sha1 = "MD5-SHA1"; + public final static String LN_md5_sha1 = "md5-sha1"; + + public final static int NID_sha1WithRSA = 115; + public final static String SN_sha1WithRSA = "RSA-SHA1-2"; + public final static String LN_sha1WithRSA = "sha1WithRSA"; + public final static String OBJ_sha1WithRSA = OBJ_algorithm + ".29"; + + public final static int NID_dsa = 116; + public final static String SN_dsa = "DSA"; + public final static String LN_dsa = "dsaEncryption"; + public final static String OBJ_dsa = OBJ_X9cm + ".1"; + + public final static int NID_ripemd160 = 117; + public final static String SN_ripemd160 = "RIPEMD160"; + public final static String LN_ripemd160 = "ripemd160"; + public final static String OBJ_ripemd160 = "1.3.36.3.2.1"; + + public final static int NID_ripemd160WithRSA = 119; + public final static String SN_ripemd160WithRSA = "RSA-RIPEMD160"; + public final static String LN_ripemd160WithRSA = "ripemd160WithRSA"; + public final static String OBJ_ripemd160WithRSA = "1.3.36.3.3.1.2"; + + public final static int NID_rc5_cbc = 120; + public final static String SN_rc5_cbc = "RC5-CBC"; + public final static String LN_rc5_cbc = "rc5-cbc"; + public final static String OBJ_rc5_cbc = OBJ_rsadsi + ".3.8"; + + public final static int NID_rc5_ecb = 121; + public final static String SN_rc5_ecb = "RC5-ECB"; + public final static String LN_rc5_ecb = "rc5-ecb"; + + public final static int NID_rc5_cfb64 = 122; + public final static String SN_rc5_cfb64 = "RC5-CFB"; + public final static String LN_rc5_cfb64 = "rc5-cfb"; + + public final static int NID_rc5_ofb64 = 123; + public final static String SN_rc5_ofb64 = "RC5-OFB"; + public final static String LN_rc5_ofb64 = "rc5-ofb"; + + public final static int NID_rle_compression = 124; + public final static String SN_rle_compression = "RLE"; + public final static String LN_rle_compression = "run length compression"; + public final static String OBJ_rle_compression = "1.1.1.1.666.1"; + + public final static int NID_zlib_compression = 125; + public final static String SN_zlib_compression = "ZLIB"; + public final static String LN_zlib_compression = "zlib compression"; + public final static String OBJ_zlib_compression = "1.1.1.1.666.2"; + + public final static int NID_ext_key_usage = 126; + public final static String SN_ext_key_usage = "extendedKeyUsage"; + public final static String LN_ext_key_usage = "X509v3 Extended Key Usage"; + public final static String OBJ_ext_key_usage = OBJ_id_ce + ".37"; + + public final static int NID_id_kp = 128; + public final static String SN_id_kp = "id-kp"; + public final static String OBJ_id_kp = OBJ_id_pkix + ".3"; + + public final static int NID_server_auth = 129; + public final static String SN_server_auth = "serverAuth"; + public final static String LN_server_auth = "TLS Web Server Authentication"; + public final static String OBJ_server_auth = OBJ_id_kp + ".1"; + + public final static int NID_client_auth = 130; + public final static String SN_client_auth = "clientAuth"; + public final static String LN_client_auth = "TLS Web Client Authentication"; + public final static String OBJ_client_auth = OBJ_id_kp + ".2"; + + public final static int NID_code_sign = 131; + public final static String SN_code_sign = "codeSigning"; + public final static String LN_code_sign = "Code Signing"; + public final static String OBJ_code_sign = OBJ_id_kp + ".3"; + + public final static int NID_email_protect = 132; + public final static String SN_email_protect = "emailProtection"; + public final static String LN_email_protect = "E-mail Protection"; + public final static String OBJ_email_protect = OBJ_id_kp + ".4"; + + public final static int NID_time_stamp = 133; + public final static String SN_time_stamp = "timeStamping"; + public final static String LN_time_stamp = "Time Stamping"; + public final static String OBJ_time_stamp = OBJ_id_kp + ".8"; + + public final static int NID_ms_code_ind = 134; + public final static String SN_ms_code_ind = "msCodeInd"; + public final static String LN_ms_code_ind = "Microsoft Individual Code Signing"; + public final static String OBJ_ms_code_ind = "1.3.6.1.4.1.311.2.1.21"; + + public final static int NID_ms_code_com = 135; + public final static String SN_ms_code_com = "msCodeCom"; + public final static String LN_ms_code_com = "Microsoft Commercial Code Signing"; + public final static String OBJ_ms_code_com = "1.3.6.1.4.1.311.2.1.22"; + + public final static int NID_ms_ctl_sign = 136; + public final static String SN_ms_ctl_sign = "msCTLSign"; + public final static String LN_ms_ctl_sign = "Microsoft Trust List Signing"; + public final static String OBJ_ms_ctl_sign = "1.3.6.1.4.1.311.10.3.1"; + + public final static int NID_ms_sgc = 137; + public final static String SN_ms_sgc = "msSGC"; + public final static String LN_ms_sgc = "Microsoft Server Gated Crypto"; + public final static String OBJ_ms_sgc = "1.3.6.1.4.1.311.10.3.3"; + + public final static int NID_ms_efs = 138; + public final static String SN_ms_efs = "msEFS"; + public final static String LN_ms_efs = "Microsoft Encrypted File System"; + public final static String OBJ_ms_efs = "1.3.6.1.4.1.311.10.3.4"; + + public final static int NID_ns_sgc = 139; + public final static String SN_ns_sgc = "nsSGC"; + public final static String LN_ns_sgc = "Netscape Server Gated Crypto"; + public final static String OBJ_ns_sgc = OBJ_netscape + ".4.1"; + + public final static int NID_delta_crl = 140; + public final static String SN_delta_crl = "deltaCRL"; + public final static String LN_delta_crl = "X509v3 Delta CRL Indicator"; + public final static String OBJ_delta_crl = OBJ_id_ce + ".27"; + + public final static int NID_crl_reason = 141; + public final static String SN_crl_reason = "CRLReason"; + public final static String LN_crl_reason = "X509v3 CRL Reason Code"; + public final static String OBJ_crl_reason = OBJ_id_ce + ".21"; + + public final static int NID_invalidity_date = 142; + public final static String SN_invalidity_date = "invalidityDate"; + public final static String LN_invalidity_date = "Invalidity Date"; + public final static String OBJ_invalidity_date = OBJ_id_ce + ".24"; + + public final static int NID_sxnet = 143; + public final static String SN_sxnet = "SXNetID"; + public final static String LN_sxnet = "Strong Extranet ID"; + public final static String OBJ_sxnet = "1.3.101.1.4.1"; + + public final static String OBJ_pkcs12_pbeids = OBJ_pkcs12 + ".1"; + + public final static int NID_pbe_WithSHA1And128BitRC4 = 144; + public final static String SN_pbe_WithSHA1And128BitRC4 = "PBE-SHA1-RC4-128"; + public final static String LN_pbe_WithSHA1And128BitRC4 = "pbeWithSHA1And128BitRC4"; + public final static String OBJ_pbe_WithSHA1And128BitRC4 = OBJ_pkcs12_pbeids + ".1"; + + public final static int NID_pbe_WithSHA1And40BitRC4 = 145; + public final static String SN_pbe_WithSHA1And40BitRC4 = "PBE-SHA1-RC4-40"; + public final static String LN_pbe_WithSHA1And40BitRC4 = "pbeWithSHA1And40BitRC4"; + public final static String OBJ_pbe_WithSHA1And40BitRC4 = OBJ_pkcs12_pbeids + ".2"; + + public final static int NID_pbe_WithSHA1And3_Key_TripleDES_CBC = 146; + public final static String SN_pbe_WithSHA1And3_Key_TripleDES_CBC = "PBE-SHA1-3DES"; + public final static String LN_pbe_WithSHA1And3_Key_TripleDES_CBC = "pbeWithSHA1And3-KeyTripleDES-CBC"; + public final static String OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC = OBJ_pkcs12_pbeids + ".3"; + + public final static int NID_pbe_WithSHA1And2_Key_TripleDES_CBC = 147; + public final static String SN_pbe_WithSHA1And2_Key_TripleDES_CBC = "PBE-SHA1-2DES"; + public final static String LN_pbe_WithSHA1And2_Key_TripleDES_CBC = "pbeWithSHA1And2-KeyTripleDES-CBC"; + public final static String OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC = OBJ_pkcs12_pbeids + ".4"; + + public final static int NID_pbe_WithSHA1And128BitRC2_CBC = 148; + public final static String SN_pbe_WithSHA1And128BitRC2_CBC = "PBE-SHA1-RC2-128"; + public final static String LN_pbe_WithSHA1And128BitRC2_CBC = "pbeWithSHA1And128BitRC2-CBC"; + public final static String OBJ_pbe_WithSHA1And128BitRC2_CBC = OBJ_pkcs12_pbeids + ".5"; + + public final static int NID_pbe_WithSHA1And40BitRC2_CBC = 149; + public final static String SN_pbe_WithSHA1And40BitRC2_CBC = "PBE-SHA1-RC2-40"; + public final static String LN_pbe_WithSHA1And40BitRC2_CBC = "pbeWithSHA1And40BitRC2-CBC"; + public final static String OBJ_pbe_WithSHA1And40BitRC2_CBC = OBJ_pkcs12_pbeids + ".6"; + + public final static int NID_keyBag = 150; + public final static String LN_keyBag = "keyBag"; + public final static String OBJ_keyBag = OBJ_pkcs12_BagIds + ".1"; + + public final static int NID_pkcs8ShroudedKeyBag = 151; + public final static String LN_pkcs8ShroudedKeyBag = "pkcs8ShroudedKeyBag"; + public final static String OBJ_pkcs8ShroudedKeyBag = OBJ_pkcs12_BagIds + ".2"; + + public final static int NID_certBag = 152; + public final static String LN_certBag = "certBag"; + public final static String OBJ_certBag = OBJ_pkcs12_BagIds + ".3"; + + public final static int NID_crlBag = 153; + public final static String LN_crlBag = "crlBag"; + public final static String OBJ_crlBag = OBJ_pkcs12_BagIds + ".4"; + + public final static int NID_secretBag = 154; + public final static String LN_secretBag = "secretBag"; + public final static String OBJ_secretBag = OBJ_pkcs12_BagIds + ".5"; + + public final static int NID_safeContentsBag = 155; + public final static String LN_safeContentsBag = "safeContentsBag"; + public final static String OBJ_safeContentsBag = OBJ_pkcs12_BagIds + ".6"; + + public final static int NID_friendlyName = 156; + public final static String LN_friendlyName = "friendlyName"; + public final static String OBJ_friendlyName = OBJ_pkcs9 + ".20"; + + public final static int NID_localKeyID = 157; + public final static String LN_localKeyID = "localKeyID"; + public final static String OBJ_localKeyID = OBJ_pkcs9 + ".21"; + + public final static int NID_x509Certificate = 158; + public final static String LN_x509Certificate = "x509Certificate"; + public final static String OBJ_x509Certificate = OBJ_certTypes + ".1"; + + public final static int NID_sdsiCertificate = 159; + public final static String LN_sdsiCertificate = "sdsiCertificate"; + public final static String OBJ_sdsiCertificate = OBJ_certTypes + ".2"; + + public final static int NID_x509Crl = 160; + public final static String LN_x509Crl = "x509Crl"; + public final static String OBJ_x509Crl = OBJ_crlTypes + ".1"; + + public final static int NID_pbes2 = 161; + public final static String LN_pbes2 = "PBES2"; + public final static String OBJ_pbes2 = OBJ_pkcs5 + ".13"; + + public final static int NID_pbmac1 = 162; + public final static String LN_pbmac1 = "PBMAC1"; + public final static String OBJ_pbmac1 = OBJ_pkcs5 + ".14"; + + public final static int NID_hmacWithSHA1 = 163; + public final static String LN_hmacWithSHA1 = "hmacWithSHA1"; + public final static String OBJ_hmacWithSHA1 = OBJ_rsadsi + ".2.7"; + + public final static int NID_id_qt = 259; + public final static String SN_id_qt = "id-qt"; + public final static String OBJ_id_qt = OBJ_id_pkix + ".2"; + + public final static int NID_id_qt_cps = 164; + public final static String SN_id_qt_cps = "id-qt-cps"; + public final static String LN_id_qt_cps = "Policy Qualifier CPS"; + public final static String OBJ_id_qt_cps = OBJ_id_qt + ".1"; + + public final static int NID_id_qt_unotice = 165; + public final static String SN_id_qt_unotice = "id-qt-unotice"; + public final static String LN_id_qt_unotice = "Policy Qualifier User Notice"; + public final static String OBJ_id_qt_unotice = OBJ_id_qt + ".2"; + + public final static int NID_rc2_64_cbc = 166; + public final static String SN_rc2_64_cbc = "RC2-64-CBC"; + public final static String LN_rc2_64_cbc = "rc2-64-cbc"; + + public final static int NID_SMIMECapabilities = 167; + public final static String SN_SMIMECapabilities = "SMIME-CAPS"; + public final static String LN_SMIMECapabilities = "S/MIME Capabilities"; + public final static String OBJ_SMIMECapabilities = OBJ_pkcs9 + ".15"; + + public final static int NID_pbeWithMD2AndRC2_CBC = 168; + public final static String SN_pbeWithMD2AndRC2_CBC = "PBE-MD2-RC2-64"; + public final static String LN_pbeWithMD2AndRC2_CBC = "pbeWithMD2AndRC2-CBC"; + public final static String OBJ_pbeWithMD2AndRC2_CBC = OBJ_pkcs5 + ".4"; + + public final static int NID_pbeWithMD5AndRC2_CBC = 169; + public final static String SN_pbeWithMD5AndRC2_CBC = "PBE-MD5-RC2-64"; + public final static String LN_pbeWithMD5AndRC2_CBC = "pbeWithMD5AndRC2-CBC"; + public final static String OBJ_pbeWithMD5AndRC2_CBC = OBJ_pkcs5 + ".6"; + + public final static int NID_pbeWithSHA1AndDES_CBC = 170; + public final static String SN_pbeWithSHA1AndDES_CBC = "PBE-SHA1-DES"; + public final static String LN_pbeWithSHA1AndDES_CBC = "pbeWithSHA1AndDES-CBC"; + public final static String OBJ_pbeWithSHA1AndDES_CBC = OBJ_pkcs5 + ".10"; + + public final static int NID_ms_ext_req = 171; + public final static String SN_ms_ext_req = "msExtReq"; + public final static String LN_ms_ext_req = "Microsoft Extension Request"; + public final static String OBJ_ms_ext_req = "1.3.6.1.4.1.311.2.1.14"; + + public final static int NID_ext_req = 172; + public final static String SN_ext_req = "extReq"; + public final static String LN_ext_req = "Extension Request"; + public final static String OBJ_ext_req = OBJ_pkcs9 + ".14"; + + public final static int NID_name = 173; + public final static String SN_name = "name"; + public final static String LN_name = "name"; + public final static String OBJ_name = OBJ_X509 + ".41"; + + public final static int NID_dnQualifier = 174; + public final static String SN_dnQualifier = "dnQualifier"; + public final static String LN_dnQualifier = "dnQualifier"; + public final static String OBJ_dnQualifier = OBJ_X509 + ".46"; + + public final static int NID_id_pe = 175; + public final static String SN_id_pe = "id-pe"; + public final static String OBJ_id_pe = OBJ_id_pkix + ".1"; + + public final static int NID_info_access = 177; + public final static String SN_info_access = "authorityInfoAccess"; + public final static String LN_info_access = "Authority Information Access"; + public final static String OBJ_info_access = OBJ_id_pe + ".1"; + + public final static int NID_ad_ca_issuers = 179; + public final static String SN_ad_ca_issuers = "caIssuers"; + public final static String LN_ad_ca_issuers = "CA Issuers"; + public final static String OBJ_ad_ca_issuers = OBJ_id_ad + ".2"; + + public final static int NID_OCSP_sign = 180; + public final static String SN_OCSP_sign = "OCSPSigning"; + public final static String LN_OCSP_sign = "OCSP Signing"; + public final static String OBJ_OCSP_sign = OBJ_id_kp + ".9"; + + public final static int NID_SMIME = 188; + public final static String SN_SMIME = "SMIME"; + public final static String LN_SMIME = "S/MIME"; + public final static String OBJ_SMIME = OBJ_pkcs9 + ".16"; + + public final static int NID_id_smime_mod = 189; + public final static String SN_id_smime_mod = "id-smime-mod"; + public final static String OBJ_id_smime_mod = OBJ_SMIME + ".0"; + + public final static int NID_id_smime_ct = 190; + public final static String SN_id_smime_ct = "id-smime-ct"; + public final static String OBJ_id_smime_ct = OBJ_SMIME + ".1"; + + public final static int NID_id_smime_aa = 191; + public final static String SN_id_smime_aa = "id-smime-aa"; + public final static String OBJ_id_smime_aa = OBJ_SMIME + ".2"; + + public final static int NID_id_smime_alg = 192; + public final static String SN_id_smime_alg = "id-smime-alg"; + public final static String OBJ_id_smime_alg = OBJ_SMIME + ".3"; + + public final static int NID_id_smime_cd = 193; + public final static String SN_id_smime_cd = "id-smime-cd"; + public final static String OBJ_id_smime_cd = OBJ_SMIME + ".4"; + + public final static int NID_id_smime_spq = 194; + public final static String SN_id_smime_spq = "id-smime-spq"; + public final static String OBJ_id_smime_spq = OBJ_SMIME + ".5"; + + public final static int NID_id_smime_cti = 195; + public final static String SN_id_smime_cti = "id-smime-cti"; + public final static String OBJ_id_smime_cti = OBJ_SMIME + ".6"; + + public final static int NID_id_smime_mod_cms = 196; + public final static String SN_id_smime_mod_cms = "id-smime-mod-cms"; + public final static String OBJ_id_smime_mod_cms = OBJ_id_smime_mod + ".1"; + + public final static int NID_id_smime_mod_ess = 197; + public final static String SN_id_smime_mod_ess = "id-smime-mod-ess"; + public final static String OBJ_id_smime_mod_ess = OBJ_id_smime_mod + ".2"; + + public final static int NID_id_smime_mod_oid = 198; + public final static String SN_id_smime_mod_oid = "id-smime-mod-oid"; + public final static String OBJ_id_smime_mod_oid = OBJ_id_smime_mod + ".3"; + + public final static int NID_id_smime_mod_msg_v3 = 199; + public final static String SN_id_smime_mod_msg_v3 = "id-smime-mod-msg-v3"; + public final static String OBJ_id_smime_mod_msg_v3 = OBJ_id_smime_mod + ".4"; + + public final static int NID_id_smime_mod_ets_eSignature_88 = 200; + public final static String SN_id_smime_mod_ets_eSignature_88 = "id-smime-mod-ets-eSignature-88"; + public final static String OBJ_id_smime_mod_ets_eSignature_88 = OBJ_id_smime_mod + ".5"; + + public final static int NID_id_smime_mod_ets_eSignature_97 = 201; + public final static String SN_id_smime_mod_ets_eSignature_97 = "id-smime-mod-ets-eSignature-97"; + public final static String OBJ_id_smime_mod_ets_eSignature_97 = OBJ_id_smime_mod + ".6"; + + public final static int NID_id_smime_mod_ets_eSigPolicy_88 = 202; + public final static String SN_id_smime_mod_ets_eSigPolicy_88 = "id-smime-mod-ets-eSigPolicy-88"; + public final static String OBJ_id_smime_mod_ets_eSigPolicy_88 = OBJ_id_smime_mod + ".7"; + + public final static int NID_id_smime_mod_ets_eSigPolicy_97 = 203; + public final static String SN_id_smime_mod_ets_eSigPolicy_97 = "id-smime-mod-ets-eSigPolicy-97"; + public final static String OBJ_id_smime_mod_ets_eSigPolicy_97 = OBJ_id_smime_mod + ".8"; + + public final static int NID_id_smime_ct_receipt = 204; + public final static String SN_id_smime_ct_receipt = "id-smime-ct-receipt"; + public final static String OBJ_id_smime_ct_receipt = OBJ_id_smime_ct + ".1"; + + public final static int NID_id_smime_ct_authData = 205; + public final static String SN_id_smime_ct_authData = "id-smime-ct-authData"; + public final static String OBJ_id_smime_ct_authData = OBJ_id_smime_ct + ".2"; + + public final static int NID_id_smime_ct_publishCert = 206; + public final static String SN_id_smime_ct_publishCert = "id-smime-ct-publishCert"; + public final static String OBJ_id_smime_ct_publishCert = OBJ_id_smime_ct + ".3"; + + public final static int NID_id_smime_ct_TSTInfo = 207; + public final static String SN_id_smime_ct_TSTInfo = "id-smime-ct-TSTInfo"; + public final static String OBJ_id_smime_ct_TSTInfo = OBJ_id_smime_ct + ".4"; + + public final static int NID_id_smime_ct_TDTInfo = 208; + public final static String SN_id_smime_ct_TDTInfo = "id-smime-ct-TDTInfo"; + public final static String OBJ_id_smime_ct_TDTInfo = OBJ_id_smime_ct + ".5"; + + public final static int NID_id_smime_ct_contentInfo = 209; + public final static String SN_id_smime_ct_contentInfo = "id-smime-ct-contentInfo"; + public final static String OBJ_id_smime_ct_contentInfo = OBJ_id_smime_ct + ".6"; + + public final static int NID_id_smime_ct_DVCSRequestData = 210; + public final static String SN_id_smime_ct_DVCSRequestData = "id-smime-ct-DVCSRequestData"; + public final static String OBJ_id_smime_ct_DVCSRequestData = OBJ_id_smime_ct + ".7"; + + public final static int NID_id_smime_ct_DVCSResponseData = 211; + public final static String SN_id_smime_ct_DVCSResponseData = "id-smime-ct-DVCSResponseData"; + public final static String OBJ_id_smime_ct_DVCSResponseData = OBJ_id_smime_ct + ".8"; + + public final static int NID_id_smime_aa_receiptRequest = 212; + public final static String SN_id_smime_aa_receiptRequest = "id-smime-aa-receiptRequest"; + public final static String OBJ_id_smime_aa_receiptRequest = OBJ_id_smime_aa + ".1"; + + public final static int NID_id_smime_aa_securityLabel = 213; + public final static String SN_id_smime_aa_securityLabel = "id-smime-aa-securityLabel"; + public final static String OBJ_id_smime_aa_securityLabel = OBJ_id_smime_aa + ".2"; + + public final static int NID_id_smime_aa_mlExpandHistory = 214; + public final static String SN_id_smime_aa_mlExpandHistory = "id-smime-aa-mlExpandHistory"; + public final static String OBJ_id_smime_aa_mlExpandHistory = OBJ_id_smime_aa + ".3"; + + public final static int NID_id_smime_aa_contentHint = 215; + public final static String SN_id_smime_aa_contentHint = "id-smime-aa-contentHint"; + public final static String OBJ_id_smime_aa_contentHint = OBJ_id_smime_aa + ".4"; + + public final static int NID_id_smime_aa_msgSigDigest = 216; + public final static String SN_id_smime_aa_msgSigDigest = "id-smime-aa-msgSigDigest"; + public final static String OBJ_id_smime_aa_msgSigDigest = OBJ_id_smime_aa + ".5"; + + public final static int NID_id_smime_aa_encapContentType = 217; + public final static String SN_id_smime_aa_encapContentType = "id-smime-aa-encapContentType"; + public final static String OBJ_id_smime_aa_encapContentType = OBJ_id_smime_aa + ".6"; + + public final static int NID_id_smime_aa_contentIdentifier = 218; + public final static String SN_id_smime_aa_contentIdentifier = "id-smime-aa-contentIdentifier"; + public final static String OBJ_id_smime_aa_contentIdentifier = OBJ_id_smime_aa + ".7"; + + public final static int NID_id_smime_aa_macValue = 219; + public final static String SN_id_smime_aa_macValue = "id-smime-aa-macValue"; + public final static String OBJ_id_smime_aa_macValue = OBJ_id_smime_aa + ".8"; + + public final static int NID_id_smime_aa_equivalentLabels = 220; + public final static String SN_id_smime_aa_equivalentLabels = "id-smime-aa-equivalentLabels"; + public final static String OBJ_id_smime_aa_equivalentLabels = OBJ_id_smime_aa + ".9"; + + public final static int NID_id_smime_aa_contentReference = 221; + public final static String SN_id_smime_aa_contentReference = "id-smime-aa-contentReference"; + public final static String OBJ_id_smime_aa_contentReference = OBJ_id_smime_aa + ".10"; + + public final static int NID_id_smime_aa_encrypKeyPref = 222; + public final static String SN_id_smime_aa_encrypKeyPref = "id-smime-aa-encrypKeyPref"; + public final static String OBJ_id_smime_aa_encrypKeyPref = OBJ_id_smime_aa + ".11"; + + public final static int NID_id_smime_aa_signingCertificate = 223; + public final static String SN_id_smime_aa_signingCertificate = "id-smime-aa-signingCertificate"; + public final static String OBJ_id_smime_aa_signingCertificate = OBJ_id_smime_aa + ".12"; + + public final static int NID_id_smime_aa_smimeEncryptCerts = 224; + public final static String SN_id_smime_aa_smimeEncryptCerts = "id-smime-aa-smimeEncryptCerts"; + public final static String OBJ_id_smime_aa_smimeEncryptCerts = OBJ_id_smime_aa + ".13"; + + public final static int NID_id_smime_aa_timeStampToken = 225; + public final static String SN_id_smime_aa_timeStampToken = "id-smime-aa-timeStampToken"; + public final static String OBJ_id_smime_aa_timeStampToken = OBJ_id_smime_aa + ".14"; + + public final static int NID_id_smime_aa_ets_sigPolicyId = 226; + public final static String SN_id_smime_aa_ets_sigPolicyId = "id-smime-aa-ets-sigPolicyId"; + public final static String OBJ_id_smime_aa_ets_sigPolicyId = OBJ_id_smime_aa + ".15"; + + public final static int NID_id_smime_aa_ets_commitmentType = 227; + public final static String SN_id_smime_aa_ets_commitmentType = "id-smime-aa-ets-commitmentType"; + public final static String OBJ_id_smime_aa_ets_commitmentType = OBJ_id_smime_aa + ".16"; + + public final static int NID_id_smime_aa_ets_signerLocation = 228; + public final static String SN_id_smime_aa_ets_signerLocation = "id-smime-aa-ets-signerLocation"; + public final static String OBJ_id_smime_aa_ets_signerLocation = OBJ_id_smime_aa + ".17"; + + public final static int NID_id_smime_aa_ets_signerAttr = 229; + public final static String SN_id_smime_aa_ets_signerAttr = "id-smime-aa-ets-signerAttr"; + public final static String OBJ_id_smime_aa_ets_signerAttr = OBJ_id_smime_aa + ".18"; + + public final static int NID_id_smime_aa_ets_otherSigCert = 230; + public final static String SN_id_smime_aa_ets_otherSigCert = "id-smime-aa-ets-otherSigCert"; + public final static String OBJ_id_smime_aa_ets_otherSigCert = OBJ_id_smime_aa + ".19"; + + public final static int NID_id_smime_aa_ets_contentTimestamp = 231; + public final static String SN_id_smime_aa_ets_contentTimestamp = "id-smime-aa-ets-contentTimestamp"; + public final static String OBJ_id_smime_aa_ets_contentTimestamp = OBJ_id_smime_aa + ".20"; + + public final static int NID_id_smime_aa_ets_CertificateRefs = 232; + public final static String SN_id_smime_aa_ets_CertificateRefs = "id-smime-aa-ets-CertificateRefs"; + public final static String OBJ_id_smime_aa_ets_CertificateRefs = OBJ_id_smime_aa + ".21"; + + public final static int NID_id_smime_aa_ets_RevocationRefs = 233; + public final static String SN_id_smime_aa_ets_RevocationRefs = "id-smime-aa-ets-RevocationRefs"; + public final static String OBJ_id_smime_aa_ets_RevocationRefs = OBJ_id_smime_aa + ".22"; + + public final static int NID_id_smime_aa_ets_certValues = 234; + public final static String SN_id_smime_aa_ets_certValues = "id-smime-aa-ets-certValues"; + public final static String OBJ_id_smime_aa_ets_certValues = OBJ_id_smime_aa + ".23"; + + public final static int NID_id_smime_aa_ets_revocationValues = 235; + public final static String SN_id_smime_aa_ets_revocationValues = "id-smime-aa-ets-revocationValues"; + public final static String OBJ_id_smime_aa_ets_revocationValues = OBJ_id_smime_aa + ".24"; + + public final static int NID_id_smime_aa_ets_escTimeStamp = 236; + public final static String SN_id_smime_aa_ets_escTimeStamp = "id-smime-aa-ets-escTimeStamp"; + public final static String OBJ_id_smime_aa_ets_escTimeStamp = OBJ_id_smime_aa + ".25"; + + public final static int NID_id_smime_aa_ets_certCRLTimestamp = 237; + public final static String SN_id_smime_aa_ets_certCRLTimestamp = "id-smime-aa-ets-certCRLTimestamp"; + public final static String OBJ_id_smime_aa_ets_certCRLTimestamp = OBJ_id_smime_aa + ".26"; + + public final static int NID_id_smime_aa_ets_archiveTimeStamp = 238; + public final static String SN_id_smime_aa_ets_archiveTimeStamp = "id-smime-aa-ets-archiveTimeStamp"; + public final static String OBJ_id_smime_aa_ets_archiveTimeStamp = OBJ_id_smime_aa + ".27"; + + public final static int NID_id_smime_aa_signatureType = 239; + public final static String SN_id_smime_aa_signatureType = "id-smime-aa-signatureType"; + public final static String OBJ_id_smime_aa_signatureType = OBJ_id_smime_aa + ".28"; + + public final static int NID_id_smime_aa_dvcs_dvc = 240; + public final static String SN_id_smime_aa_dvcs_dvc = "id-smime-aa-dvcs-dvc"; + public final static String OBJ_id_smime_aa_dvcs_dvc = OBJ_id_smime_aa + ".29"; + + public final static int NID_id_smime_alg_ESDHwith3DES = 241; + public final static String SN_id_smime_alg_ESDHwith3DES = "id-smime-alg-ESDHwith3DES"; + public final static String OBJ_id_smime_alg_ESDHwith3DES = OBJ_id_smime_alg + ".1"; + + public final static int NID_id_smime_alg_ESDHwithRC2 = 242; + public final static String SN_id_smime_alg_ESDHwithRC2 = "id-smime-alg-ESDHwithRC2"; + public final static String OBJ_id_smime_alg_ESDHwithRC2 = OBJ_id_smime_alg + ".2"; + + public final static int NID_id_smime_alg_3DESwrap = 243; + public final static String SN_id_smime_alg_3DESwrap = "id-smime-alg-3DESwrap"; + public final static String OBJ_id_smime_alg_3DESwrap = OBJ_id_smime_alg + ".3"; + + public final static int NID_id_smime_alg_RC2wrap = 244; + public final static String SN_id_smime_alg_RC2wrap = "id-smime-alg-RC2wrap"; + public final static String OBJ_id_smime_alg_RC2wrap = OBJ_id_smime_alg + ".4"; + + public final static int NID_id_smime_alg_ESDH = 245; + public final static String SN_id_smime_alg_ESDH = "id-smime-alg-ESDH"; + public final static String OBJ_id_smime_alg_ESDH = OBJ_id_smime_alg + ".5"; + + public final static int NID_id_smime_alg_CMS3DESwrap = 246; + public final static String SN_id_smime_alg_CMS3DESwrap = "id-smime-alg-CMS3DESwrap"; + public final static String OBJ_id_smime_alg_CMS3DESwrap = OBJ_id_smime_alg + ".6"; + + public final static int NID_id_smime_alg_CMSRC2wrap = 247; + public final static String SN_id_smime_alg_CMSRC2wrap = "id-smime-alg-CMSRC2wrap"; + public final static String OBJ_id_smime_alg_CMSRC2wrap = OBJ_id_smime_alg + ".7"; + + public final static int NID_id_smime_cd_ldap = 248; + public final static String SN_id_smime_cd_ldap = "id-smime-cd-ldap"; + public final static String OBJ_id_smime_cd_ldap = OBJ_id_smime_cd + ".1"; + + public final static int NID_id_smime_spq_ets_sqt_uri = 249; + public final static String SN_id_smime_spq_ets_sqt_uri = "id-smime-spq-ets-sqt-uri"; + public final static String OBJ_id_smime_spq_ets_sqt_uri = OBJ_id_smime_spq + ".1"; + + public final static int NID_id_smime_spq_ets_sqt_unotice = 250; + public final static String SN_id_smime_spq_ets_sqt_unotice = "id-smime-spq-ets-sqt-unotice"; + public final static String OBJ_id_smime_spq_ets_sqt_unotice = OBJ_id_smime_spq + ".2"; + + public final static int NID_id_smime_cti_ets_proofOfOrigin = 251; + public final static String SN_id_smime_cti_ets_proofOfOrigin = "id-smime-cti-ets-proofOfOrigin"; + public final static String OBJ_id_smime_cti_ets_proofOfOrigin = OBJ_id_smime_cti + ".1"; + + public final static int NID_id_smime_cti_ets_proofOfReceipt = 252; + public final static String SN_id_smime_cti_ets_proofOfReceipt = "id-smime-cti-ets-proofOfReceipt"; + public final static String OBJ_id_smime_cti_ets_proofOfReceipt = OBJ_id_smime_cti + ".2"; + + public final static int NID_id_smime_cti_ets_proofOfDelivery = 253; + public final static String SN_id_smime_cti_ets_proofOfDelivery = "id-smime-cti-ets-proofOfDelivery"; + public final static String OBJ_id_smime_cti_ets_proofOfDelivery = OBJ_id_smime_cti + ".3"; + + public final static int NID_id_smime_cti_ets_proofOfSender = 254; + public final static String SN_id_smime_cti_ets_proofOfSender = "id-smime-cti-ets-proofOfSender"; + public final static String OBJ_id_smime_cti_ets_proofOfSender = OBJ_id_smime_cti + ".4"; + + public final static int NID_id_smime_cti_ets_proofOfApproval = 255; + public final static String SN_id_smime_cti_ets_proofOfApproval = "id-smime-cti-ets-proofOfApproval"; + public final static String OBJ_id_smime_cti_ets_proofOfApproval = OBJ_id_smime_cti + ".5"; + + public final static int NID_id_smime_cti_ets_proofOfCreation = 256; + public final static String SN_id_smime_cti_ets_proofOfCreation = "id-smime-cti-ets-proofOfCreation"; + public final static String OBJ_id_smime_cti_ets_proofOfCreation = OBJ_id_smime_cti + ".6"; + + public final static int NID_md4 = 257; + public final static String SN_md4 = "MD4"; + public final static String LN_md4 = "md4"; + public final static String OBJ_md4 = OBJ_rsadsi + ".2.4"; + + public final static int NID_id_pkix_mod = 258; + public final static String SN_id_pkix_mod = "id-pkix-mod"; + public final static String OBJ_id_pkix_mod = OBJ_id_pkix + ".0"; + + public final static int NID_id_it = 260; + public final static String SN_id_it = "id-it"; + public final static String OBJ_id_it = OBJ_id_pkix + ".4"; + + public final static int NID_id_pkip = 261; + public final static String SN_id_pkip = "id-pkip"; + public final static String OBJ_id_pkip = OBJ_id_pkix + ".5"; + + public final static int NID_id_alg = 262; + public final static String SN_id_alg = "id-alg"; + public final static String OBJ_id_alg = OBJ_id_pkix + ".6"; + + public final static int NID_id_cmc = 263; + public final static String SN_id_cmc = "id-cmc"; + public final static String OBJ_id_cmc = OBJ_id_pkix + ".7"; + + public final static int NID_id_on = 264; + public final static String SN_id_on = "id-on"; + public final static String OBJ_id_on = OBJ_id_pkix + ".8"; + + public final static int NID_id_pda = 265; + public final static String SN_id_pda = "id-pda"; + public final static String OBJ_id_pda = OBJ_id_pkix + ".9"; + + public final static int NID_id_aca = 266; + public final static String SN_id_aca = "id-aca"; + public final static String OBJ_id_aca = OBJ_id_pkix + ".10"; + + public final static int NID_id_qcs = 267; + public final static String SN_id_qcs = "id-qcs"; + public final static String OBJ_id_qcs = OBJ_id_pkix + ".11"; + + public final static int NID_id_cct = 268; + public final static String SN_id_cct = "id-cct"; + public final static String OBJ_id_cct = OBJ_id_pkix + ".12"; + + public final static int NID_id_pkix1_explicit_88 = 269; + public final static String SN_id_pkix1_explicit_88 = "id-pkix1-explicit-88"; + public final static String OBJ_id_pkix1_explicit_88 = OBJ_id_pkix_mod + ".1"; + + public final static int NID_id_pkix1_implicit_88 = 270; + public final static String SN_id_pkix1_implicit_88 = "id-pkix1-implicit-88"; + public final static String OBJ_id_pkix1_implicit_88 = OBJ_id_pkix_mod + ".2"; + + public final static int NID_id_pkix1_explicit_93 = 271; + public final static String SN_id_pkix1_explicit_93 = "id-pkix1-explicit-93"; + public final static String OBJ_id_pkix1_explicit_93 = OBJ_id_pkix_mod + ".3"; + + public final static int NID_id_pkix1_implicit_93 = 272; + public final static String SN_id_pkix1_implicit_93 = "id-pkix1-implicit-93"; + public final static String OBJ_id_pkix1_implicit_93 = OBJ_id_pkix_mod + ".4"; + + public final static int NID_id_mod_crmf = 273; + public final static String SN_id_mod_crmf = "id-mod-crmf"; + public final static String OBJ_id_mod_crmf = OBJ_id_pkix_mod + ".5"; + + public final static int NID_id_mod_cmc = 274; + public final static String SN_id_mod_cmc = "id-mod-cmc"; + public final static String OBJ_id_mod_cmc = OBJ_id_pkix_mod + ".6"; + + public final static int NID_id_mod_kea_profile_88 = 275; + public final static String SN_id_mod_kea_profile_88 = "id-mod-kea-profile-88"; + public final static String OBJ_id_mod_kea_profile_88 = OBJ_id_pkix_mod + ".7"; + + public final static int NID_id_mod_kea_profile_93 = 276; + public final static String SN_id_mod_kea_profile_93 = "id-mod-kea-profile-93"; + public final static String OBJ_id_mod_kea_profile_93 = OBJ_id_pkix_mod + ".8"; + + public final static int NID_id_mod_cmp = 277; + public final static String SN_id_mod_cmp = "id-mod-cmp"; + public final static String OBJ_id_mod_cmp = OBJ_id_pkix_mod + ".9"; + + public final static int NID_id_mod_qualified_cert_88 = 278; + public final static String SN_id_mod_qualified_cert_88 = "id-mod-qualified-cert-88"; + public final static String OBJ_id_mod_qualified_cert_88 = OBJ_id_pkix_mod + ".10"; + + public final static int NID_id_mod_qualified_cert_93 = 279; + public final static String SN_id_mod_qualified_cert_93 = "id-mod-qualified-cert-93"; + public final static String OBJ_id_mod_qualified_cert_93 = OBJ_id_pkix_mod + ".11"; + + public final static int NID_id_mod_attribute_cert = 280; + public final static String SN_id_mod_attribute_cert = "id-mod-attribute-cert"; + public final static String OBJ_id_mod_attribute_cert = OBJ_id_pkix_mod + ".12"; + + public final static int NID_id_mod_timestamp_protocol = 281; + public final static String SN_id_mod_timestamp_protocol = "id-mod-timestamp-protocol"; + public final static String OBJ_id_mod_timestamp_protocol = OBJ_id_pkix_mod + ".13"; + + public final static int NID_id_mod_ocsp = 282; + public final static String SN_id_mod_ocsp = "id-mod-ocsp"; + public final static String OBJ_id_mod_ocsp = OBJ_id_pkix_mod + ".14"; + + public final static int NID_id_mod_dvcs = 283; + public final static String SN_id_mod_dvcs = "id-mod-dvcs"; + public final static String OBJ_id_mod_dvcs = OBJ_id_pkix_mod + ".15"; + + public final static int NID_id_mod_cmp2000 = 284; + public final static String SN_id_mod_cmp2000 = "id-mod-cmp2000"; + public final static String OBJ_id_mod_cmp2000 = OBJ_id_pkix_mod + ".16"; + + public final static int NID_biometricInfo = 285; + public final static String SN_biometricInfo = "biometricInfo"; + public final static String LN_biometricInfo = "Biometric Info"; + public final static String OBJ_biometricInfo = OBJ_id_pe + ".2"; + + public final static int NID_qcStatements = 286; + public final static String SN_qcStatements = "qcStatements"; + public final static String OBJ_qcStatements = OBJ_id_pe + ".3"; + + public final static int NID_ac_auditEntity = 287; + public final static String SN_ac_auditEntity = "ac-auditEntity"; + public final static String OBJ_ac_auditEntity = OBJ_id_pe + ".4"; + + public final static int NID_ac_targeting = 288; + public final static String SN_ac_targeting = "ac-targeting"; + public final static String OBJ_ac_targeting = OBJ_id_pe + ".5"; + + public final static int NID_aaControls = 289; + public final static String SN_aaControls = "aaControls"; + public final static String OBJ_aaControls = OBJ_id_pe + ".6"; + + public final static int NID_sbgp_ipAddrBlock = 290; + public final static String SN_sbgp_ipAddrBlock = "sbgp-ipAddrBlock"; + public final static String OBJ_sbgp_ipAddrBlock = OBJ_id_pe + ".7"; + + public final static int NID_sbgp_autonomousSysNum = 291; + public final static String SN_sbgp_autonomousSysNum = "sbgp-autonomousSysNum"; + public final static String OBJ_sbgp_autonomousSysNum = OBJ_id_pe + ".8"; + + public final static int NID_sbgp_routerIdentifier = 292; + public final static String SN_sbgp_routerIdentifier = "sbgp-routerIdentifier"; + public final static String OBJ_sbgp_routerIdentifier = OBJ_id_pe + ".9"; + + public final static int NID_textNotice = 293; + public final static String SN_textNotice = "textNotice"; + public final static String OBJ_textNotice = OBJ_id_qt + ".3"; + + public final static int NID_ipsecEndSystem = 294; + public final static String SN_ipsecEndSystem = "ipsecEndSystem"; + public final static String LN_ipsecEndSystem = "IPSec End System"; + public final static String OBJ_ipsecEndSystem = OBJ_id_kp + ".5"; + + public final static int NID_ipsecTunnel = 295; + public final static String SN_ipsecTunnel = "ipsecTunnel"; + public final static String LN_ipsecTunnel = "IPSec Tunnel"; + public final static String OBJ_ipsecTunnel = OBJ_id_kp + ".6"; + + public final static int NID_ipsecUser = 296; + public final static String SN_ipsecUser = "ipsecUser"; + public final static String LN_ipsecUser = "IPSec User"; + public final static String OBJ_ipsecUser = OBJ_id_kp + ".7"; + + public final static int NID_dvcs = 297; + public final static String SN_dvcs = "DVCS"; + public final static String LN_dvcs = "dvcs"; + public final static String OBJ_dvcs = OBJ_id_kp + ".10"; + + public final static int NID_id_it_caProtEncCert = 298; + public final static String SN_id_it_caProtEncCert = "id-it-caProtEncCert"; + public final static String OBJ_id_it_caProtEncCert = OBJ_id_it + ".1"; + + public final static int NID_id_it_signKeyPairTypes = 299; + public final static String SN_id_it_signKeyPairTypes = "id-it-signKeyPairTypes"; + public final static String OBJ_id_it_signKeyPairTypes = OBJ_id_it + ".2"; + + public final static int NID_id_it_encKeyPairTypes = 300; + public final static String SN_id_it_encKeyPairTypes = "id-it-encKeyPairTypes"; + public final static String OBJ_id_it_encKeyPairTypes = OBJ_id_it + ".3"; + + public final static int NID_id_it_preferredSymmAlg = 301; + public final static String SN_id_it_preferredSymmAlg = "id-it-preferredSymmAlg"; + public final static String OBJ_id_it_preferredSymmAlg = OBJ_id_it + ".4"; + + public final static int NID_id_it_caKeyUpdateInfo = 302; + public final static String SN_id_it_caKeyUpdateInfo = "id-it-caKeyUpdateInfo"; + public final static String OBJ_id_it_caKeyUpdateInfo = OBJ_id_it + ".5"; + + public final static int NID_id_it_currentCRL = 303; + public final static String SN_id_it_currentCRL = "id-it-currentCRL"; + public final static String OBJ_id_it_currentCRL = OBJ_id_it + ".6"; + + public final static int NID_id_it_unsupportedOIDs = 304; + public final static String SN_id_it_unsupportedOIDs = "id-it-unsupportedOIDs"; + public final static String OBJ_id_it_unsupportedOIDs = OBJ_id_it + ".7"; + + public final static int NID_id_it_subscriptionRequest = 305; + public final static String SN_id_it_subscriptionRequest = "id-it-subscriptionRequest"; + public final static String OBJ_id_it_subscriptionRequest = OBJ_id_it + ".8"; + + public final static int NID_id_it_subscriptionResponse = 306; + public final static String SN_id_it_subscriptionResponse = "id-it-subscriptionResponse"; + public final static String OBJ_id_it_subscriptionResponse = OBJ_id_it + ".9"; + + public final static int NID_id_it_keyPairParamReq = 307; + public final static String SN_id_it_keyPairParamReq = "id-it-keyPairParamReq"; + public final static String OBJ_id_it_keyPairParamReq = OBJ_id_it + ".10"; + + public final static int NID_id_it_keyPairParamRep = 308; + public final static String SN_id_it_keyPairParamRep = "id-it-keyPairParamRep"; + public final static String OBJ_id_it_keyPairParamRep = OBJ_id_it + ".11"; + + public final static int NID_id_it_revPassphrase = 309; + public final static String SN_id_it_revPassphrase = "id-it-revPassphrase"; + public final static String OBJ_id_it_revPassphrase = OBJ_id_it + ".12"; + + public final static int NID_id_it_implicitConfirm = 310; + public final static String SN_id_it_implicitConfirm = "id-it-implicitConfirm"; + public final static String OBJ_id_it_implicitConfirm = OBJ_id_it + ".13"; + + public final static int NID_id_it_confirmWaitTime = 311; + public final static String SN_id_it_confirmWaitTime = "id-it-confirmWaitTime"; + public final static String OBJ_id_it_confirmWaitTime = OBJ_id_it + ".14"; + + public final static int NID_id_it_origPKIMessage = 312; + public final static String SN_id_it_origPKIMessage = "id-it-origPKIMessage"; + public final static String OBJ_id_it_origPKIMessage = OBJ_id_it + ".15"; + + public final static int NID_id_regCtrl = 313; + public final static String SN_id_regCtrl = "id-regCtrl"; + public final static String OBJ_id_regCtrl = OBJ_id_pkip + ".1"; + + public final static int NID_id_regInfo = 314; + public final static String SN_id_regInfo = "id-regInfo"; + public final static String OBJ_id_regInfo = OBJ_id_pkip + ".2"; + + public final static int NID_id_regCtrl_regToken = 315; + public final static String SN_id_regCtrl_regToken = "id-regCtrl-regToken"; + public final static String OBJ_id_regCtrl_regToken = OBJ_id_regCtrl + ".1"; + + public final static int NID_id_regCtrl_authenticator = 316; + public final static String SN_id_regCtrl_authenticator = "id-regCtrl-authenticator"; + public final static String OBJ_id_regCtrl_authenticator = OBJ_id_regCtrl + ".2"; + + public final static int NID_id_regCtrl_pkiPublicationInfo = 317; + public final static String SN_id_regCtrl_pkiPublicationInfo = "id-regCtrl-pkiPublicationInfo"; + public final static String OBJ_id_regCtrl_pkiPublicationInfo = OBJ_id_regCtrl + ".3"; + + public final static int NID_id_regCtrl_pkiArchiveOptions = 318; + public final static String SN_id_regCtrl_pkiArchiveOptions = "id-regCtrl-pkiArchiveOptions"; + public final static String OBJ_id_regCtrl_pkiArchiveOptions = OBJ_id_regCtrl + ".4"; + + public final static int NID_id_regCtrl_oldCertID = 319; + public final static String SN_id_regCtrl_oldCertID = "id-regCtrl-oldCertID"; + public final static String OBJ_id_regCtrl_oldCertID = OBJ_id_regCtrl + ".5"; + + public final static int NID_id_regCtrl_protocolEncrKey = 320; + public final static String SN_id_regCtrl_protocolEncrKey = "id-regCtrl-protocolEncrKey"; + public final static String OBJ_id_regCtrl_protocolEncrKey = OBJ_id_regCtrl + ".6"; + + public final static int NID_id_regInfo_utf8Pairs = 321; + public final static String SN_id_regInfo_utf8Pairs = "id-regInfo-utf8Pairs"; + public final static String OBJ_id_regInfo_utf8Pairs = OBJ_id_regInfo + ".1"; + + public final static int NID_id_regInfo_certReq = 322; + public final static String SN_id_regInfo_certReq = "id-regInfo-certReq"; + public final static String OBJ_id_regInfo_certReq = OBJ_id_regInfo + ".2"; + + public final static int NID_id_alg_des40 = 323; + public final static String SN_id_alg_des40 = "id-alg-des40"; + public final static String OBJ_id_alg_des40 = OBJ_id_alg + ".1"; + + public final static int NID_id_alg_noSignature = 324; + public final static String SN_id_alg_noSignature = "id-alg-noSignature"; + public final static String OBJ_id_alg_noSignature = OBJ_id_alg + ".2"; + + public final static int NID_id_alg_dh_sig_hmac_sha1 = 325; + public final static String SN_id_alg_dh_sig_hmac_sha1 = "id-alg-dh-sig-hmac-sha1"; + public final static String OBJ_id_alg_dh_sig_hmac_sha1 = OBJ_id_alg + ".3"; + + public final static int NID_id_alg_dh_pop = 326; + public final static String SN_id_alg_dh_pop = "id-alg-dh-pop"; + public final static String OBJ_id_alg_dh_pop = OBJ_id_alg + ".4"; + + public final static int NID_id_cmc_statusInfo = 327; + public final static String SN_id_cmc_statusInfo = "id-cmc-statusInfo"; + public final static String OBJ_id_cmc_statusInfo = OBJ_id_cmc + ".1"; + + public final static int NID_id_cmc_identification = 328; + public final static String SN_id_cmc_identification = "id-cmc-identification"; + public final static String OBJ_id_cmc_identification = OBJ_id_cmc + ".2"; + + public final static int NID_id_cmc_identityProof = 329; + public final static String SN_id_cmc_identityProof = "id-cmc-identityProof"; + public final static String OBJ_id_cmc_identityProof = OBJ_id_cmc + ".3"; + + public final static int NID_id_cmc_dataReturn = 330; + public final static String SN_id_cmc_dataReturn = "id-cmc-dataReturn"; + public final static String OBJ_id_cmc_dataReturn = OBJ_id_cmc + ".4"; + + public final static int NID_id_cmc_transactionId = 331; + public final static String SN_id_cmc_transactionId = "id-cmc-transactionId"; + public final static String OBJ_id_cmc_transactionId = OBJ_id_cmc + ".5"; + + public final static int NID_id_cmc_senderNonce = 332; + public final static String SN_id_cmc_senderNonce = "id-cmc-senderNonce"; + public final static String OBJ_id_cmc_senderNonce = OBJ_id_cmc + ".6"; + + public final static int NID_id_cmc_recipientNonce = 333; + public final static String SN_id_cmc_recipientNonce = "id-cmc-recipientNonce"; + public final static String OBJ_id_cmc_recipientNonce = OBJ_id_cmc + ".7"; + + public final static int NID_id_cmc_addExtensions = 334; + public final static String SN_id_cmc_addExtensions = "id-cmc-addExtensions"; + public final static String OBJ_id_cmc_addExtensions = OBJ_id_cmc + ".8"; + + public final static int NID_id_cmc_encryptedPOP = 335; + public final static String SN_id_cmc_encryptedPOP = "id-cmc-encryptedPOP"; + public final static String OBJ_id_cmc_encryptedPOP = OBJ_id_cmc + ".9"; + + public final static int NID_id_cmc_decryptedPOP = 336; + public final static String SN_id_cmc_decryptedPOP = "id-cmc-decryptedPOP"; + public final static String OBJ_id_cmc_decryptedPOP = OBJ_id_cmc + ".10"; + + public final static int NID_id_cmc_lraPOPWitness = 337; + public final static String SN_id_cmc_lraPOPWitness = "id-cmc-lraPOPWitness"; + public final static String OBJ_id_cmc_lraPOPWitness = OBJ_id_cmc + ".11"; + + public final static int NID_id_cmc_getCert = 338; + public final static String SN_id_cmc_getCert = "id-cmc-getCert"; + public final static String OBJ_id_cmc_getCert = OBJ_id_cmc + ".15"; + + public final static int NID_id_cmc_getCRL = 339; + public final static String SN_id_cmc_getCRL = "id-cmc-getCRL"; + public final static String OBJ_id_cmc_getCRL = OBJ_id_cmc + ".16"; + + public final static int NID_id_cmc_revokeRequest = 340; + public final static String SN_id_cmc_revokeRequest = "id-cmc-revokeRequest"; + public final static String OBJ_id_cmc_revokeRequest = OBJ_id_cmc + ".17"; + + public final static int NID_id_cmc_regInfo = 341; + public final static String SN_id_cmc_regInfo = "id-cmc-regInfo"; + public final static String OBJ_id_cmc_regInfo = OBJ_id_cmc + ".18"; + + public final static int NID_id_cmc_responseInfo = 342; + public final static String SN_id_cmc_responseInfo = "id-cmc-responseInfo"; + public final static String OBJ_id_cmc_responseInfo = OBJ_id_cmc + ".19"; + + public final static int NID_id_cmc_queryPending = 343; + public final static String SN_id_cmc_queryPending = "id-cmc-queryPending"; + public final static String OBJ_id_cmc_queryPending = OBJ_id_cmc + ".21"; + + public final static int NID_id_cmc_popLinkRandom = 344; + public final static String SN_id_cmc_popLinkRandom = "id-cmc-popLinkRandom"; + public final static String OBJ_id_cmc_popLinkRandom = OBJ_id_cmc + ".22"; + + public final static int NID_id_cmc_popLinkWitness = 345; + public final static String SN_id_cmc_popLinkWitness = "id-cmc-popLinkWitness"; + public final static String OBJ_id_cmc_popLinkWitness = OBJ_id_cmc + ".23"; + + public final static int NID_id_cmc_confirmCertAcceptance = 346; + public final static String SN_id_cmc_confirmCertAcceptance = "id-cmc-confirmCertAcceptance"; + public final static String OBJ_id_cmc_confirmCertAcceptance = OBJ_id_cmc + ".24"; + + public final static int NID_id_on_personalData = 347; + public final static String SN_id_on_personalData = "id-on-personalData"; + public final static String OBJ_id_on_personalData = OBJ_id_on + ".1"; + + public final static int NID_id_pda_dateOfBirth = 348; + public final static String SN_id_pda_dateOfBirth = "id-pda-dateOfBirth"; + public final static String OBJ_id_pda_dateOfBirth = OBJ_id_pda + ".1"; + + public final static int NID_id_pda_placeOfBirth = 349; + public final static String SN_id_pda_placeOfBirth = "id-pda-placeOfBirth"; + public final static String OBJ_id_pda_placeOfBirth = OBJ_id_pda + ".2"; + + public final static int NID_id_pda_gender = 351; + public final static String SN_id_pda_gender = "id-pda-gender"; + public final static String OBJ_id_pda_gender = OBJ_id_pda + ".3"; + + public final static int NID_id_pda_countryOfCitizenship = 352; + public final static String SN_id_pda_countryOfCitizenship = "id-pda-countryOfCitizenship"; + public final static String OBJ_id_pda_countryOfCitizenship = OBJ_id_pda + ".4"; + + public final static int NID_id_pda_countryOfResidence = 353; + public final static String SN_id_pda_countryOfResidence = "id-pda-countryOfResidence"; + public final static String OBJ_id_pda_countryOfResidence = OBJ_id_pda + ".5"; + + public final static int NID_id_aca_authenticationInfo = 354; + public final static String SN_id_aca_authenticationInfo = "id-aca-authenticationInfo"; + public final static String OBJ_id_aca_authenticationInfo = OBJ_id_aca + ".1"; + + public final static int NID_id_aca_accessIdentity = 355; + public final static String SN_id_aca_accessIdentity = "id-aca-accessIdentity"; + public final static String OBJ_id_aca_accessIdentity = OBJ_id_aca + ".2"; + + public final static int NID_id_aca_chargingIdentity = 356; + public final static String SN_id_aca_chargingIdentity = "id-aca-chargingIdentity"; + public final static String OBJ_id_aca_chargingIdentity = OBJ_id_aca + ".3"; + + public final static int NID_id_aca_group = 357; + public final static String SN_id_aca_group = "id-aca-group"; + public final static String OBJ_id_aca_group = OBJ_id_aca + ".4"; + + public final static int NID_id_aca_role = 358; + public final static String SN_id_aca_role = "id-aca-role"; + public final static String OBJ_id_aca_role = OBJ_id_aca + ".5"; + + public final static int NID_id_qcs_pkixQCSyntax_v1 = 359; + public final static String SN_id_qcs_pkixQCSyntax_v1 = "id-qcs-pkixQCSyntax-v1"; + public final static String OBJ_id_qcs_pkixQCSyntax_v1 = OBJ_id_qcs + ".1"; + + public final static int NID_id_cct_crs = 360; + public final static String SN_id_cct_crs = "id-cct-crs"; + public final static String OBJ_id_cct_crs = OBJ_id_cct + ".1"; + + public final static int NID_id_cct_PKIData = 361; + public final static String SN_id_cct_PKIData = "id-cct-PKIData"; + public final static String OBJ_id_cct_PKIData = OBJ_id_cct + ".2"; + + public final static int NID_id_cct_PKIResponse = 362; + public final static String SN_id_cct_PKIResponse = "id-cct-PKIResponse"; + public final static String OBJ_id_cct_PKIResponse = OBJ_id_cct + ".3"; + + public final static int NID_ad_timeStamping = 363; + public final static String SN_ad_timeStamping = "ad_timestamping"; + public final static String LN_ad_timeStamping = "AD Time Stamping"; + public final static String OBJ_ad_timeStamping = OBJ_id_ad + ".3"; + + public final static int NID_ad_dvcs = 364; + public final static String SN_ad_dvcs = "AD_DVCS"; + public final static String LN_ad_dvcs = "ad dvcs"; + public final static String OBJ_ad_dvcs = OBJ_id_ad + ".4"; + + public final static int NID_id_pkix_OCSP_basic = 365; + public final static String SN_id_pkix_OCSP_basic = "basicOCSPResponse"; + public final static String LN_id_pkix_OCSP_basic = "Basic OCSP Response"; + public final static String OBJ_id_pkix_OCSP_basic = OBJ_id_pkix_OCSP + ".1"; + + public final static int NID_id_pkix_OCSP_Nonce = 366; + public final static String SN_id_pkix_OCSP_Nonce = "Nonce"; + public final static String LN_id_pkix_OCSP_Nonce = "OCSP Nonce"; + public final static String OBJ_id_pkix_OCSP_Nonce = OBJ_id_pkix_OCSP + ".2"; + + public final static int NID_id_pkix_OCSP_CrlID = 367; + public final static String SN_id_pkix_OCSP_CrlID = "CrlID"; + public final static String LN_id_pkix_OCSP_CrlID = "OCSP CRL ID"; + public final static String OBJ_id_pkix_OCSP_CrlID = OBJ_id_pkix_OCSP + ".3"; + + public final static int NID_id_pkix_OCSP_acceptableResponses = 368; + public final static String SN_id_pkix_OCSP_acceptableResponses = "acceptableResponses"; + public final static String LN_id_pkix_OCSP_acceptableResponses = "Acceptable OCSP Responses"; + public final static String OBJ_id_pkix_OCSP_acceptableResponses = OBJ_id_pkix_OCSP + ".4"; + + public final static int NID_id_pkix_OCSP_noCheck = 369; + public final static String SN_id_pkix_OCSP_noCheck = "noCheck"; + public final static String LN_id_pkix_OCSP_noCheck = "OCSP No Check"; + public final static String OBJ_id_pkix_OCSP_noCheck = OBJ_id_pkix_OCSP + ".5"; + + public final static int NID_id_pkix_OCSP_archiveCutoff = 370; + public final static String SN_id_pkix_OCSP_archiveCutoff = "archiveCutoff"; + public final static String LN_id_pkix_OCSP_archiveCutoff = "OCSP Archive Cutoff"; + public final static String OBJ_id_pkix_OCSP_archiveCutoff = OBJ_id_pkix_OCSP + ".6"; + + public final static int NID_id_pkix_OCSP_serviceLocator = 371; + public final static String SN_id_pkix_OCSP_serviceLocator = "serviceLocator"; + public final static String LN_id_pkix_OCSP_serviceLocator = "OCSP Service Locator"; + public final static String OBJ_id_pkix_OCSP_serviceLocator = OBJ_id_pkix_OCSP + ".7"; + + public final static int NID_id_pkix_OCSP_extendedStatus = 372; + public final static String SN_id_pkix_OCSP_extendedStatus = "extendedStatus"; + public final static String LN_id_pkix_OCSP_extendedStatus = "Extended OCSP Status"; + public final static String OBJ_id_pkix_OCSP_extendedStatus = OBJ_id_pkix_OCSP + ".8"; + + public final static int NID_id_pkix_OCSP_valid = 373; + public final static String SN_id_pkix_OCSP_valid = "valid"; + public final static String OBJ_id_pkix_OCSP_valid = OBJ_id_pkix_OCSP + ".9"; + + public final static int NID_id_pkix_OCSP_path = 374; + public final static String SN_id_pkix_OCSP_path = "path"; + public final static String OBJ_id_pkix_OCSP_path = OBJ_id_pkix_OCSP + ".10"; + + public final static int NID_id_pkix_OCSP_trustRoot = 375; + public final static String SN_id_pkix_OCSP_trustRoot = "trustRoot"; + public final static String LN_id_pkix_OCSP_trustRoot = "Trust Root"; + public final static String OBJ_id_pkix_OCSP_trustRoot = OBJ_id_pkix_OCSP + ".11"; + + public final static int NID_rsaSignature = 377; + public final static String SN_rsaSignature = "rsaSignature"; + public final static String OBJ_rsaSignature = OBJ_algorithm + ".11"; + + public final static int NID_Directory = 382; + public final static String SN_Directory = "directory"; + public final static String LN_Directory = "Directory"; + public final static String OBJ_Directory = OBJ_internet + ".1"; + + public final static int NID_Management = 383; + public final static String SN_Management = "mgmt"; + public final static String LN_Management = "Management"; + public final static String OBJ_Management = OBJ_internet + ".2"; + + public final static int NID_Experimental = 384; + public final static String SN_Experimental = "experimental"; + public final static String LN_Experimental = "Experimental"; + public final static String OBJ_Experimental = OBJ_internet + ".3"; + + public final static int NID_Private = 385; + public final static String SN_Private = "private"; + public final static String LN_Private = "Private"; + public final static String OBJ_Private = OBJ_internet + ".4"; + + public final static int NID_Security = 386; + public final static String SN_Security = "security"; + public final static String LN_Security = "Security"; + public final static String OBJ_Security = OBJ_internet + ".5"; + + public final static int NID_SNMPv2 = 387; + public final static String SN_SNMPv2 = "snmpv2"; + public final static String LN_SNMPv2 = "SNMPv2"; + public final static String OBJ_SNMPv2 = OBJ_internet + ".6"; + + public final static int NID_Mail = 388; + public final static String LN_Mail = "Mail"; + public final static String OBJ_Mail = OBJ_internet + ".7"; + + public final static int NID_Enterprises = 389; + public final static String SN_Enterprises = "enterprises"; + public final static String LN_Enterprises = "Enterprises"; + public final static String OBJ_Enterprises = OBJ_Private + ".1"; + + public final static int NID_dcObject = 390; + public final static String SN_dcObject = "dcobject"; + public final static String LN_dcObject = "dcObject"; + public final static String OBJ_dcObject = OBJ_Enterprises + ".1466.344"; + + public final static int NID_itu_t = 645; + public final static String SN_itu_t = "ITU-T"; + public final static String LN_itu_t = "itu-t"; + public final static String OBJ_itu_t = "0"; + + public final static int NID_data = 434; + public final static String SN_data = "data"; + public final static String OBJ_data = OBJ_itu_t + ".9"; + + public final static int NID_pss = 435; + public final static String SN_pss = "pss"; + public final static String OBJ_pss = OBJ_data + ".2342"; + + public final static int NID_ucl = 436; + public final static String SN_ucl = "ucl"; + public final static String OBJ_ucl = OBJ_pss + ".19200300"; + + public final static int NID_pilot = 437; + public final static String SN_pilot = "pilot"; + public final static String OBJ_pilot = OBJ_ucl + ".100"; + + public final static int NID_pilotAttributeType = 438; + public final static String LN_pilotAttributeType = "pilotAttributeType"; + public final static String OBJ_pilotAttributeType = OBJ_pilot + ".1"; + + public final static int NID_domainComponent = 391; + public final static String SN_domainComponent = "DC"; + public final static String LN_domainComponent = "domainComponent"; + public final static String OBJ_domainComponent = OBJ_pilotAttributeType + ".25"; + + public final static int NID_pilotObjectClass = 440; + public final static String LN_pilotObjectClass = "pilotObjectClass"; + public final static String OBJ_pilotObjectClass = OBJ_pilot + ".4"; + + public final static int NID_Domain = 392; + public final static String SN_Domain = "domain"; + public final static String LN_Domain = "Domain"; + public final static String OBJ_Domain = OBJ_pilotObjectClass + ".13"; + + public final static int NID_joint_iso_ccitt = 393; + public final static String OBJ_joint_iso_ccitt = "OBJ_joint_iso_itu_t"; + + public final static int NID_selected_attribute_types = 394; + public final static String SN_selected_attribute_types = "selected-attribute-types"; + public final static String LN_selected_attribute_types = "Selected Attribute Types"; + public final static String OBJ_selected_attribute_types = OBJ_joint_iso_itu_t + ".5.1.5"; + + public final static int NID_clearance = 395; + public final static String SN_clearance = "clearance"; + public final static String OBJ_clearance = OBJ_selected_attribute_types + ".55"; + + public final static int NID_md4WithRSAEncryption = 396; + public final static String SN_md4WithRSAEncryption = "RSA-MD4"; + public final static String LN_md4WithRSAEncryption = "md4WithRSAEncryption"; + public final static String OBJ_md4WithRSAEncryption = OBJ_pkcs1 + ".3"; + + public final static int NID_ac_proxying = 397; + public final static String SN_ac_proxying = "ac-proxying"; + public final static String OBJ_ac_proxying = OBJ_id_pe + ".10"; + + public final static int NID_sinfo_access = 398; + public final static String SN_sinfo_access = "subjectInfoAccess"; + public final static String LN_sinfo_access = "Subject Information Access"; + public final static String OBJ_sinfo_access = OBJ_id_pe + ".11"; + + public final static int NID_id_aca_encAttrs = 399; + public final static String SN_id_aca_encAttrs = "id-aca-encAttrs"; + public final static String OBJ_id_aca_encAttrs = OBJ_id_aca + ".6"; + + public final static int NID_role = 400; + public final static String SN_role = "role"; + public final static String LN_role = "role"; + public final static String OBJ_role = OBJ_X509 + ".72"; + + public final static int NID_policy_constraints = 401; + public final static String SN_policy_constraints = "policyConstraints"; + public final static String LN_policy_constraints = "X509v3 Policy Constraints"; + public final static String OBJ_policy_constraints = OBJ_id_ce + ".36"; + + public final static int NID_target_information = 402; + public final static String SN_target_information = "targetInformation"; + public final static String LN_target_information = "X509v3 AC Targeting"; + public final static String OBJ_target_information = OBJ_id_ce + ".55"; + + public final static int NID_no_rev_avail = 403; + public final static String SN_no_rev_avail = "noRevAvail"; + public final static String LN_no_rev_avail = "X509v3 No Revocation Available"; + public final static String OBJ_no_rev_avail = OBJ_id_ce + ".56"; + + public final static int NID_ccitt = 404; + public final static String OBJ_ccitt = "OBJ_itu_t"; + + public final static int NID_X9_62_prime_field = 406; + public final static String SN_X9_62_prime_field = "prime-field"; + public final static String OBJ_X9_62_prime_field = OBJ_X9_62_id_fieldType + ".1"; + + public final static int NID_X9_62_characteristic_two_field = 407; + public final static String SN_X9_62_characteristic_two_field = "characteristic-two-field"; + public final static String OBJ_X9_62_characteristic_two_field = OBJ_X9_62_id_fieldType + ".2"; + + public final static int NID_X9_62_id_ecPublicKey = 408; + public final static String SN_X9_62_id_ecPublicKey = "id-ecPublicKey"; + public final static String OBJ_X9_62_id_ecPublicKey = OBJ_X9_62_id_publicKeyType + ".1"; + + public final static int NID_X9_62_prime192v1 = 409; + public final static String SN_X9_62_prime192v1 = "prime192v1"; + public final static String OBJ_X9_62_prime192v1 = OBJ_X9_62_primeCurve + ".1"; + + public final static int NID_X9_62_prime192v2 = 410; + public final static String SN_X9_62_prime192v2 = "prime192v2"; + public final static String OBJ_X9_62_prime192v2 = OBJ_X9_62_primeCurve + ".2"; + + public final static int NID_X9_62_prime192v3 = 411; + public final static String SN_X9_62_prime192v3 = "prime192v3"; + public final static String OBJ_X9_62_prime192v3 = OBJ_X9_62_primeCurve + ".3"; + + public final static int NID_X9_62_prime239v1 = 412; + public final static String SN_X9_62_prime239v1 = "prime239v1"; + public final static String OBJ_X9_62_prime239v1 = OBJ_X9_62_primeCurve + ".4"; + + public final static int NID_X9_62_prime239v2 = 413; + public final static String SN_X9_62_prime239v2 = "prime239v2"; + public final static String OBJ_X9_62_prime239v2 = OBJ_X9_62_primeCurve + ".5"; + + public final static int NID_X9_62_prime239v3 = 414; + public final static String SN_X9_62_prime239v3 = "prime239v3"; + public final static String OBJ_X9_62_prime239v3 = OBJ_X9_62_primeCurve + ".6"; + + public final static int NID_X9_62_prime256v1 = 415; + public final static String SN_X9_62_prime256v1 = "prime256v1"; + public final static String OBJ_X9_62_prime256v1 = OBJ_X9_62_primeCurve + ".7"; + + public final static int NID_ecdsa_with_SHA1 = 416; + public final static String SN_ecdsa_with_SHA1 = "ecdsa-with-SHA1"; + public final static String OBJ_ecdsa_with_SHA1 = OBJ_X9_62_id_ecSigType + ".1"; + + public final static int NID_ms_csp_name = 417; + public final static String SN_ms_csp_name = "CSPName"; + public final static String LN_ms_csp_name = "Microsoft CSP Name"; + public final static String OBJ_ms_csp_name = "1.3.6.1.4.1.311.17.1"; + + public final static int NID_aes_128_ecb = 418; + public final static String SN_aes_128_ecb = "AES-128-ECB"; + public final static String LN_aes_128_ecb = "aes-128-ecb"; + public final static String OBJ_aes_128_ecb = OBJ_aes + ".1"; + + public final static int NID_aes_128_cbc = 419; + public final static String SN_aes_128_cbc = "AES-128-CBC"; + public final static String LN_aes_128_cbc = "aes-128-cbc"; + public final static String OBJ_aes_128_cbc = OBJ_aes + ".2"; + + public final static int NID_aes_128_ofb128 = 420; + public final static String SN_aes_128_ofb128 = "AES-128-OFB"; + public final static String LN_aes_128_ofb128 = "aes-128-ofb"; + public final static String OBJ_aes_128_ofb128 = OBJ_aes + ".3"; + + public final static int NID_aes_128_cfb128 = 421; + public final static String SN_aes_128_cfb128 = "AES-128-CFB"; + public final static String LN_aes_128_cfb128 = "aes-128-cfb"; + public final static String OBJ_aes_128_cfb128 = OBJ_aes + ".4"; + + public final static int NID_aes_192_ecb = 422; + public final static String SN_aes_192_ecb = "AES-192-ECB"; + public final static String LN_aes_192_ecb = "aes-192-ecb"; + public final static String OBJ_aes_192_ecb = OBJ_aes + ".21"; + + public final static int NID_aes_192_cbc = 423; + public final static String SN_aes_192_cbc = "AES-192-CBC"; + public final static String LN_aes_192_cbc = "aes-192-cbc"; + public final static String OBJ_aes_192_cbc = OBJ_aes + ".22"; + + public final static int NID_aes_192_ofb128 = 424; + public final static String SN_aes_192_ofb128 = "AES-192-OFB"; + public final static String LN_aes_192_ofb128 = "aes-192-ofb"; + public final static String OBJ_aes_192_ofb128 = OBJ_aes + ".23"; + + public final static int NID_aes_192_cfb128 = 425; + public final static String SN_aes_192_cfb128 = "AES-192-CFB"; + public final static String LN_aes_192_cfb128 = "aes-192-cfb"; + public final static String OBJ_aes_192_cfb128 = OBJ_aes + ".24"; + + public final static int NID_aes_256_ecb = 426; + public final static String SN_aes_256_ecb = "AES-256-ECB"; + public final static String LN_aes_256_ecb = "aes-256-ecb"; + public final static String OBJ_aes_256_ecb = OBJ_aes + ".41"; + + public final static int NID_aes_256_cbc = 427; + public final static String SN_aes_256_cbc = "AES-256-CBC"; + public final static String LN_aes_256_cbc = "aes-256-cbc"; + public final static String OBJ_aes_256_cbc = OBJ_aes + ".42"; + + public final static int NID_aes_256_ofb128 = 428; + public final static String SN_aes_256_ofb128 = "AES-256-OFB"; + public final static String LN_aes_256_ofb128 = "aes-256-ofb"; + public final static String OBJ_aes_256_ofb128 = OBJ_aes + ".43"; + + public final static int NID_aes_256_cfb128 = 429; + public final static String SN_aes_256_cfb128 = "AES-256-CFB"; + public final static String LN_aes_256_cfb128 = "aes-256-cfb"; + public final static String OBJ_aes_256_cfb128 = OBJ_aes + ".44"; + + public final static int NID_hold_instruction_code = 430; + public final static String SN_hold_instruction_code = "holdInstructionCode"; + public final static String LN_hold_instruction_code = "Hold Instruction Code"; + public final static String OBJ_hold_instruction_code = OBJ_id_ce + ".23"; + + public final static int NID_hold_instruction_none = 431; + public final static String SN_hold_instruction_none = "holdInstructionNone"; + public final static String LN_hold_instruction_none = "Hold Instruction None"; + public final static String OBJ_hold_instruction_none = OBJ_holdInstruction + ".1"; + + public final static int NID_hold_instruction_call_issuer = 432; + public final static String SN_hold_instruction_call_issuer = "holdInstructionCallIssuer"; + public final static String LN_hold_instruction_call_issuer = "Hold Instruction Call Issuer"; + public final static String OBJ_hold_instruction_call_issuer = OBJ_holdInstruction + ".2"; + + public final static int NID_hold_instruction_reject = 433; + public final static String SN_hold_instruction_reject = "holdInstructionReject"; + public final static String LN_hold_instruction_reject = "Hold Instruction Reject"; + public final static String OBJ_hold_instruction_reject = OBJ_holdInstruction + ".3"; + + public final static int NID_pilotAttributeSyntax = 439; + public final static String LN_pilotAttributeSyntax = "pilotAttributeSyntax"; + public final static String OBJ_pilotAttributeSyntax = OBJ_pilot + ".3"; + + public final static int NID_pilotGroups = 441; + public final static String LN_pilotGroups = "pilotGroups"; + public final static String OBJ_pilotGroups = OBJ_pilot + ".10"; + + public final static int NID_iA5StringSyntax = 442; + public final static String LN_iA5StringSyntax = "iA5StringSyntax"; + public final static String OBJ_iA5StringSyntax = OBJ_pilotAttributeSyntax + ".4"; + + public final static int NID_caseIgnoreIA5StringSyntax = 443; + public final static String LN_caseIgnoreIA5StringSyntax = "caseIgnoreIA5StringSyntax"; + public final static String OBJ_caseIgnoreIA5StringSyntax = OBJ_pilotAttributeSyntax + ".5"; + + public final static int NID_pilotObject = 444; + public final static String LN_pilotObject = "pilotObject"; + public final static String OBJ_pilotObject = OBJ_pilotObjectClass + ".3"; + + public final static int NID_pilotPerson = 445; + public final static String LN_pilotPerson = "pilotPerson"; + public final static String OBJ_pilotPerson = OBJ_pilotObjectClass + ".4"; + + public final static int NID_account = 446; + public final static String SN_account = "account"; + public final static String OBJ_account = OBJ_pilotObjectClass + ".5"; + + public final static int NID_document = 447; + public final static String SN_document = "document"; + public final static String OBJ_document = OBJ_pilotObjectClass + ".6"; + + public final static int NID_room = 448; + public final static String SN_room = "room"; + public final static String OBJ_room = OBJ_pilotObjectClass + ".7"; + + public final static int NID_documentSeries = 449; + public final static String LN_documentSeries = "documentSeries"; + public final static String OBJ_documentSeries = OBJ_pilotObjectClass + ".9"; + + public final static int NID_rFC822localPart = 450; + public final static String LN_rFC822localPart = "rFC822localPart"; + public final static String OBJ_rFC822localPart = OBJ_pilotObjectClass + ".14"; + + public final static int NID_dNSDomain = 451; + public final static String LN_dNSDomain = "dNSDomain"; + public final static String OBJ_dNSDomain = OBJ_pilotObjectClass + ".15"; + + public final static int NID_domainRelatedObject = 452; + public final static String LN_domainRelatedObject = "domainRelatedObject"; + public final static String OBJ_domainRelatedObject = OBJ_pilotObjectClass + ".17"; + + public final static int NID_friendlyCountry = 453; + public final static String LN_friendlyCountry = "friendlyCountry"; + public final static String OBJ_friendlyCountry = OBJ_pilotObjectClass + ".18"; + + public final static int NID_simpleSecurityObject = 454; + public final static String LN_simpleSecurityObject = "simpleSecurityObject"; + public final static String OBJ_simpleSecurityObject = OBJ_pilotObjectClass + ".19"; + + public final static int NID_pilotOrganization = 455; + public final static String LN_pilotOrganization = "pilotOrganization"; + public final static String OBJ_pilotOrganization = OBJ_pilotObjectClass + ".20"; + + public final static int NID_pilotDSA = 456; + public final static String LN_pilotDSA = "pilotDSA"; + public final static String OBJ_pilotDSA = OBJ_pilotObjectClass + ".21"; + + public final static int NID_qualityLabelledData = 457; + public final static String LN_qualityLabelledData = "qualityLabelledData"; + public final static String OBJ_qualityLabelledData = OBJ_pilotObjectClass + ".22"; + + public final static int NID_userId = 458; + public final static String SN_userId = "UID"; + public final static String LN_userId = "userId"; + public final static String OBJ_userId = OBJ_pilotAttributeType + ".1"; + + public final static int NID_textEncodedORAddress = 459; + public final static String LN_textEncodedORAddress = "textEncodedORAddress"; + public final static String OBJ_textEncodedORAddress = OBJ_pilotAttributeType + ".2"; + + public final static int NID_rfc822Mailbox = 460; + public final static String SN_rfc822Mailbox = "mail"; + public final static String LN_rfc822Mailbox = "rfc822Mailbox"; + public final static String OBJ_rfc822Mailbox = OBJ_pilotAttributeType + ".3"; + + public final static int NID_info = 461; + public final static String SN_info = "info"; + public final static String OBJ_info = OBJ_pilotAttributeType + ".4"; + + public final static int NID_favouriteDrink = 462; + public final static String LN_favouriteDrink = "favouriteDrink"; + public final static String OBJ_favouriteDrink = OBJ_pilotAttributeType + ".5"; + + public final static int NID_roomNumber = 463; + public final static String LN_roomNumber = "roomNumber"; + public final static String OBJ_roomNumber = OBJ_pilotAttributeType + ".6"; + + public final static int NID_photo = 464; + public final static String SN_photo = "photo"; + public final static String OBJ_photo = OBJ_pilotAttributeType + ".7"; + + public final static int NID_userClass = 465; + public final static String LN_userClass = "userClass"; + public final static String OBJ_userClass = OBJ_pilotAttributeType + ".8"; + + public final static int NID_host = 466; + public final static String SN_host = "host"; + public final static String OBJ_host = OBJ_pilotAttributeType + ".9"; + + public final static int NID_manager = 467; + public final static String SN_manager = "manager"; + public final static String OBJ_manager = OBJ_pilotAttributeType + ".10"; + + public final static int NID_documentIdentifier = 468; + public final static String LN_documentIdentifier = "documentIdentifier"; + public final static String OBJ_documentIdentifier = OBJ_pilotAttributeType + ".11"; + + public final static int NID_documentTitle = 469; + public final static String LN_documentTitle = "documentTitle"; + public final static String OBJ_documentTitle = OBJ_pilotAttributeType + ".12"; + + public final static int NID_documentVersion = 470; + public final static String LN_documentVersion = "documentVersion"; + public final static String OBJ_documentVersion = OBJ_pilotAttributeType + ".13"; + + public final static int NID_documentAuthor = 471; + public final static String LN_documentAuthor = "documentAuthor"; + public final static String OBJ_documentAuthor = OBJ_pilotAttributeType + ".14"; + + public final static int NID_documentLocation = 472; + public final static String LN_documentLocation = "documentLocation"; + public final static String OBJ_documentLocation = OBJ_pilotAttributeType + ".15"; + + public final static int NID_homeTelephoneNumber = 473; + public final static String LN_homeTelephoneNumber = "homeTelephoneNumber"; + public final static String OBJ_homeTelephoneNumber = OBJ_pilotAttributeType + ".20"; + + public final static int NID_secretary = 474; + public final static String SN_secretary = "secretary"; + public final static String OBJ_secretary = OBJ_pilotAttributeType + ".21"; + + public final static int NID_otherMailbox = 475; + public final static String LN_otherMailbox = "otherMailbox"; + public final static String OBJ_otherMailbox = OBJ_pilotAttributeType + ".22"; + + public final static int NID_lastModifiedTime = 476; + public final static String LN_lastModifiedTime = "lastModifiedTime"; + public final static String OBJ_lastModifiedTime = OBJ_pilotAttributeType + ".23"; + + public final static int NID_lastModifiedBy = 477; + public final static String LN_lastModifiedBy = "lastModifiedBy"; + public final static String OBJ_lastModifiedBy = OBJ_pilotAttributeType + ".24"; + + public final static int NID_aRecord = 478; + public final static String LN_aRecord = "aRecord"; + public final static String OBJ_aRecord = OBJ_pilotAttributeType + ".26"; + + public final static int NID_pilotAttributeType27 = 479; + public final static String LN_pilotAttributeType27 = "pilotAttributeType27"; + public final static String OBJ_pilotAttributeType27 = OBJ_pilotAttributeType + ".27"; + + public final static int NID_mXRecord = 480; + public final static String LN_mXRecord = "mXRecord"; + public final static String OBJ_mXRecord = OBJ_pilotAttributeType + ".28"; + + public final static int NID_nSRecord = 481; + public final static String LN_nSRecord = "nSRecord"; + public final static String OBJ_nSRecord = OBJ_pilotAttributeType + ".29"; + + public final static int NID_sOARecord = 482; + public final static String LN_sOARecord = "sOARecord"; + public final static String OBJ_sOARecord = OBJ_pilotAttributeType + ".30"; + + public final static int NID_cNAMERecord = 483; + public final static String LN_cNAMERecord = "cNAMERecord"; + public final static String OBJ_cNAMERecord = OBJ_pilotAttributeType + ".31"; + + public final static int NID_associatedDomain = 484; + public final static String LN_associatedDomain = "associatedDomain"; + public final static String OBJ_associatedDomain = OBJ_pilotAttributeType + ".37"; + + public final static int NID_associatedName = 485; + public final static String LN_associatedName = "associatedName"; + public final static String OBJ_associatedName = OBJ_pilotAttributeType + ".38"; + + public final static int NID_homePostalAddress = 486; + public final static String LN_homePostalAddress = "homePostalAddress"; + public final static String OBJ_homePostalAddress = OBJ_pilotAttributeType + ".39"; + + public final static int NID_personalTitle = 487; + public final static String LN_personalTitle = "personalTitle"; + public final static String OBJ_personalTitle = OBJ_pilotAttributeType + ".40"; + + public final static int NID_mobileTelephoneNumber = 488; + public final static String LN_mobileTelephoneNumber = "mobileTelephoneNumber"; + public final static String OBJ_mobileTelephoneNumber = OBJ_pilotAttributeType + ".41"; + + public final static int NID_pagerTelephoneNumber = 489; + public final static String LN_pagerTelephoneNumber = "pagerTelephoneNumber"; + public final static String OBJ_pagerTelephoneNumber = OBJ_pilotAttributeType + ".42"; + + public final static int NID_friendlyCountryName = 490; + public final static String LN_friendlyCountryName = "friendlyCountryName"; + public final static String OBJ_friendlyCountryName = OBJ_pilotAttributeType + ".43"; + + public final static int NID_organizationalStatus = 491; + public final static String LN_organizationalStatus = "organizationalStatus"; + public final static String OBJ_organizationalStatus = OBJ_pilotAttributeType + ".45"; + + public final static int NID_janetMailbox = 492; + public final static String LN_janetMailbox = "janetMailbox"; + public final static String OBJ_janetMailbox = OBJ_pilotAttributeType + ".46"; + + public final static int NID_mailPreferenceOption = 493; + public final static String LN_mailPreferenceOption = "mailPreferenceOption"; + public final static String OBJ_mailPreferenceOption = OBJ_pilotAttributeType + ".47"; + + public final static int NID_buildingName = 494; + public final static String LN_buildingName = "buildingName"; + public final static String OBJ_buildingName = OBJ_pilotAttributeType + ".48"; + + public final static int NID_dSAQuality = 495; + public final static String LN_dSAQuality = "dSAQuality"; + public final static String OBJ_dSAQuality = OBJ_pilotAttributeType + ".49"; + + public final static int NID_singleLevelQuality = 496; + public final static String LN_singleLevelQuality = "singleLevelQuality"; + public final static String OBJ_singleLevelQuality = OBJ_pilotAttributeType + ".50"; + + public final static int NID_subtreeMinimumQuality = 497; + public final static String LN_subtreeMinimumQuality = "subtreeMinimumQuality"; + public final static String OBJ_subtreeMinimumQuality = OBJ_pilotAttributeType + ".51"; + + public final static int NID_subtreeMaximumQuality = 498; + public final static String LN_subtreeMaximumQuality = "subtreeMaximumQuality"; + public final static String OBJ_subtreeMaximumQuality = OBJ_pilotAttributeType + ".52"; + + public final static int NID_personalSignature = 499; + public final static String LN_personalSignature = "personalSignature"; + public final static String OBJ_personalSignature = OBJ_pilotAttributeType + ".53"; + + public final static int NID_dITRedirect = 500; + public final static String LN_dITRedirect = "dITRedirect"; + public final static String OBJ_dITRedirect = OBJ_pilotAttributeType + ".54"; + + public final static int NID_audio = 501; + public final static String SN_audio = "audio"; + public final static String OBJ_audio = OBJ_pilotAttributeType + ".55"; + + public final static int NID_documentPublisher = 502; + public final static String LN_documentPublisher = "documentPublisher"; + public final static String OBJ_documentPublisher = OBJ_pilotAttributeType + ".56"; + + public final static int NID_x500UniqueIdentifier = 503; + public final static String LN_x500UniqueIdentifier = "x500UniqueIdentifier"; + public final static String OBJ_x500UniqueIdentifier = OBJ_X509 + ".45"; + + public final static int NID_mime_mhs = 504; + public final static String SN_mime_mhs = "mime-mhs"; + public final static String LN_mime_mhs = "MIME MHS"; + public final static String OBJ_mime_mhs = OBJ_Mail + ".1"; + + public final static int NID_mime_mhs_headings = 505; + public final static String SN_mime_mhs_headings = "mime-mhs-headings"; + public final static String LN_mime_mhs_headings = "mime-mhs-headings"; + public final static String OBJ_mime_mhs_headings = OBJ_mime_mhs + ".1"; + + public final static int NID_mime_mhs_bodies = 506; + public final static String SN_mime_mhs_bodies = "mime-mhs-bodies"; + public final static String LN_mime_mhs_bodies = "mime-mhs-bodies"; + public final static String OBJ_mime_mhs_bodies = OBJ_mime_mhs + ".2"; + + public final static int NID_id_hex_partial_message = 507; + public final static String SN_id_hex_partial_message = "id-hex-partial-message"; + public final static String LN_id_hex_partial_message = "id-hex-partial-message"; + public final static String OBJ_id_hex_partial_message = OBJ_mime_mhs_headings + ".1"; + + public final static int NID_id_hex_multipart_message = 508; + public final static String SN_id_hex_multipart_message = "id-hex-multipart-message"; + public final static String LN_id_hex_multipart_message = "id-hex-multipart-message"; + public final static String OBJ_id_hex_multipart_message = OBJ_mime_mhs_headings + ".2"; + + public final static int NID_generationQualifier = 509; + public final static String LN_generationQualifier = "generationQualifier"; + public final static String OBJ_generationQualifier = OBJ_X509 + ".44"; + + public final static int NID_pseudonym = 510; + public final static String LN_pseudonym = "pseudonym"; + public final static String OBJ_pseudonym = OBJ_X509 + ".65"; + + public final static int NID_id_set = 512; + public final static String SN_id_set = "id-set"; + public final static String LN_id_set = "Secure Electronic Transactions"; + public final static String OBJ_id_set = OBJ_international_organizations + ".42"; + + public final static int NID_set_ctype = 513; + public final static String SN_set_ctype = "set-ctype"; + public final static String LN_set_ctype = "content types"; + public final static String OBJ_set_ctype = OBJ_id_set + ".0"; + + public final static int NID_set_msgExt = 514; + public final static String SN_set_msgExt = "set-msgExt"; + public final static String LN_set_msgExt = "message extensions"; + public final static String OBJ_set_msgExt = OBJ_id_set + ".1"; + + public final static int NID_set_attr = 515; + public final static String SN_set_attr = "set-attr"; + public final static String OBJ_set_attr = OBJ_id_set + ".3"; + + public final static int NID_set_policy = 516; + public final static String SN_set_policy = "set-policy"; + public final static String OBJ_set_policy = OBJ_id_set + ".5"; + + public final static int NID_set_certExt = 517; + public final static String SN_set_certExt = "set-certExt"; + public final static String LN_set_certExt = "certificate extensions"; + public final static String OBJ_set_certExt = OBJ_id_set + ".7"; + + public final static int NID_set_brand = 518; + public final static String SN_set_brand = "set-brand"; + public final static String OBJ_set_brand = OBJ_id_set + ".8"; + + public final static int NID_setct_PANData = 519; + public final static String SN_setct_PANData = "setct-PANData"; + public final static String OBJ_setct_PANData = OBJ_set_ctype + ".0"; + + public final static int NID_setct_PANToken = 520; + public final static String SN_setct_PANToken = "setct-PANToken"; + public final static String OBJ_setct_PANToken = OBJ_set_ctype + ".1"; + + public final static int NID_setct_PANOnly = 521; + public final static String SN_setct_PANOnly = "setct-PANOnly"; + public final static String OBJ_setct_PANOnly = OBJ_set_ctype + ".2"; + + public final static int NID_setct_OIData = 522; + public final static String SN_setct_OIData = "setct-OIData"; + public final static String OBJ_setct_OIData = OBJ_set_ctype + ".3"; + + public final static int NID_setct_PI = 523; + public final static String SN_setct_PI = "setct-PI"; + public final static String OBJ_setct_PI = OBJ_set_ctype + ".4"; + + public final static int NID_setct_PIData = 524; + public final static String SN_setct_PIData = "setct-PIData"; + public final static String OBJ_setct_PIData = OBJ_set_ctype + ".5"; + + public final static int NID_setct_PIDataUnsigned = 525; + public final static String SN_setct_PIDataUnsigned = "setct-PIDataUnsigned"; + public final static String OBJ_setct_PIDataUnsigned = OBJ_set_ctype + ".6"; + + public final static int NID_setct_HODInput = 526; + public final static String SN_setct_HODInput = "setct-HODInput"; + public final static String OBJ_setct_HODInput = OBJ_set_ctype + ".7"; + + public final static int NID_setct_AuthResBaggage = 527; + public final static String SN_setct_AuthResBaggage = "setct-AuthResBaggage"; + public final static String OBJ_setct_AuthResBaggage = OBJ_set_ctype + ".8"; + + public final static int NID_setct_AuthRevReqBaggage = 528; + public final static String SN_setct_AuthRevReqBaggage = "setct-AuthRevReqBaggage"; + public final static String OBJ_setct_AuthRevReqBaggage = OBJ_set_ctype + ".9"; + + public final static int NID_setct_AuthRevResBaggage = 529; + public final static String SN_setct_AuthRevResBaggage = "setct-AuthRevResBaggage"; + public final static String OBJ_setct_AuthRevResBaggage = OBJ_set_ctype + ".10"; + + public final static int NID_setct_CapTokenSeq = 530; + public final static String SN_setct_CapTokenSeq = "setct-CapTokenSeq"; + public final static String OBJ_setct_CapTokenSeq = OBJ_set_ctype + ".11"; + + public final static int NID_setct_PInitResData = 531; + public final static String SN_setct_PInitResData = "setct-PInitResData"; + public final static String OBJ_setct_PInitResData = OBJ_set_ctype + ".12"; + + public final static int NID_setct_PI_TBS = 532; + public final static String SN_setct_PI_TBS = "setct-PI-TBS"; + public final static String OBJ_setct_PI_TBS = OBJ_set_ctype + ".13"; + + public final static int NID_setct_PResData = 533; + public final static String SN_setct_PResData = "setct-PResData"; + public final static String OBJ_setct_PResData = OBJ_set_ctype + ".14"; + + public final static int NID_setct_AuthReqTBS = 534; + public final static String SN_setct_AuthReqTBS = "setct-AuthReqTBS"; + public final static String OBJ_setct_AuthReqTBS = OBJ_set_ctype + ".16"; + + public final static int NID_setct_AuthResTBS = 535; + public final static String SN_setct_AuthResTBS = "setct-AuthResTBS"; + public final static String OBJ_setct_AuthResTBS = OBJ_set_ctype + ".17"; + + public final static int NID_setct_AuthResTBSX = 536; + public final static String SN_setct_AuthResTBSX = "setct-AuthResTBSX"; + public final static String OBJ_setct_AuthResTBSX = OBJ_set_ctype + ".18"; + + public final static int NID_setct_AuthTokenTBS = 537; + public final static String SN_setct_AuthTokenTBS = "setct-AuthTokenTBS"; + public final static String OBJ_setct_AuthTokenTBS = OBJ_set_ctype + ".19"; + + public final static int NID_setct_CapTokenData = 538; + public final static String SN_setct_CapTokenData = "setct-CapTokenData"; + public final static String OBJ_setct_CapTokenData = OBJ_set_ctype + ".20"; + + public final static int NID_setct_CapTokenTBS = 539; + public final static String SN_setct_CapTokenTBS = "setct-CapTokenTBS"; + public final static String OBJ_setct_CapTokenTBS = OBJ_set_ctype + ".21"; + + public final static int NID_setct_AcqCardCodeMsg = 540; + public final static String SN_setct_AcqCardCodeMsg = "setct-AcqCardCodeMsg"; + public final static String OBJ_setct_AcqCardCodeMsg = OBJ_set_ctype + ".22"; + + public final static int NID_setct_AuthRevReqTBS = 541; + public final static String SN_setct_AuthRevReqTBS = "setct-AuthRevReqTBS"; + public final static String OBJ_setct_AuthRevReqTBS = OBJ_set_ctype + ".23"; + + public final static int NID_setct_AuthRevResData = 542; + public final static String SN_setct_AuthRevResData = "setct-AuthRevResData"; + public final static String OBJ_setct_AuthRevResData = OBJ_set_ctype + ".24"; + + public final static int NID_setct_AuthRevResTBS = 543; + public final static String SN_setct_AuthRevResTBS = "setct-AuthRevResTBS"; + public final static String OBJ_setct_AuthRevResTBS = OBJ_set_ctype + ".25"; + + public final static int NID_setct_CapReqTBS = 544; + public final static String SN_setct_CapReqTBS = "setct-CapReqTBS"; + public final static String OBJ_setct_CapReqTBS = OBJ_set_ctype + ".26"; + + public final static int NID_setct_CapReqTBSX = 545; + public final static String SN_setct_CapReqTBSX = "setct-CapReqTBSX"; + public final static String OBJ_setct_CapReqTBSX = OBJ_set_ctype + ".27"; + + public final static int NID_setct_CapResData = 546; + public final static String SN_setct_CapResData = "setct-CapResData"; + public final static String OBJ_setct_CapResData = OBJ_set_ctype + ".28"; + + public final static int NID_setct_CapRevReqTBS = 547; + public final static String SN_setct_CapRevReqTBS = "setct-CapRevReqTBS"; + public final static String OBJ_setct_CapRevReqTBS = OBJ_set_ctype + ".29"; + + public final static int NID_setct_CapRevReqTBSX = 548; + public final static String SN_setct_CapRevReqTBSX = "setct-CapRevReqTBSX"; + public final static String OBJ_setct_CapRevReqTBSX = OBJ_set_ctype + ".30"; + + public final static int NID_setct_CapRevResData = 549; + public final static String SN_setct_CapRevResData = "setct-CapRevResData"; + public final static String OBJ_setct_CapRevResData = OBJ_set_ctype + ".31"; + + public final static int NID_setct_CredReqTBS = 550; + public final static String SN_setct_CredReqTBS = "setct-CredReqTBS"; + public final static String OBJ_setct_CredReqTBS = OBJ_set_ctype + ".32"; + + public final static int NID_setct_CredReqTBSX = 551; + public final static String SN_setct_CredReqTBSX = "setct-CredReqTBSX"; + public final static String OBJ_setct_CredReqTBSX = OBJ_set_ctype + ".33"; + + public final static int NID_setct_CredResData = 552; + public final static String SN_setct_CredResData = "setct-CredResData"; + public final static String OBJ_setct_CredResData = OBJ_set_ctype + ".34"; + + public final static int NID_setct_CredRevReqTBS = 553; + public final static String SN_setct_CredRevReqTBS = "setct-CredRevReqTBS"; + public final static String OBJ_setct_CredRevReqTBS = OBJ_set_ctype + ".35"; + + public final static int NID_setct_CredRevReqTBSX = 554; + public final static String SN_setct_CredRevReqTBSX = "setct-CredRevReqTBSX"; + public final static String OBJ_setct_CredRevReqTBSX = OBJ_set_ctype + ".36"; + + public final static int NID_setct_CredRevResData = 555; + public final static String SN_setct_CredRevResData = "setct-CredRevResData"; + public final static String OBJ_setct_CredRevResData = OBJ_set_ctype + ".37"; + + public final static int NID_setct_PCertReqData = 556; + public final static String SN_setct_PCertReqData = "setct-PCertReqData"; + public final static String OBJ_setct_PCertReqData = OBJ_set_ctype + ".38"; + + public final static int NID_setct_PCertResTBS = 557; + public final static String SN_setct_PCertResTBS = "setct-PCertResTBS"; + public final static String OBJ_setct_PCertResTBS = OBJ_set_ctype + ".39"; + + public final static int NID_setct_BatchAdminReqData = 558; + public final static String SN_setct_BatchAdminReqData = "setct-BatchAdminReqData"; + public final static String OBJ_setct_BatchAdminReqData = OBJ_set_ctype + ".40"; + + public final static int NID_setct_BatchAdminResData = 559; + public final static String SN_setct_BatchAdminResData = "setct-BatchAdminResData"; + public final static String OBJ_setct_BatchAdminResData = OBJ_set_ctype + ".41"; + + public final static int NID_setct_CardCInitResTBS = 560; + public final static String SN_setct_CardCInitResTBS = "setct-CardCInitResTBS"; + public final static String OBJ_setct_CardCInitResTBS = OBJ_set_ctype + ".42"; + + public final static int NID_setct_MeAqCInitResTBS = 561; + public final static String SN_setct_MeAqCInitResTBS = "setct-MeAqCInitResTBS"; + public final static String OBJ_setct_MeAqCInitResTBS = OBJ_set_ctype + ".43"; + + public final static int NID_setct_RegFormResTBS = 562; + public final static String SN_setct_RegFormResTBS = "setct-RegFormResTBS"; + public final static String OBJ_setct_RegFormResTBS = OBJ_set_ctype + ".44"; + + public final static int NID_setct_CertReqData = 563; + public final static String SN_setct_CertReqData = "setct-CertReqData"; + public final static String OBJ_setct_CertReqData = OBJ_set_ctype + ".45"; + + public final static int NID_setct_CertReqTBS = 564; + public final static String SN_setct_CertReqTBS = "setct-CertReqTBS"; + public final static String OBJ_setct_CertReqTBS = OBJ_set_ctype + ".46"; + + public final static int NID_setct_CertResData = 565; + public final static String SN_setct_CertResData = "setct-CertResData"; + public final static String OBJ_setct_CertResData = OBJ_set_ctype + ".47"; + + public final static int NID_setct_CertInqReqTBS = 566; + public final static String SN_setct_CertInqReqTBS = "setct-CertInqReqTBS"; + public final static String OBJ_setct_CertInqReqTBS = OBJ_set_ctype + ".48"; + + public final static int NID_setct_ErrorTBS = 567; + public final static String SN_setct_ErrorTBS = "setct-ErrorTBS"; + public final static String OBJ_setct_ErrorTBS = OBJ_set_ctype + ".49"; + + public final static int NID_setct_PIDualSignedTBE = 568; + public final static String SN_setct_PIDualSignedTBE = "setct-PIDualSignedTBE"; + public final static String OBJ_setct_PIDualSignedTBE = OBJ_set_ctype + ".50"; + + public final static int NID_setct_PIUnsignedTBE = 569; + public final static String SN_setct_PIUnsignedTBE = "setct-PIUnsignedTBE"; + public final static String OBJ_setct_PIUnsignedTBE = OBJ_set_ctype + ".51"; + + public final static int NID_setct_AuthReqTBE = 570; + public final static String SN_setct_AuthReqTBE = "setct-AuthReqTBE"; + public final static String OBJ_setct_AuthReqTBE = OBJ_set_ctype + ".52"; + + public final static int NID_setct_AuthResTBE = 571; + public final static String SN_setct_AuthResTBE = "setct-AuthResTBE"; + public final static String OBJ_setct_AuthResTBE = OBJ_set_ctype + ".53"; + + public final static int NID_setct_AuthResTBEX = 572; + public final static String SN_setct_AuthResTBEX = "setct-AuthResTBEX"; + public final static String OBJ_setct_AuthResTBEX = OBJ_set_ctype + ".54"; + + public final static int NID_setct_AuthTokenTBE = 573; + public final static String SN_setct_AuthTokenTBE = "setct-AuthTokenTBE"; + public final static String OBJ_setct_AuthTokenTBE = OBJ_set_ctype + ".55"; + + public final static int NID_setct_CapTokenTBE = 574; + public final static String SN_setct_CapTokenTBE = "setct-CapTokenTBE"; + public final static String OBJ_setct_CapTokenTBE = OBJ_set_ctype + ".56"; + + public final static int NID_setct_CapTokenTBEX = 575; + public final static String SN_setct_CapTokenTBEX = "setct-CapTokenTBEX"; + public final static String OBJ_setct_CapTokenTBEX = OBJ_set_ctype + ".57"; + + public final static int NID_setct_AcqCardCodeMsgTBE = 576; + public final static String SN_setct_AcqCardCodeMsgTBE = "setct-AcqCardCodeMsgTBE"; + public final static String OBJ_setct_AcqCardCodeMsgTBE = OBJ_set_ctype + ".58"; + + public final static int NID_setct_AuthRevReqTBE = 577; + public final static String SN_setct_AuthRevReqTBE = "setct-AuthRevReqTBE"; + public final static String OBJ_setct_AuthRevReqTBE = OBJ_set_ctype + ".59"; + + public final static int NID_setct_AuthRevResTBE = 578; + public final static String SN_setct_AuthRevResTBE = "setct-AuthRevResTBE"; + public final static String OBJ_setct_AuthRevResTBE = OBJ_set_ctype + ".60"; + + public final static int NID_setct_AuthRevResTBEB = 579; + public final static String SN_setct_AuthRevResTBEB = "setct-AuthRevResTBEB"; + public final static String OBJ_setct_AuthRevResTBEB = OBJ_set_ctype + ".61"; + + public final static int NID_setct_CapReqTBE = 580; + public final static String SN_setct_CapReqTBE = "setct-CapReqTBE"; + public final static String OBJ_setct_CapReqTBE = OBJ_set_ctype + ".62"; + + public final static int NID_setct_CapReqTBEX = 581; + public final static String SN_setct_CapReqTBEX = "setct-CapReqTBEX"; + public final static String OBJ_setct_CapReqTBEX = OBJ_set_ctype + ".63"; + + public final static int NID_setct_CapResTBE = 582; + public final static String SN_setct_CapResTBE = "setct-CapResTBE"; + public final static String OBJ_setct_CapResTBE = OBJ_set_ctype + ".64"; + + public final static int NID_setct_CapRevReqTBE = 583; + public final static String SN_setct_CapRevReqTBE = "setct-CapRevReqTBE"; + public final static String OBJ_setct_CapRevReqTBE = OBJ_set_ctype + ".65"; + + public final static int NID_setct_CapRevReqTBEX = 584; + public final static String SN_setct_CapRevReqTBEX = "setct-CapRevReqTBEX"; + public final static String OBJ_setct_CapRevReqTBEX = OBJ_set_ctype + ".66"; + + public final static int NID_setct_CapRevResTBE = 585; + public final static String SN_setct_CapRevResTBE = "setct-CapRevResTBE"; + public final static String OBJ_setct_CapRevResTBE = OBJ_set_ctype + ".67"; + + public final static int NID_setct_CredReqTBE = 586; + public final static String SN_setct_CredReqTBE = "setct-CredReqTBE"; + public final static String OBJ_setct_CredReqTBE = OBJ_set_ctype + ".68"; + + public final static int NID_setct_CredReqTBEX = 587; + public final static String SN_setct_CredReqTBEX = "setct-CredReqTBEX"; + public final static String OBJ_setct_CredReqTBEX = OBJ_set_ctype + ".69"; + + public final static int NID_setct_CredResTBE = 588; + public final static String SN_setct_CredResTBE = "setct-CredResTBE"; + public final static String OBJ_setct_CredResTBE = OBJ_set_ctype + ".70"; + + public final static int NID_setct_CredRevReqTBE = 589; + public final static String SN_setct_CredRevReqTBE = "setct-CredRevReqTBE"; + public final static String OBJ_setct_CredRevReqTBE = OBJ_set_ctype + ".71"; + + public final static int NID_setct_CredRevReqTBEX = 590; + public final static String SN_setct_CredRevReqTBEX = "setct-CredRevReqTBEX"; + public final static String OBJ_setct_CredRevReqTBEX = OBJ_set_ctype + ".72"; + + public final static int NID_setct_CredRevResTBE = 591; + public final static String SN_setct_CredRevResTBE = "setct-CredRevResTBE"; + public final static String OBJ_setct_CredRevResTBE = OBJ_set_ctype + ".73"; + + public final static int NID_setct_BatchAdminReqTBE = 592; + public final static String SN_setct_BatchAdminReqTBE = "setct-BatchAdminReqTBE"; + public final static String OBJ_setct_BatchAdminReqTBE = OBJ_set_ctype + ".74"; + + public final static int NID_setct_BatchAdminResTBE = 593; + public final static String SN_setct_BatchAdminResTBE = "setct-BatchAdminResTBE"; + public final static String OBJ_setct_BatchAdminResTBE = OBJ_set_ctype + ".75"; + + public final static int NID_setct_RegFormReqTBE = 594; + public final static String SN_setct_RegFormReqTBE = "setct-RegFormReqTBE"; + public final static String OBJ_setct_RegFormReqTBE = OBJ_set_ctype + ".76"; + + public final static int NID_setct_CertReqTBE = 595; + public final static String SN_setct_CertReqTBE = "setct-CertReqTBE"; + public final static String OBJ_setct_CertReqTBE = OBJ_set_ctype + ".77"; + + public final static int NID_setct_CertReqTBEX = 596; + public final static String SN_setct_CertReqTBEX = "setct-CertReqTBEX"; + public final static String OBJ_setct_CertReqTBEX = OBJ_set_ctype + ".78"; + + public final static int NID_setct_CertResTBE = 597; + public final static String SN_setct_CertResTBE = "setct-CertResTBE"; + public final static String OBJ_setct_CertResTBE = OBJ_set_ctype + ".79"; + + public final static int NID_setct_CRLNotificationTBS = 598; + public final static String SN_setct_CRLNotificationTBS = "setct-CRLNotificationTBS"; + public final static String OBJ_setct_CRLNotificationTBS = OBJ_set_ctype + ".80"; + + public final static int NID_setct_CRLNotificationResTBS = 599; + public final static String SN_setct_CRLNotificationResTBS = "setct-CRLNotificationResTBS"; + public final static String OBJ_setct_CRLNotificationResTBS = OBJ_set_ctype + ".81"; + + public final static int NID_setct_BCIDistributionTBS = 600; + public final static String SN_setct_BCIDistributionTBS = "setct-BCIDistributionTBS"; + public final static String OBJ_setct_BCIDistributionTBS = OBJ_set_ctype + ".82"; + + public final static int NID_setext_genCrypt = 601; + public final static String SN_setext_genCrypt = "setext-genCrypt"; + public final static String LN_setext_genCrypt = "generic cryptogram"; + public final static String OBJ_setext_genCrypt = OBJ_set_msgExt + ".1"; + + public final static int NID_setext_miAuth = 602; + public final static String SN_setext_miAuth = "setext-miAuth"; + public final static String LN_setext_miAuth = "merchant initiated auth"; + public final static String OBJ_setext_miAuth = OBJ_set_msgExt + ".3"; + + public final static int NID_setext_pinSecure = 603; + public final static String SN_setext_pinSecure = "setext-pinSecure"; + public final static String OBJ_setext_pinSecure = OBJ_set_msgExt + ".4"; + + public final static int NID_setext_pinAny = 604; + public final static String SN_setext_pinAny = "setext-pinAny"; + public final static String OBJ_setext_pinAny = OBJ_set_msgExt + ".5"; + + public final static int NID_setext_track2 = 605; + public final static String SN_setext_track2 = "setext-track2"; + public final static String OBJ_setext_track2 = OBJ_set_msgExt + ".7"; + + public final static int NID_setext_cv = 606; + public final static String SN_setext_cv = "setext-cv"; + public final static String LN_setext_cv = "additional verification"; + public final static String OBJ_setext_cv = OBJ_set_msgExt + ".8"; + + public final static int NID_set_policy_root = 607; + public final static String SN_set_policy_root = "set-policy-root"; + public final static String OBJ_set_policy_root = OBJ_set_policy + ".0"; + + public final static int NID_setCext_hashedRoot = 608; + public final static String SN_setCext_hashedRoot = "setCext-hashedRoot"; + public final static String OBJ_setCext_hashedRoot = OBJ_set_certExt + ".0"; + + public final static int NID_setCext_certType = 609; + public final static String SN_setCext_certType = "setCext-certType"; + public final static String OBJ_setCext_certType = OBJ_set_certExt + ".1"; + + public final static int NID_setCext_merchData = 610; + public final static String SN_setCext_merchData = "setCext-merchData"; + public final static String OBJ_setCext_merchData = OBJ_set_certExt + ".2"; + + public final static int NID_setCext_cCertRequired = 611; + public final static String SN_setCext_cCertRequired = "setCext-cCertRequired"; + public final static String OBJ_setCext_cCertRequired = OBJ_set_certExt + ".3"; + + public final static int NID_setCext_tunneling = 612; + public final static String SN_setCext_tunneling = "setCext-tunneling"; + public final static String OBJ_setCext_tunneling = OBJ_set_certExt + ".4"; + + public final static int NID_setCext_setExt = 613; + public final static String SN_setCext_setExt = "setCext-setExt"; + public final static String OBJ_setCext_setExt = OBJ_set_certExt + ".5"; + + public final static int NID_setCext_setQualf = 614; + public final static String SN_setCext_setQualf = "setCext-setQualf"; + public final static String OBJ_setCext_setQualf = OBJ_set_certExt + ".6"; + + public final static int NID_setCext_PGWYcapabilities = 615; + public final static String SN_setCext_PGWYcapabilities = "setCext-PGWYcapabilities"; + public final static String OBJ_setCext_PGWYcapabilities = OBJ_set_certExt + ".7"; + + public final static int NID_setCext_TokenIdentifier = 616; + public final static String SN_setCext_TokenIdentifier = "setCext-TokenIdentifier"; + public final static String OBJ_setCext_TokenIdentifier = OBJ_set_certExt + ".8"; + + public final static int NID_setCext_Track2Data = 617; + public final static String SN_setCext_Track2Data = "setCext-Track2Data"; + public final static String OBJ_setCext_Track2Data = OBJ_set_certExt + ".9"; + + public final static int NID_setCext_TokenType = 618; + public final static String SN_setCext_TokenType = "setCext-TokenType"; + public final static String OBJ_setCext_TokenType = OBJ_set_certExt + ".10"; + + public final static int NID_setCext_IssuerCapabilities = 619; + public final static String SN_setCext_IssuerCapabilities = "setCext-IssuerCapabilities"; + public final static String OBJ_setCext_IssuerCapabilities = OBJ_set_certExt + ".11"; + + public final static int NID_setAttr_Cert = 620; + public final static String SN_setAttr_Cert = "setAttr-Cert"; + public final static String OBJ_setAttr_Cert = OBJ_set_attr + ".0"; + + public final static int NID_setAttr_PGWYcap = 621; + public final static String SN_setAttr_PGWYcap = "setAttr-PGWYcap"; + public final static String LN_setAttr_PGWYcap = "payment gateway capabilities"; + public final static String OBJ_setAttr_PGWYcap = OBJ_set_attr + ".1"; + + public final static int NID_setAttr_TokenType = 622; + public final static String SN_setAttr_TokenType = "setAttr-TokenType"; + public final static String OBJ_setAttr_TokenType = OBJ_set_attr + ".2"; + + public final static int NID_setAttr_IssCap = 623; + public final static String SN_setAttr_IssCap = "setAttr-IssCap"; + public final static String LN_setAttr_IssCap = "issuer capabilities"; + public final static String OBJ_setAttr_IssCap = OBJ_set_attr + ".3"; + + public final static int NID_set_rootKeyThumb = 624; + public final static String SN_set_rootKeyThumb = "set-rootKeyThumb"; + public final static String OBJ_set_rootKeyThumb = OBJ_setAttr_Cert + ".0"; + + public final static int NID_set_addPolicy = 625; + public final static String SN_set_addPolicy = "set-addPolicy"; + public final static String OBJ_set_addPolicy = OBJ_setAttr_Cert + ".1"; + + public final static int NID_setAttr_Token_EMV = 626; + public final static String SN_setAttr_Token_EMV = "setAttr-Token-EMV"; + public final static String OBJ_setAttr_Token_EMV = OBJ_setAttr_TokenType + ".1"; + + public final static int NID_setAttr_Token_B0Prime = 627; + public final static String SN_setAttr_Token_B0Prime = "setAttr-Token-B0Prime"; + public final static String OBJ_setAttr_Token_B0Prime = OBJ_setAttr_TokenType + ".2"; + + public final static int NID_setAttr_IssCap_CVM = 628; + public final static String SN_setAttr_IssCap_CVM = "setAttr-IssCap-CVM"; + public final static String OBJ_setAttr_IssCap_CVM = OBJ_setAttr_IssCap + ".3"; + + public final static int NID_setAttr_IssCap_T2 = 629; + public final static String SN_setAttr_IssCap_T2 = "setAttr-IssCap-T2"; + public final static String OBJ_setAttr_IssCap_T2 = OBJ_setAttr_IssCap + ".4"; + + public final static int NID_setAttr_IssCap_Sig = 630; + public final static String SN_setAttr_IssCap_Sig = "setAttr-IssCap-Sig"; + public final static String OBJ_setAttr_IssCap_Sig = OBJ_setAttr_IssCap + ".5"; + + public final static int NID_setAttr_GenCryptgrm = 631; + public final static String SN_setAttr_GenCryptgrm = "setAttr-GenCryptgrm"; + public final static String LN_setAttr_GenCryptgrm = "generate cryptogram"; + public final static String OBJ_setAttr_GenCryptgrm = OBJ_setAttr_IssCap_CVM + ".1"; + + public final static int NID_setAttr_T2Enc = 632; + public final static String SN_setAttr_T2Enc = "setAttr-T2Enc"; + public final static String LN_setAttr_T2Enc = "encrypted track 2"; + public final static String OBJ_setAttr_T2Enc = OBJ_setAttr_IssCap_T2 + ".1"; + + public final static int NID_setAttr_T2cleartxt = 633; + public final static String SN_setAttr_T2cleartxt = "setAttr-T2cleartxt"; + public final static String LN_setAttr_T2cleartxt = "cleartext track 2"; + public final static String OBJ_setAttr_T2cleartxt = OBJ_setAttr_IssCap_T2 + ".2"; + + public final static int NID_setAttr_TokICCsig = 634; + public final static String SN_setAttr_TokICCsig = "setAttr-TokICCsig"; + public final static String LN_setAttr_TokICCsig = "ICC or token signature"; + public final static String OBJ_setAttr_TokICCsig = OBJ_setAttr_IssCap_Sig + ".1"; + + public final static int NID_setAttr_SecDevSig = 635; + public final static String SN_setAttr_SecDevSig = "setAttr-SecDevSig"; + public final static String LN_setAttr_SecDevSig = "secure device signature"; + public final static String OBJ_setAttr_SecDevSig = OBJ_setAttr_IssCap_Sig + ".2"; + + public final static int NID_set_brand_IATA_ATA = 636; + public final static String SN_set_brand_IATA_ATA = "set-brand-IATA-ATA"; + public final static String OBJ_set_brand_IATA_ATA = OBJ_set_brand + ".1"; + + public final static int NID_set_brand_Diners = 637; + public final static String SN_set_brand_Diners = "set-brand-Diners"; + public final static String OBJ_set_brand_Diners = OBJ_set_brand + ".30"; + + public final static int NID_set_brand_AmericanExpress = 638; + public final static String SN_set_brand_AmericanExpress = "set-brand-AmericanExpress"; + public final static String OBJ_set_brand_AmericanExpress = OBJ_set_brand + ".34"; + + public final static int NID_set_brand_JCB = 639; + public final static String SN_set_brand_JCB = "set-brand-JCB"; + public final static String OBJ_set_brand_JCB = OBJ_set_brand + ".35"; + + public final static int NID_set_brand_Visa = 640; + public final static String SN_set_brand_Visa = "set-brand-Visa"; + public final static String OBJ_set_brand_Visa = OBJ_set_brand + ".4"; + + public final static int NID_set_brand_MasterCard = 641; + public final static String SN_set_brand_MasterCard = "set-brand-MasterCard"; + public final static String OBJ_set_brand_MasterCard = OBJ_set_brand + ".5"; + + public final static int NID_set_brand_Novus = 642; + public final static String SN_set_brand_Novus = "set-brand-Novus"; + public final static String OBJ_set_brand_Novus = OBJ_set_brand + ".6011"; + + public final static int NID_des_cdmf = 643; + public final static String SN_des_cdmf = "DES-CDMF"; + public final static String LN_des_cdmf = "des-cdmf"; + public final static String OBJ_des_cdmf = OBJ_rsadsi + ".3.10"; + + public final static int NID_rsaOAEPEncryptionSET = 644; + public final static String SN_rsaOAEPEncryptionSET = "rsaOAEPEncryptionSET"; + public final static String OBJ_rsaOAEPEncryptionSET = OBJ_rsadsi + ".1.1.6"; + + public final static int NID_ms_smartcard_login = 648; + public final static String SN_ms_smartcard_login = "msSmartcardLogin"; + public final static String LN_ms_smartcard_login = "Microsoft Smartcardlogin"; + public final static String OBJ_ms_smartcard_login = "1.3.6.1.4.1.311.20.2.2"; + + public final static int NID_ms_upn = 649; + public final static String SN_ms_upn = "msUPN"; + public final static String LN_ms_upn = "Microsoft Universal Principal Name"; + public final static String OBJ_ms_upn = "1.3.6.1.4.1.311.20.2.3"; + + public final static int NID_aes_128_cfb1 = 650; + public final static String SN_aes_128_cfb1 = "AES-128-CFB1"; + public final static String LN_aes_128_cfb1 = "aes-128-cfb1"; + + public final static int NID_aes_192_cfb1 = 651; + public final static String SN_aes_192_cfb1 = "AES-192-CFB1"; + public final static String LN_aes_192_cfb1 = "aes-192-cfb1"; + + public final static int NID_aes_256_cfb1 = 652; + public final static String SN_aes_256_cfb1 = "AES-256-CFB1"; + public final static String LN_aes_256_cfb1 = "aes-256-cfb1"; + + public final static int NID_aes_128_cfb8 = 653; + public final static String SN_aes_128_cfb8 = "AES-128-CFB8"; + public final static String LN_aes_128_cfb8 = "aes-128-cfb8"; + + public final static int NID_aes_192_cfb8 = 654; + public final static String SN_aes_192_cfb8 = "AES-192-CFB8"; + public final static String LN_aes_192_cfb8 = "aes-192-cfb8"; + + public final static int NID_aes_256_cfb8 = 655; + public final static String SN_aes_256_cfb8 = "AES-256-CFB8"; + public final static String LN_aes_256_cfb8 = "aes-256-cfb8"; + + public final static int NID_des_cfb1 = 656; + public final static String SN_des_cfb1 = "DES-CFB1"; + public final static String LN_des_cfb1 = "des-cfb1"; + + public final static int NID_des_cfb8 = 657; + public final static String SN_des_cfb8 = "DES-CFB8"; + public final static String LN_des_cfb8 = "des-cfb8"; + + public final static int NID_des_ede3_cfb1 = 658; + public final static String SN_des_ede3_cfb1 = "DES-EDE3-CFB1"; + public final static String LN_des_ede3_cfb1 = "des-ede3-cfb1"; + + public final static int NID_des_ede3_cfb8 = 659; + public final static String SN_des_ede3_cfb8 = "DES-EDE3-CFB8"; + public final static String LN_des_ede3_cfb8 = "des-ede3-cfb8"; + + public final static int NID_streetAddress = 660; + public final static String LN_streetAddress = "streetAddress"; + public final static String OBJ_streetAddress = OBJ_X509 + ".9"; + + public final static int NID_postalCode = 661; + public final static String LN_postalCode = "postalCode"; + public final static String OBJ_postalCode = OBJ_X509 + ".17"; + + public final static int NID_id_ppl = 662; + public final static String SN_id_ppl = "id-ppl"; + public final static String OBJ_id_ppl = OBJ_id_pkix + ".21"; + + public final static int NID_proxyCertInfo = 663; + public final static String SN_proxyCertInfo = "proxyCertInfo"; + public final static String LN_proxyCertInfo = "Proxy Certificate Information"; + public final static String OBJ_proxyCertInfo = OBJ_id_pe + ".14"; + + public final static int NID_id_ppl_anyLanguage = 664; + public final static String SN_id_ppl_anyLanguage = "id-ppl-anyLanguage"; + public final static String LN_id_ppl_anyLanguage = "Any language"; + public final static String OBJ_id_ppl_anyLanguage = OBJ_id_ppl + ".0"; + + public final static int NID_id_ppl_inheritAll = 665; + public final static String SN_id_ppl_inheritAll = "id-ppl-inheritAll"; + public final static String LN_id_ppl_inheritAll = "Inherit all"; + public final static String OBJ_id_ppl_inheritAll = OBJ_id_ppl + ".1"; + + public final static int NID_name_constraints = 666; + public final static String SN_name_constraints = "nameConstraints"; + public final static String LN_name_constraints = "X509v3 Name Constraints"; + public final static String OBJ_name_constraints = OBJ_id_ce + ".30"; + + public final static int NID_Independent = 667; + public final static String SN_Independent = "id-ppl-independent"; + public final static String LN_Independent = "Independent"; + public final static String OBJ_Independent = OBJ_id_ppl + ".2"; + + public final static int NID_sha256WithRSAEncryption = 668; + public final static String SN_sha256WithRSAEncryption = "RSA-SHA256"; + public final static String LN_sha256WithRSAEncryption = "sha256WithRSAEncryption"; + public final static String OBJ_sha256WithRSAEncryption = OBJ_pkcs1 + ".11"; + + public final static int NID_sha384WithRSAEncryption = 669; + public final static String SN_sha384WithRSAEncryption = "RSA-SHA384"; + public final static String LN_sha384WithRSAEncryption = "sha384WithRSAEncryption"; + public final static String OBJ_sha384WithRSAEncryption = OBJ_pkcs1 + ".12"; + + public final static int NID_sha512WithRSAEncryption = 670; + public final static String SN_sha512WithRSAEncryption = "RSA-SHA512"; + public final static String LN_sha512WithRSAEncryption = "sha512WithRSAEncryption"; + public final static String OBJ_sha512WithRSAEncryption = OBJ_pkcs1 + ".13"; + + public final static int NID_sha224WithRSAEncryption = 671; + public final static String SN_sha224WithRSAEncryption = "RSA-SHA224"; + public final static String LN_sha224WithRSAEncryption = "sha224WithRSAEncryption"; + public final static String OBJ_sha224WithRSAEncryption = OBJ_pkcs1 + ".14"; + + public final static int NID_sha256 = 672; + public final static String SN_sha256 = "SHA256"; + public final static String LN_sha256 = "sha256"; + public final static String OBJ_sha256 = OBJ_nist_hashalgs + ".1"; + + public final static int NID_sha384 = 673; + public final static String SN_sha384 = "SHA384"; + public final static String LN_sha384 = "sha384"; + public final static String OBJ_sha384 = OBJ_nist_hashalgs + ".2"; + + public final static int NID_sha512 = 674; + public final static String SN_sha512 = "SHA512"; + public final static String LN_sha512 = "sha512"; + public final static String OBJ_sha512 = OBJ_nist_hashalgs + ".3"; + + public final static int NID_sha224 = 675; + public final static String SN_sha224 = "SHA224"; + public final static String LN_sha224 = "sha224"; + public final static String OBJ_sha224 = OBJ_nist_hashalgs + ".4"; + + public final static int NID_dsa_with_SHA224 = 802; + public final static String SN_dsa_with_SHA224 = "dsa_with_SHA224"; + public final static String OBJ_dsa_with_SHA224 = OBJ_dsa_with_sha2 + ".1"; + + public final static String SN_dsa_with_SHA256 = "dsa_with_SHA256"; + public final static int NID_dsa_with_SHA256 = 803; + public final static String OBJ_dsa_with_SHA256 = OBJ_dsa_with_sha2 + ".2"; + + public final static int NID_X9_62_id_characteristic_two_basis = 680; + public final static String SN_X9_62_id_characteristic_two_basis = "id-characteristic-two-basis"; + public final static String OBJ_X9_62_id_characteristic_two_basis = OBJ_X9_62_characteristic_two_field + ".3"; + + public final static int NID_X9_62_onBasis = 681; + public final static String SN_X9_62_onBasis = "onBasis"; + public final static String OBJ_X9_62_onBasis = OBJ_X9_62_id_characteristic_two_basis + ".1"; + + public final static int NID_X9_62_tpBasis = 682; + public final static String SN_X9_62_tpBasis = "tpBasis"; + public final static String OBJ_X9_62_tpBasis = OBJ_X9_62_id_characteristic_two_basis + ".2"; + + public final static int NID_X9_62_ppBasis = 683; + public final static String SN_X9_62_ppBasis = "ppBasis"; + public final static String OBJ_X9_62_ppBasis = OBJ_X9_62_id_characteristic_two_basis + ".3"; + + public final static int NID_X9_62_c2pnb163v1 = 684; + public final static String SN_X9_62_c2pnb163v1 = "c2pnb163v1"; + public final static String OBJ_X9_62_c2pnb163v1 = OBJ_X9_62_c_TwoCurve + ".1"; + + public final static int NID_X9_62_c2pnb163v2 = 685; + public final static String SN_X9_62_c2pnb163v2 = "c2pnb163v2"; + public final static String OBJ_X9_62_c2pnb163v2 = OBJ_X9_62_c_TwoCurve + ".2"; + + public final static int NID_X9_62_c2pnb163v3 = 686; + public final static String SN_X9_62_c2pnb163v3 = "c2pnb163v3"; + public final static String OBJ_X9_62_c2pnb163v3 = OBJ_X9_62_c_TwoCurve + ".3"; + + public final static int NID_X9_62_c2pnb176v1 = 687; + public final static String SN_X9_62_c2pnb176v1 = "c2pnb176v1"; + public final static String OBJ_X9_62_c2pnb176v1 = OBJ_X9_62_c_TwoCurve + ".4"; + + public final static int NID_X9_62_c2tnb191v1 = 688; + public final static String SN_X9_62_c2tnb191v1 = "c2tnb191v1"; + public final static String OBJ_X9_62_c2tnb191v1 = OBJ_X9_62_c_TwoCurve + ".5"; + + public final static int NID_X9_62_c2tnb191v2 = 689; + public final static String SN_X9_62_c2tnb191v2 = "c2tnb191v2"; + public final static String OBJ_X9_62_c2tnb191v2 = OBJ_X9_62_c_TwoCurve + ".6"; + + public final static int NID_X9_62_c2tnb191v3 = 690; + public final static String SN_X9_62_c2tnb191v3 = "c2tnb191v3"; + public final static String OBJ_X9_62_c2tnb191v3 = OBJ_X9_62_c_TwoCurve + ".7"; + + public final static int NID_X9_62_c2onb191v4 = 691; + public final static String SN_X9_62_c2onb191v4 = "c2onb191v4"; + public final static String OBJ_X9_62_c2onb191v4 = OBJ_X9_62_c_TwoCurve + ".8"; + + public final static int NID_X9_62_c2onb191v5 = 692; + public final static String SN_X9_62_c2onb191v5 = "c2onb191v5"; + public final static String OBJ_X9_62_c2onb191v5 = OBJ_X9_62_c_TwoCurve + ".9"; + + public final static int NID_X9_62_c2pnb208w1 = 693; + public final static String SN_X9_62_c2pnb208w1 = "c2pnb208w1"; + public final static String OBJ_X9_62_c2pnb208w1 = OBJ_X9_62_c_TwoCurve + ".10"; + + public final static int NID_X9_62_c2tnb239v1 = 694; + public final static String SN_X9_62_c2tnb239v1 = "c2tnb239v1"; + public final static String OBJ_X9_62_c2tnb239v1 = OBJ_X9_62_c_TwoCurve + ".11"; + + public final static int NID_X9_62_c2tnb239v2 = 695; + public final static String SN_X9_62_c2tnb239v2 = "c2tnb239v2"; + public final static String OBJ_X9_62_c2tnb239v2 = OBJ_X9_62_c_TwoCurve + ".12"; + + public final static int NID_X9_62_c2tnb239v3 = 696; + public final static String SN_X9_62_c2tnb239v3 = "c2tnb239v3"; + public final static String OBJ_X9_62_c2tnb239v3 = OBJ_X9_62_c_TwoCurve + ".13"; + + public final static int NID_X9_62_c2onb239v4 = 697; + public final static String SN_X9_62_c2onb239v4 = "c2onb239v4"; + public final static String OBJ_X9_62_c2onb239v4 = OBJ_X9_62_c_TwoCurve + ".14"; + + public final static int NID_X9_62_c2onb239v5 = 698; + public final static String SN_X9_62_c2onb239v5 = "c2onb239v5"; + public final static String OBJ_X9_62_c2onb239v5 = OBJ_X9_62_c_TwoCurve + ".15"; + + public final static int NID_X9_62_c2pnb272w1 = 699; + public final static String SN_X9_62_c2pnb272w1 = "c2pnb272w1"; + public final static String OBJ_X9_62_c2pnb272w1 = OBJ_X9_62_c_TwoCurve + ".16"; + + public final static int NID_X9_62_c2pnb304w1 = 700; + public final static String SN_X9_62_c2pnb304w1 = "c2pnb304w1"; + public final static String OBJ_X9_62_c2pnb304w1 = OBJ_X9_62_c_TwoCurve + ".17"; + + public final static int NID_X9_62_c2tnb359v1 = 701; + public final static String SN_X9_62_c2tnb359v1 = "c2tnb359v1"; + public final static String OBJ_X9_62_c2tnb359v1 = OBJ_X9_62_c_TwoCurve + ".18"; + + public final static int NID_X9_62_c2pnb368w1 = 702; + public final static String SN_X9_62_c2pnb368w1 = "c2pnb368w1"; + public final static String OBJ_X9_62_c2pnb368w1 = OBJ_X9_62_c_TwoCurve + ".19"; + + public final static int NID_X9_62_c2tnb431r1 = 703; + public final static String SN_X9_62_c2tnb431r1 = "c2tnb431r1"; + public final static String OBJ_X9_62_c2tnb431r1 = OBJ_X9_62_c_TwoCurve + ".20"; + + public final static int NID_secp112r1 = 704; + public final static String SN_secp112r1 = "secp112r1"; + public final static String OBJ_secp112r1 = OBJ_secg_ellipticCurve + ".6"; + + public final static int NID_secp112r2 = 705; + public final static String SN_secp112r2 = "secp112r2"; + public final static String OBJ_secp112r2 = OBJ_secg_ellipticCurve + ".7"; + + public final static int NID_secp128r1 = 706; + public final static String SN_secp128r1 = "secp128r1"; + public final static String OBJ_secp128r1 = OBJ_secg_ellipticCurve + ".28"; + + public final static int NID_secp128r2 = 707; + public final static String SN_secp128r2 = "secp128r2"; + public final static String OBJ_secp128r2 = OBJ_secg_ellipticCurve + ".29"; + + public final static int NID_secp160k1 = 708; + public final static String SN_secp160k1 = "secp160k1"; + public final static String OBJ_secp160k1 = OBJ_secg_ellipticCurve + ".9"; + + public final static int NID_secp160r1 = 709; + public final static String SN_secp160r1 = "secp160r1"; + public final static String OBJ_secp160r1 = OBJ_secg_ellipticCurve + ".8"; + + public final static int NID_secp160r2 = 710; + public final static String SN_secp160r2 = "secp160r2"; + public final static String OBJ_secp160r2 = OBJ_secg_ellipticCurve + ".30"; + + public final static int NID_secp192k1 = 711; + public final static String SN_secp192k1 = "secp192k1"; + public final static String OBJ_secp192k1 = OBJ_secg_ellipticCurve + ".31"; + + public final static int NID_secp224k1 = 712; + public final static String SN_secp224k1 = "secp224k1"; + public final static String OBJ_secp224k1 = OBJ_secg_ellipticCurve + ".32"; + + public final static int NID_secp224r1 = 713; + public final static String SN_secp224r1 = "secp224r1"; + public final static String OBJ_secp224r1 = OBJ_secg_ellipticCurve + ".33"; + + public final static int NID_secp256k1 = 714; + public final static String SN_secp256k1 = "secp256k1"; + public final static String OBJ_secp256k1 = OBJ_secg_ellipticCurve + ".10"; + + public final static int NID_secp384r1 = 715; + public final static String SN_secp384r1 = "secp384r1"; + public final static String OBJ_secp384r1 = OBJ_secg_ellipticCurve + ".34"; + + public final static int NID_secp521r1 = 716; + public final static String SN_secp521r1 = "secp521r1"; + public final static String OBJ_secp521r1 = OBJ_secg_ellipticCurve + ".35"; + + public final static int NID_sect113r1 = 717; + public final static String SN_sect113r1 = "sect113r1"; + public final static String OBJ_sect113r1 = OBJ_secg_ellipticCurve + ".4"; + + public final static int NID_sect113r2 = 718; + public final static String SN_sect113r2 = "sect113r2"; + public final static String OBJ_sect113r2 = OBJ_secg_ellipticCurve + ".5"; + + public final static int NID_sect131r1 = 719; + public final static String SN_sect131r1 = "sect131r1"; + public final static String OBJ_sect131r1 = OBJ_secg_ellipticCurve + ".22"; + + public final static int NID_sect131r2 = 720; + public final static String SN_sect131r2 = "sect131r2"; + public final static String OBJ_sect131r2 = OBJ_secg_ellipticCurve + ".23"; + + public final static int NID_sect163k1 = 721; + public final static String SN_sect163k1 = "sect163k1"; + public final static String OBJ_sect163k1 = OBJ_secg_ellipticCurve + ".1"; + + public final static int NID_sect163r1 = 722; + public final static String SN_sect163r1 = "sect163r1"; + public final static String OBJ_sect163r1 = OBJ_secg_ellipticCurve + ".2"; + + public final static int NID_sect163r2 = 723; + public final static String SN_sect163r2 = "sect163r2"; + public final static String OBJ_sect163r2 = OBJ_secg_ellipticCurve + ".15"; + + public final static int NID_sect193r1 = 724; + public final static String SN_sect193r1 = "sect193r1"; + public final static String OBJ_sect193r1 = OBJ_secg_ellipticCurve + ".24"; + + public final static int NID_sect193r2 = 725; + public final static String SN_sect193r2 = "sect193r2"; + public final static String OBJ_sect193r2 = OBJ_secg_ellipticCurve + ".25"; + + public final static int NID_sect233k1 = 726; + public final static String SN_sect233k1 = "sect233k1"; + public final static String OBJ_sect233k1 = OBJ_secg_ellipticCurve + ".26"; + + public final static int NID_sect233r1 = 727; + public final static String SN_sect233r1 = "sect233r1"; + public final static String OBJ_sect233r1 = OBJ_secg_ellipticCurve + ".27"; + + public final static int NID_sect239k1 = 728; + public final static String SN_sect239k1 = "sect239k1"; + public final static String OBJ_sect239k1 = OBJ_secg_ellipticCurve + ".3"; + + public final static int NID_sect283k1 = 729; + public final static String SN_sect283k1 = "sect283k1"; + public final static String OBJ_sect283k1 = OBJ_secg_ellipticCurve + ".16"; + + public final static int NID_sect283r1 = 730; + public final static String SN_sect283r1 = "sect283r1"; + public final static String OBJ_sect283r1 = OBJ_secg_ellipticCurve + ".17"; + + public final static int NID_sect409k1 = 731; + public final static String SN_sect409k1 = "sect409k1"; + public final static String OBJ_sect409k1 = OBJ_secg_ellipticCurve + ".36"; + + public final static int NID_sect409r1 = 732; + public final static String SN_sect409r1 = "sect409r1"; + public final static String OBJ_sect409r1 = OBJ_secg_ellipticCurve + ".37"; + + public final static int NID_sect571k1 = 733; + public final static String SN_sect571k1 = "sect571k1"; + public final static String OBJ_sect571k1 = OBJ_secg_ellipticCurve + ".38"; + + public final static int NID_sect571r1 = 734; + public final static String SN_sect571r1 = "sect571r1"; + public final static String OBJ_sect571r1 = OBJ_secg_ellipticCurve + ".39"; + + public final static int NID_wap_wsg_idm_ecid_wtls1 = 735; + public final static String SN_wap_wsg_idm_ecid_wtls1 = "wap-wsg-idm-ecid-wtls1"; + public final static String OBJ_wap_wsg_idm_ecid_wtls1 = OBJ_wap_wsg_idm_ecid + ".1"; + + public final static int NID_wap_wsg_idm_ecid_wtls3 = 736; + public final static String SN_wap_wsg_idm_ecid_wtls3 = "wap-wsg-idm-ecid-wtls3"; + public final static String OBJ_wap_wsg_idm_ecid_wtls3 = OBJ_wap_wsg_idm_ecid + ".3"; + + public final static int NID_wap_wsg_idm_ecid_wtls4 = 737; + public final static String SN_wap_wsg_idm_ecid_wtls4 = "wap-wsg-idm-ecid-wtls4"; + public final static String OBJ_wap_wsg_idm_ecid_wtls4 = OBJ_wap_wsg_idm_ecid + ".4"; + + public final static int NID_wap_wsg_idm_ecid_wtls5 = 738; + public final static String SN_wap_wsg_idm_ecid_wtls5 = "wap-wsg-idm-ecid-wtls5"; + public final static String OBJ_wap_wsg_idm_ecid_wtls5 = OBJ_wap_wsg_idm_ecid + ".5"; + + public final static int NID_wap_wsg_idm_ecid_wtls6 = 739; + public final static String SN_wap_wsg_idm_ecid_wtls6 = "wap-wsg-idm-ecid-wtls6"; + public final static String OBJ_wap_wsg_idm_ecid_wtls6 = OBJ_wap_wsg_idm_ecid + ".6"; + + public final static int NID_wap_wsg_idm_ecid_wtls7 = 740; + public final static String SN_wap_wsg_idm_ecid_wtls7 = "wap-wsg-idm-ecid-wtls7"; + public final static String OBJ_wap_wsg_idm_ecid_wtls7 = OBJ_wap_wsg_idm_ecid + ".7"; + + public final static int NID_wap_wsg_idm_ecid_wtls8 = 741; + public final static String SN_wap_wsg_idm_ecid_wtls8 = "wap-wsg-idm-ecid-wtls8"; + public final static String OBJ_wap_wsg_idm_ecid_wtls8 = OBJ_wap_wsg_idm_ecid + ".8"; + + public final static int NID_wap_wsg_idm_ecid_wtls9 = 742; + public final static String SN_wap_wsg_idm_ecid_wtls9 = "wap-wsg-idm-ecid-wtls9"; + public final static String OBJ_wap_wsg_idm_ecid_wtls9 = OBJ_wap_wsg_idm_ecid + ".9"; + + public final static int NID_wap_wsg_idm_ecid_wtls10 = 743; + public final static String SN_wap_wsg_idm_ecid_wtls10 = "wap-wsg-idm-ecid-wtls10"; + public final static String OBJ_wap_wsg_idm_ecid_wtls10 = OBJ_wap_wsg_idm_ecid + ".10"; + + public final static int NID_wap_wsg_idm_ecid_wtls11 = 744; + public final static String SN_wap_wsg_idm_ecid_wtls11 = "wap-wsg-idm-ecid-wtls11"; + public final static String OBJ_wap_wsg_idm_ecid_wtls11 = OBJ_wap_wsg_idm_ecid + ".11"; + + public final static int NID_wap_wsg_idm_ecid_wtls12 = 745; + public final static String SN_wap_wsg_idm_ecid_wtls12 = "wap-wsg-idm-ecid-wtls12"; + public final static String OBJ_wap_wsg_idm_ecid_wtls12 = OBJ_wap_wsg_idm_ecid + ".12"; + + public final static int NID_any_policy = 746; + public final static String SN_any_policy = "anyPolicy"; + public final static String LN_any_policy = "X509v3 Any Policy"; + public final static String OBJ_any_policy = OBJ_certificate_policies + ".0"; + + public final static int NID_policy_mappings = 747; + public final static String SN_policy_mappings = "policyMappings"; + public final static String LN_policy_mappings = "X509v3 Policy Mappings"; + public final static String OBJ_policy_mappings = OBJ_id_ce + ".33"; + + public final static int NID_inhibit_any_policy = 748; + public final static String SN_inhibit_any_policy = "inhibitAnyPolicy"; + public final static String LN_inhibit_any_policy = "X509v3 Inhibit Any Policy"; + public final static String OBJ_inhibit_any_policy = OBJ_id_ce + ".54"; + + public final static int NID_ipsec3 = 749; + public final static String SN_ipsec3 = "Oakley-EC2N-3"; + public final static String LN_ipsec3 = "ipsec3"; + + public final static int NID_ipsec4 = 750; + public final static String SN_ipsec4 = "Oakley-EC2N-4"; + public final static String LN_ipsec4 = "ipsec4"; + + static { + addObject(NID_undef, SN_undef, LN_undef, OBJ_undef); // NID: 0 + addObject(NID_rsadsi, SN_rsadsi, LN_rsadsi, OBJ_rsadsi); // NID: 1 + addObject(NID_pkcs, SN_pkcs, LN_pkcs, OBJ_pkcs); // NID: 2 + addObject(NID_md2, SN_md2, LN_md2, OBJ_md2); // NID: 3 + addObject(NID_md5, SN_md5, LN_md5, OBJ_md5); // NID: 4 + addObject(NID_rc4, SN_rc4, LN_rc4, OBJ_rc4); // NID: 5 + addObject(NID_rsaEncryption, null, LN_rsaEncryption, OBJ_rsaEncryption); // NID: 6 + addObject(NID_md2WithRSAEncryption, SN_md2WithRSAEncryption, LN_md2WithRSAEncryption, OBJ_md2WithRSAEncryption); // NID: 7 + addObject(NID_md5WithRSAEncryption, SN_md5WithRSAEncryption, LN_md5WithRSAEncryption, OBJ_md5WithRSAEncryption); // NID: 8 + addObject(NID_pbeWithMD2AndDES_CBC, SN_pbeWithMD2AndDES_CBC, LN_pbeWithMD2AndDES_CBC, OBJ_pbeWithMD2AndDES_CBC); // NID: 9 + addObject(NID_pbeWithMD5AndDES_CBC, SN_pbeWithMD5AndDES_CBC, LN_pbeWithMD5AndDES_CBC, OBJ_pbeWithMD5AndDES_CBC); // NID: 10 + addObject(NID_X500, SN_X500, LN_X500, OBJ_X500); // NID: 11 + addObject(NID_X509, SN_X509, null, OBJ_X509); // NID: 12 + addObject(NID_commonName, SN_commonName, LN_commonName, OBJ_commonName); // NID: 13 + addObject(NID_countryName, SN_countryName, LN_countryName, OBJ_countryName); // NID: 14 + addObject(NID_localityName, SN_localityName, LN_localityName, OBJ_localityName); // NID: 15 + addObject(NID_stateOrProvinceName, SN_stateOrProvinceName, LN_stateOrProvinceName, OBJ_stateOrProvinceName); // NID: 16 + addObject(NID_organizationName, SN_organizationName, LN_organizationName, OBJ_organizationName); // NID: 17 + addObject(NID_organizationalUnitName, SN_organizationalUnitName, LN_organizationalUnitName, OBJ_organizationalUnitName); // NID: 18 + addObject(NID_rsa, SN_rsa, LN_rsa, OBJ_rsa); // NID: 19 + addObject(NID_pkcs7, SN_pkcs7, null, OBJ_pkcs7); // NID: 20 + addObject(NID_pkcs7_data, null, LN_pkcs7_data, OBJ_pkcs7_data); // NID: 21 + addObject(NID_pkcs7_signed, null, LN_pkcs7_signed, OBJ_pkcs7_signed); // NID: 22 + addObject(NID_pkcs7_enveloped, null, LN_pkcs7_enveloped, OBJ_pkcs7_enveloped); // NID: 23 + addObject(NID_pkcs7_signedAndEnveloped, null, LN_pkcs7_signedAndEnveloped, OBJ_pkcs7_signedAndEnveloped); // NID: 24 + addObject(NID_pkcs7_digest, null, LN_pkcs7_digest, OBJ_pkcs7_digest); // NID: 25 + addObject(NID_pkcs7_encrypted, null, LN_pkcs7_encrypted, OBJ_pkcs7_encrypted); // NID: 26 + addObject(NID_pkcs3, SN_pkcs3, null, OBJ_pkcs3); // NID: 27 + addObject(NID_dhKeyAgreement, null, LN_dhKeyAgreement, OBJ_dhKeyAgreement); // NID: 28 + addObject(NID_des_ecb, SN_des_ecb, LN_des_ecb, OBJ_des_ecb); // NID: 29 + addObject(NID_des_cfb64, SN_des_cfb64, LN_des_cfb64, OBJ_des_cfb64); // NID: 30 + addObject(NID_des_cbc, SN_des_cbc, LN_des_cbc, OBJ_des_cbc); // NID: 31 + addObject(NID_des_ede_ecb, SN_des_ede_ecb, LN_des_ede_ecb, OBJ_des_ede_ecb); // NID: 32 + addObject(NID_des_ede3_ecb, SN_des_ede3_ecb, LN_des_ede3_ecb, null); // NID: 33 + addObject(NID_idea_cbc, SN_idea_cbc, LN_idea_cbc, OBJ_idea_cbc); // NID: 34 + addObject(NID_idea_cfb64, SN_idea_cfb64, LN_idea_cfb64, null); // NID: 35 + addObject(NID_idea_ecb, SN_idea_ecb, LN_idea_ecb, null); // NID: 36 + addObject(NID_rc2_cbc, SN_rc2_cbc, LN_rc2_cbc, OBJ_rc2_cbc); // NID: 37 + addObject(NID_rc2_ecb, SN_rc2_ecb, LN_rc2_ecb, null); // NID: 38 + addObject(NID_rc2_cfb64, SN_rc2_cfb64, LN_rc2_cfb64, null); // NID: 39 + addObject(NID_rc2_ofb64, SN_rc2_ofb64, LN_rc2_ofb64, null); // NID: 40 + addObject(NID_sha, SN_sha, LN_sha, OBJ_sha); // NID: 41 + addObject(NID_shaWithRSAEncryption, SN_shaWithRSAEncryption, LN_shaWithRSAEncryption, OBJ_shaWithRSAEncryption); // NID: 42 + addObject(NID_des_ede_cbc, SN_des_ede_cbc, LN_des_ede_cbc, null); // NID: 43 + addObject(NID_des_ede3_cbc, SN_des_ede3_cbc, LN_des_ede3_cbc, OBJ_des_ede3_cbc); // NID: 44 + addObject(NID_des_ofb64, SN_des_ofb64, LN_des_ofb64, OBJ_des_ofb64); // NID: 45 + addObject(NID_idea_ofb64, SN_idea_ofb64, LN_idea_ofb64, null); // NID: 46 + addObject(NID_pkcs9, SN_pkcs9, null, OBJ_pkcs9); // NID: 47 + addObject(NID_pkcs9_emailAddress, null, LN_pkcs9_emailAddress, OBJ_pkcs9_emailAddress); // NID: 48 + addObject(NID_pkcs9_unstructuredName, null, LN_pkcs9_unstructuredName, OBJ_pkcs9_unstructuredName); // NID: 49 + addObject(NID_pkcs9_contentType, null, LN_pkcs9_contentType, OBJ_pkcs9_contentType); // NID: 50 + addObject(NID_pkcs9_messageDigest, null, LN_pkcs9_messageDigest, OBJ_pkcs9_messageDigest); // NID: 51 + addObject(NID_pkcs9_signingTime, null, LN_pkcs9_signingTime, OBJ_pkcs9_signingTime); // NID: 52 + addObject(NID_pkcs9_countersignature, null, LN_pkcs9_countersignature, OBJ_pkcs9_countersignature); // NID: 53 + addObject(NID_pkcs9_challengePassword, null, LN_pkcs9_challengePassword, OBJ_pkcs9_challengePassword); // NID: 54 + addObject(NID_pkcs9_unstructuredAddress, null, LN_pkcs9_unstructuredAddress, OBJ_pkcs9_unstructuredAddress); // NID: 55 + addObject(NID_pkcs9_extCertAttributes, null, LN_pkcs9_extCertAttributes, OBJ_pkcs9_extCertAttributes); // NID: 56 + addObject(NID_netscape, SN_netscape, LN_netscape, OBJ_netscape); // NID: 57 + addObject(NID_netscape_cert_extension, SN_netscape_cert_extension, LN_netscape_cert_extension, OBJ_netscape_cert_extension); // NID: 58 + addObject(NID_netscape_data_type, SN_netscape_data_type, LN_netscape_data_type, OBJ_netscape_data_type); // NID: 59 + addObject(NID_des_ede_cfb64, SN_des_ede_cfb64, LN_des_ede_cfb64, null); // NID: 60 + addObject(NID_des_ede3_cfb64, SN_des_ede3_cfb64, LN_des_ede3_cfb64, null); // NID: 61 + addObject(NID_des_ede_ofb64, SN_des_ede_ofb64, LN_des_ede_ofb64, null); // NID: 62 + addObject(NID_des_ede3_ofb64, SN_des_ede3_ofb64, LN_des_ede3_ofb64, null); // NID: 63 + addObject(NID_sha1, SN_sha1, LN_sha1, OBJ_sha1); // NID: 64 + addObject(NID_sha1WithRSAEncryption, SN_sha1WithRSAEncryption, LN_sha1WithRSAEncryption, OBJ_sha1WithRSAEncryption); // NID: 65 + addObject(NID_dsaWithSHA, SN_dsaWithSHA, LN_dsaWithSHA, OBJ_dsaWithSHA); // NID: 66 + addObject(NID_dsa_2, SN_dsa_2, LN_dsa_2, OBJ_dsa_2); // NID: 67 + addObject(NID_pbeWithSHA1AndRC2_CBC, SN_pbeWithSHA1AndRC2_CBC, LN_pbeWithSHA1AndRC2_CBC, OBJ_pbeWithSHA1AndRC2_CBC); // NID: 68 + addObject(NID_id_pbkdf2, null, LN_id_pbkdf2, OBJ_id_pbkdf2); // NID: 69 + addObject(NID_dsaWithSHA1_2, SN_dsaWithSHA1_2, LN_dsaWithSHA1_2, OBJ_dsaWithSHA1_2); // NID: 70 + addObject(NID_netscape_cert_type, SN_netscape_cert_type, LN_netscape_cert_type, OBJ_netscape_cert_type); // NID: 71 + addObject(NID_netscape_base_url, SN_netscape_base_url, LN_netscape_base_url, OBJ_netscape_base_url); // NID: 72 + addObject(NID_netscape_revocation_url, SN_netscape_revocation_url, LN_netscape_revocation_url, OBJ_netscape_revocation_url); // NID: 73 + addObject(NID_netscape_ca_revocation_url, SN_netscape_ca_revocation_url, LN_netscape_ca_revocation_url, OBJ_netscape_ca_revocation_url); // NID: 74 + addObject(NID_netscape_renewal_url, SN_netscape_renewal_url, LN_netscape_renewal_url, OBJ_netscape_renewal_url); // NID: 75 + addObject(NID_netscape_ca_policy_url, SN_netscape_ca_policy_url, LN_netscape_ca_policy_url, OBJ_netscape_ca_policy_url); // NID: 76 + addObject(NID_netscape_ssl_server_name, SN_netscape_ssl_server_name, LN_netscape_ssl_server_name, OBJ_netscape_ssl_server_name); // NID: 77 + addObject(NID_netscape_comment, SN_netscape_comment, LN_netscape_comment, OBJ_netscape_comment); // NID: 78 + addObject(NID_netscape_cert_sequence, SN_netscape_cert_sequence, LN_netscape_cert_sequence, OBJ_netscape_cert_sequence); // NID: 79 + addObject(NID_desx_cbc, SN_desx_cbc, LN_desx_cbc, null); // NID: 80 + addObject(NID_id_ce, SN_id_ce, null, OBJ_id_ce); // NID: 81 + addObject(NID_subject_key_identifier, SN_subject_key_identifier, LN_subject_key_identifier, OBJ_subject_key_identifier); // NID: 82 + addObject(NID_key_usage, SN_key_usage, LN_key_usage, OBJ_key_usage); // NID: 83 + addObject(NID_private_key_usage_period, SN_private_key_usage_period, LN_private_key_usage_period, OBJ_private_key_usage_period); // NID: 84 + addObject(NID_subject_alt_name, SN_subject_alt_name, LN_subject_alt_name, OBJ_subject_alt_name); // NID: 85 + addObject(NID_issuer_alt_name, SN_issuer_alt_name, LN_issuer_alt_name, OBJ_issuer_alt_name); // NID: 86 + addObject(NID_basic_constraints, SN_basic_constraints, LN_basic_constraints, OBJ_basic_constraints); // NID: 87 + addObject(NID_crl_number, SN_crl_number, LN_crl_number, OBJ_crl_number); // NID: 88 + addObject(NID_certificate_policies, SN_certificate_policies, LN_certificate_policies, OBJ_certificate_policies); // NID: 89 + addObject(NID_authority_key_identifier, SN_authority_key_identifier, LN_authority_key_identifier, OBJ_authority_key_identifier); // NID: 90 + addObject(NID_bf_cbc, SN_bf_cbc, LN_bf_cbc, OBJ_bf_cbc); // NID: 91 + addObject(NID_bf_ecb, SN_bf_ecb, LN_bf_ecb, null); // NID: 92 + addObject(NID_bf_cfb64, SN_bf_cfb64, LN_bf_cfb64, null); // NID: 93 + addObject(NID_bf_ofb64, SN_bf_ofb64, LN_bf_ofb64, null); // NID: 94 + addObject(NID_mdc2, SN_mdc2, LN_mdc2, OBJ_mdc2); // NID: 95 + addObject(NID_mdc2WithRSA, SN_mdc2WithRSA, LN_mdc2WithRSA, OBJ_mdc2WithRSA); // NID: 96 + addObject(NID_rc4_40, SN_rc4_40, LN_rc4_40, null); // NID: 97 + addObject(NID_rc2_40_cbc, SN_rc2_40_cbc, LN_rc2_40_cbc, OBJ_rc2_40_cbc); // NID: 98 + addObject(NID_givenName, SN_givenName, LN_givenName, OBJ_givenName); // NID: 99 + addObject(NID_surname, SN_surname, LN_surname, OBJ_surname); // NID: 100 + addObject(NID_initials, null, LN_initials, OBJ_initials); // NID: 101 + addObject(NID_crl_distribution_points, SN_crl_distribution_points, LN_crl_distribution_points, OBJ_crl_distribution_points); // NID: 103 + addObject(NID_md5WithRSA, SN_md5WithRSA, LN_md5WithRSA, OBJ_md5WithRSA); // NID: 104 + addObject(NID_serialNumber, null, LN_serialNumber, OBJ_serialNumber); // NID: 105 + addObject(NID_title, null, LN_title, OBJ_title); // NID: 106 + addObject(NID_description, null, LN_description, OBJ_description); // NID: 107 + addObject(NID_cast5_cbc, SN_cast5_cbc, LN_cast5_cbc, OBJ_cast5_cbc); // NID: 108 + addObject(NID_cast5_ecb, SN_cast5_ecb, LN_cast5_ecb, null); // NID: 109 + addObject(NID_cast5_cfb64, SN_cast5_cfb64, LN_cast5_cfb64, null); // NID: 110 + addObject(NID_cast5_ofb64, SN_cast5_ofb64, LN_cast5_ofb64, null); // NID: 111 + addObject(NID_pbeWithMD5AndCast5_CBC, null, LN_pbeWithMD5AndCast5_CBC, OBJ_pbeWithMD5AndCast5_CBC); // NID: 112 + addObject(NID_dsaWithSHA1, SN_dsaWithSHA1, LN_dsaWithSHA1, OBJ_dsaWithSHA1); // NID: 113 + addObject(NID_md5_sha1, SN_md5_sha1, LN_md5_sha1, null); // NID: 114 + addObject(NID_sha1WithRSA, SN_sha1WithRSA, LN_sha1WithRSA, OBJ_sha1WithRSA); // NID: 115 + addObject(NID_dsa, SN_dsa, LN_dsa, OBJ_dsa); // NID: 116 + addObject(NID_ripemd160, SN_ripemd160, LN_ripemd160, OBJ_ripemd160); // NID: 117 + addObject(NID_ripemd160WithRSA, SN_ripemd160WithRSA, LN_ripemd160WithRSA, OBJ_ripemd160WithRSA); // NID: 119 + addObject(NID_rc5_cbc, SN_rc5_cbc, LN_rc5_cbc, OBJ_rc5_cbc); // NID: 120 + addObject(NID_rc5_ecb, SN_rc5_ecb, LN_rc5_ecb, null); // NID: 121 + addObject(NID_rc5_cfb64, SN_rc5_cfb64, LN_rc5_cfb64, null); // NID: 122 + addObject(NID_rc5_ofb64, SN_rc5_ofb64, LN_rc5_ofb64, null); // NID: 123 + addObject(NID_rle_compression, SN_rle_compression, LN_rle_compression, OBJ_rle_compression); // NID: 124 + addObject(NID_zlib_compression, SN_zlib_compression, LN_zlib_compression, OBJ_zlib_compression); // NID: 125 + addObject(NID_ext_key_usage, SN_ext_key_usage, LN_ext_key_usage, OBJ_ext_key_usage); // NID: 126 + addObject(NID_id_pkix, SN_id_pkix, null, OBJ_id_pkix); // NID: 127 + addObject(NID_id_kp, SN_id_kp, null, OBJ_id_kp); // NID: 128 + addObject(NID_server_auth, SN_server_auth, LN_server_auth, OBJ_server_auth); // NID: 129 + addObject(NID_client_auth, SN_client_auth, LN_client_auth, OBJ_client_auth); // NID: 130 + addObject(NID_code_sign, SN_code_sign, LN_code_sign, OBJ_code_sign); // NID: 131 + addObject(NID_email_protect, SN_email_protect, LN_email_protect, OBJ_email_protect); // NID: 132 + addObject(NID_time_stamp, SN_time_stamp, LN_time_stamp, OBJ_time_stamp); // NID: 133 + addObject(NID_ms_code_ind, SN_ms_code_ind, LN_ms_code_ind, OBJ_ms_code_ind); // NID: 134 + addObject(NID_ms_code_com, SN_ms_code_com, LN_ms_code_com, OBJ_ms_code_com); // NID: 135 + addObject(NID_ms_ctl_sign, SN_ms_ctl_sign, LN_ms_ctl_sign, OBJ_ms_ctl_sign); // NID: 136 + addObject(NID_ms_sgc, SN_ms_sgc, LN_ms_sgc, OBJ_ms_sgc); // NID: 137 + addObject(NID_ms_efs, SN_ms_efs, LN_ms_efs, OBJ_ms_efs); // NID: 138 + addObject(NID_ns_sgc, SN_ns_sgc, LN_ns_sgc, OBJ_ns_sgc); // NID: 139 + addObject(NID_delta_crl, SN_delta_crl, LN_delta_crl, OBJ_delta_crl); // NID: 140 + addObject(NID_crl_reason, SN_crl_reason, LN_crl_reason, OBJ_crl_reason); // NID: 141 + addObject(NID_invalidity_date, SN_invalidity_date, LN_invalidity_date, OBJ_invalidity_date); // NID: 142 + addObject(NID_sxnet, SN_sxnet, LN_sxnet, OBJ_sxnet); // NID: 143 + addObject(NID_pbe_WithSHA1And128BitRC4, SN_pbe_WithSHA1And128BitRC4, LN_pbe_WithSHA1And128BitRC4, OBJ_pbe_WithSHA1And128BitRC4); // NID: 144 + addObject(NID_pbe_WithSHA1And40BitRC4, SN_pbe_WithSHA1And40BitRC4, LN_pbe_WithSHA1And40BitRC4, OBJ_pbe_WithSHA1And40BitRC4); // NID: 145 + addObject(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, SN_pbe_WithSHA1And3_Key_TripleDES_CBC, LN_pbe_WithSHA1And3_Key_TripleDES_CBC, OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC); // NID: 146 + addObject(NID_pbe_WithSHA1And2_Key_TripleDES_CBC, SN_pbe_WithSHA1And2_Key_TripleDES_CBC, LN_pbe_WithSHA1And2_Key_TripleDES_CBC, OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC); // NID: 147 + addObject(NID_pbe_WithSHA1And128BitRC2_CBC, SN_pbe_WithSHA1And128BitRC2_CBC, LN_pbe_WithSHA1And128BitRC2_CBC, OBJ_pbe_WithSHA1And128BitRC2_CBC); // NID: 148 + addObject(NID_pbe_WithSHA1And40BitRC2_CBC, SN_pbe_WithSHA1And40BitRC2_CBC, LN_pbe_WithSHA1And40BitRC2_CBC, OBJ_pbe_WithSHA1And40BitRC2_CBC); // NID: 149 + addObject(NID_keyBag, null, LN_keyBag, OBJ_keyBag); // NID: 150 + addObject(NID_pkcs8ShroudedKeyBag, null, LN_pkcs8ShroudedKeyBag, OBJ_pkcs8ShroudedKeyBag); // NID: 151 + addObject(NID_certBag, null, LN_certBag, OBJ_certBag); // NID: 152 + addObject(NID_crlBag, null, LN_crlBag, OBJ_crlBag); // NID: 153 + addObject(NID_secretBag, null, LN_secretBag, OBJ_secretBag); // NID: 154 + addObject(NID_safeContentsBag, null, LN_safeContentsBag, OBJ_safeContentsBag); // NID: 155 + addObject(NID_friendlyName, null, LN_friendlyName, OBJ_friendlyName); // NID: 156 + addObject(NID_localKeyID, null, LN_localKeyID, OBJ_localKeyID); // NID: 157 + addObject(NID_x509Certificate, null, LN_x509Certificate, OBJ_x509Certificate); // NID: 158 + addObject(NID_sdsiCertificate, null, LN_sdsiCertificate, OBJ_sdsiCertificate); // NID: 159 + addObject(NID_x509Crl, null, LN_x509Crl, OBJ_x509Crl); // NID: 160 + addObject(NID_pbes2, null, LN_pbes2, OBJ_pbes2); // NID: 161 + addObject(NID_pbmac1, null, LN_pbmac1, OBJ_pbmac1); // NID: 162 + addObject(NID_hmacWithSHA1, null, LN_hmacWithSHA1, OBJ_hmacWithSHA1); // NID: 163 + addObject(NID_id_qt_cps, SN_id_qt_cps, LN_id_qt_cps, OBJ_id_qt_cps); // NID: 164 + addObject(NID_id_qt_unotice, SN_id_qt_unotice, LN_id_qt_unotice, OBJ_id_qt_unotice); // NID: 165 + addObject(NID_rc2_64_cbc, SN_rc2_64_cbc, LN_rc2_64_cbc, null); // NID: 166 + addObject(NID_SMIMECapabilities, SN_SMIMECapabilities, LN_SMIMECapabilities, OBJ_SMIMECapabilities); // NID: 167 + addObject(NID_pbeWithMD2AndRC2_CBC, SN_pbeWithMD2AndRC2_CBC, LN_pbeWithMD2AndRC2_CBC, OBJ_pbeWithMD2AndRC2_CBC); // NID: 168 + addObject(NID_pbeWithMD5AndRC2_CBC, SN_pbeWithMD5AndRC2_CBC, LN_pbeWithMD5AndRC2_CBC, OBJ_pbeWithMD5AndRC2_CBC); // NID: 169 + addObject(NID_pbeWithSHA1AndDES_CBC, SN_pbeWithSHA1AndDES_CBC, LN_pbeWithSHA1AndDES_CBC, OBJ_pbeWithSHA1AndDES_CBC); // NID: 170 + addObject(NID_ms_ext_req, SN_ms_ext_req, LN_ms_ext_req, OBJ_ms_ext_req); // NID: 171 + addObject(NID_ext_req, SN_ext_req, LN_ext_req, OBJ_ext_req); // NID: 172 + addObject(NID_name, SN_name, LN_name, OBJ_name); // NID: 173 + addObject(NID_dnQualifier, SN_dnQualifier, LN_dnQualifier, OBJ_dnQualifier); // NID: 174 + addObject(NID_id_pe, SN_id_pe, null, OBJ_id_pe); // NID: 175 + addObject(NID_id_ad, SN_id_ad, null, OBJ_id_ad); // NID: 176 + addObject(NID_info_access, SN_info_access, LN_info_access, OBJ_info_access); // NID: 177 + addObject(NID_ad_OCSP, SN_ad_OCSP, LN_ad_OCSP, OBJ_ad_OCSP); // NID: 178 + addObject(NID_ad_ca_issuers, SN_ad_ca_issuers, LN_ad_ca_issuers, OBJ_ad_ca_issuers); // NID: 179 + addObject(NID_OCSP_sign, SN_OCSP_sign, LN_OCSP_sign, OBJ_OCSP_sign); // NID: 180 + addObject(NID_iso, SN_iso, LN_iso, OBJ_iso); // NID: 181 + addObject(NID_member_body, SN_member_body, LN_member_body, OBJ_member_body); // NID: 182 + addObject(NID_ISO_US, SN_ISO_US, LN_ISO_US, OBJ_ISO_US); // NID: 183 + addObject(NID_X9_57, SN_X9_57, LN_X9_57, OBJ_X9_57); // NID: 184 + addObject(NID_X9cm, SN_X9cm, LN_X9cm, OBJ_X9cm); // NID: 185 + addObject(NID_pkcs1, SN_pkcs1, null, OBJ_pkcs1); // NID: 186 + addObject(NID_pkcs5, SN_pkcs5, null, OBJ_pkcs5); // NID: 187 + addObject(NID_SMIME, SN_SMIME, LN_SMIME, OBJ_SMIME); // NID: 188 + addObject(NID_id_smime_mod, SN_id_smime_mod, null, OBJ_id_smime_mod); // NID: 189 + addObject(NID_id_smime_ct, SN_id_smime_ct, null, OBJ_id_smime_ct); // NID: 190 + addObject(NID_id_smime_aa, SN_id_smime_aa, null, OBJ_id_smime_aa); // NID: 191 + addObject(NID_id_smime_alg, SN_id_smime_alg, null, OBJ_id_smime_alg); // NID: 192 + addObject(NID_id_smime_cd, SN_id_smime_cd, null, OBJ_id_smime_cd); // NID: 193 + addObject(NID_id_smime_spq, SN_id_smime_spq, null, OBJ_id_smime_spq); // NID: 194 + addObject(NID_id_smime_cti, SN_id_smime_cti, null, OBJ_id_smime_cti); // NID: 195 + addObject(NID_id_smime_mod_cms, SN_id_smime_mod_cms, null, OBJ_id_smime_mod_cms); // NID: 196 + addObject(NID_id_smime_mod_ess, SN_id_smime_mod_ess, null, OBJ_id_smime_mod_ess); // NID: 197 + addObject(NID_id_smime_mod_oid, SN_id_smime_mod_oid, null, OBJ_id_smime_mod_oid); // NID: 198 + addObject(NID_id_smime_mod_msg_v3, SN_id_smime_mod_msg_v3, null, OBJ_id_smime_mod_msg_v3); // NID: 199 + addObject(NID_id_smime_mod_ets_eSignature_88, SN_id_smime_mod_ets_eSignature_88, null, OBJ_id_smime_mod_ets_eSignature_88); // NID: 200 + addObject(NID_id_smime_mod_ets_eSignature_97, SN_id_smime_mod_ets_eSignature_97, null, OBJ_id_smime_mod_ets_eSignature_97); // NID: 201 + addObject(NID_id_smime_mod_ets_eSigPolicy_88, SN_id_smime_mod_ets_eSigPolicy_88, null, OBJ_id_smime_mod_ets_eSigPolicy_88); // NID: 202 + addObject(NID_id_smime_mod_ets_eSigPolicy_97, SN_id_smime_mod_ets_eSigPolicy_97, null, OBJ_id_smime_mod_ets_eSigPolicy_97); // NID: 203 + addObject(NID_id_smime_ct_receipt, SN_id_smime_ct_receipt, null, OBJ_id_smime_ct_receipt); // NID: 204 + addObject(NID_id_smime_ct_authData, SN_id_smime_ct_authData, null, OBJ_id_smime_ct_authData); // NID: 205 + addObject(NID_id_smime_ct_publishCert, SN_id_smime_ct_publishCert, null, OBJ_id_smime_ct_publishCert); // NID: 206 + addObject(NID_id_smime_ct_TSTInfo, SN_id_smime_ct_TSTInfo, null, OBJ_id_smime_ct_TSTInfo); // NID: 207 + addObject(NID_id_smime_ct_TDTInfo, SN_id_smime_ct_TDTInfo, null, OBJ_id_smime_ct_TDTInfo); // NID: 208 + addObject(NID_id_smime_ct_contentInfo, SN_id_smime_ct_contentInfo, null, OBJ_id_smime_ct_contentInfo); // NID: 209 + addObject(NID_id_smime_ct_DVCSRequestData, SN_id_smime_ct_DVCSRequestData, null, OBJ_id_smime_ct_DVCSRequestData); // NID: 210 + addObject(NID_id_smime_ct_DVCSResponseData, SN_id_smime_ct_DVCSResponseData, null, OBJ_id_smime_ct_DVCSResponseData); // NID: 211 + addObject(NID_id_smime_aa_receiptRequest, SN_id_smime_aa_receiptRequest, null, OBJ_id_smime_aa_receiptRequest); // NID: 212 + addObject(NID_id_smime_aa_securityLabel, SN_id_smime_aa_securityLabel, null, OBJ_id_smime_aa_securityLabel); // NID: 213 + addObject(NID_id_smime_aa_mlExpandHistory, SN_id_smime_aa_mlExpandHistory, null, OBJ_id_smime_aa_mlExpandHistory); // NID: 214 + addObject(NID_id_smime_aa_contentHint, SN_id_smime_aa_contentHint, null, OBJ_id_smime_aa_contentHint); // NID: 215 + addObject(NID_id_smime_aa_msgSigDigest, SN_id_smime_aa_msgSigDigest, null, OBJ_id_smime_aa_msgSigDigest); // NID: 216 + addObject(NID_id_smime_aa_encapContentType, SN_id_smime_aa_encapContentType, null, OBJ_id_smime_aa_encapContentType); // NID: 217 + addObject(NID_id_smime_aa_contentIdentifier, SN_id_smime_aa_contentIdentifier, null, OBJ_id_smime_aa_contentIdentifier); // NID: 218 + addObject(NID_id_smime_aa_macValue, SN_id_smime_aa_macValue, null, OBJ_id_smime_aa_macValue); // NID: 219 + addObject(NID_id_smime_aa_equivalentLabels, SN_id_smime_aa_equivalentLabels, null, OBJ_id_smime_aa_equivalentLabels); // NID: 220 + addObject(NID_id_smime_aa_contentReference, SN_id_smime_aa_contentReference, null, OBJ_id_smime_aa_contentReference); // NID: 221 + addObject(NID_id_smime_aa_encrypKeyPref, SN_id_smime_aa_encrypKeyPref, null, OBJ_id_smime_aa_encrypKeyPref); // NID: 222 + addObject(NID_id_smime_aa_signingCertificate, SN_id_smime_aa_signingCertificate, null, OBJ_id_smime_aa_signingCertificate); // NID: 223 + addObject(NID_id_smime_aa_smimeEncryptCerts, SN_id_smime_aa_smimeEncryptCerts, null, OBJ_id_smime_aa_smimeEncryptCerts); // NID: 224 + addObject(NID_id_smime_aa_timeStampToken, SN_id_smime_aa_timeStampToken, null, OBJ_id_smime_aa_timeStampToken); // NID: 225 + addObject(NID_id_smime_aa_ets_sigPolicyId, SN_id_smime_aa_ets_sigPolicyId, null, OBJ_id_smime_aa_ets_sigPolicyId); // NID: 226 + addObject(NID_id_smime_aa_ets_commitmentType, SN_id_smime_aa_ets_commitmentType, null, OBJ_id_smime_aa_ets_commitmentType); // NID: 227 + addObject(NID_id_smime_aa_ets_signerLocation, SN_id_smime_aa_ets_signerLocation, null, OBJ_id_smime_aa_ets_signerLocation); // NID: 228 + addObject(NID_id_smime_aa_ets_signerAttr, SN_id_smime_aa_ets_signerAttr, null, OBJ_id_smime_aa_ets_signerAttr); // NID: 229 + addObject(NID_id_smime_aa_ets_otherSigCert, SN_id_smime_aa_ets_otherSigCert, null, OBJ_id_smime_aa_ets_otherSigCert); // NID: 230 + addObject(NID_id_smime_aa_ets_contentTimestamp, SN_id_smime_aa_ets_contentTimestamp, null, OBJ_id_smime_aa_ets_contentTimestamp); // NID: 231 + addObject(NID_id_smime_aa_ets_CertificateRefs, SN_id_smime_aa_ets_CertificateRefs, null, OBJ_id_smime_aa_ets_CertificateRefs); // NID: 232 + addObject(NID_id_smime_aa_ets_RevocationRefs, SN_id_smime_aa_ets_RevocationRefs, null, OBJ_id_smime_aa_ets_RevocationRefs); // NID: 233 + addObject(NID_id_smime_aa_ets_certValues, SN_id_smime_aa_ets_certValues, null, OBJ_id_smime_aa_ets_certValues); // NID: 234 + addObject(NID_id_smime_aa_ets_revocationValues, SN_id_smime_aa_ets_revocationValues, null, OBJ_id_smime_aa_ets_revocationValues); // NID: 235 + addObject(NID_id_smime_aa_ets_escTimeStamp, SN_id_smime_aa_ets_escTimeStamp, null, OBJ_id_smime_aa_ets_escTimeStamp); // NID: 236 + addObject(NID_id_smime_aa_ets_certCRLTimestamp, SN_id_smime_aa_ets_certCRLTimestamp, null, OBJ_id_smime_aa_ets_certCRLTimestamp); // NID: 237 + addObject(NID_id_smime_aa_ets_archiveTimeStamp, SN_id_smime_aa_ets_archiveTimeStamp, null, OBJ_id_smime_aa_ets_archiveTimeStamp); // NID: 238 + addObject(NID_id_smime_aa_signatureType, SN_id_smime_aa_signatureType, null, OBJ_id_smime_aa_signatureType); // NID: 239 + addObject(NID_id_smime_aa_dvcs_dvc, SN_id_smime_aa_dvcs_dvc, null, OBJ_id_smime_aa_dvcs_dvc); // NID: 240 + addObject(NID_id_smime_alg_ESDHwith3DES, SN_id_smime_alg_ESDHwith3DES, null, OBJ_id_smime_alg_ESDHwith3DES); // NID: 241 + addObject(NID_id_smime_alg_ESDHwithRC2, SN_id_smime_alg_ESDHwithRC2, null, OBJ_id_smime_alg_ESDHwithRC2); // NID: 242 + addObject(NID_id_smime_alg_3DESwrap, SN_id_smime_alg_3DESwrap, null, OBJ_id_smime_alg_3DESwrap); // NID: 243 + addObject(NID_id_smime_alg_RC2wrap, SN_id_smime_alg_RC2wrap, null, OBJ_id_smime_alg_RC2wrap); // NID: 244 + addObject(NID_id_smime_alg_ESDH, SN_id_smime_alg_ESDH, null, OBJ_id_smime_alg_ESDH); // NID: 245 + addObject(NID_id_smime_alg_CMS3DESwrap, SN_id_smime_alg_CMS3DESwrap, null, OBJ_id_smime_alg_CMS3DESwrap); // NID: 246 + addObject(NID_id_smime_alg_CMSRC2wrap, SN_id_smime_alg_CMSRC2wrap, null, OBJ_id_smime_alg_CMSRC2wrap); // NID: 247 + addObject(NID_id_smime_cd_ldap, SN_id_smime_cd_ldap, null, OBJ_id_smime_cd_ldap); // NID: 248 + addObject(NID_id_smime_spq_ets_sqt_uri, SN_id_smime_spq_ets_sqt_uri, null, OBJ_id_smime_spq_ets_sqt_uri); // NID: 249 + addObject(NID_id_smime_spq_ets_sqt_unotice, SN_id_smime_spq_ets_sqt_unotice, null, OBJ_id_smime_spq_ets_sqt_unotice); // NID: 250 + addObject(NID_id_smime_cti_ets_proofOfOrigin, SN_id_smime_cti_ets_proofOfOrigin, null, OBJ_id_smime_cti_ets_proofOfOrigin); // NID: 251 + addObject(NID_id_smime_cti_ets_proofOfReceipt, SN_id_smime_cti_ets_proofOfReceipt, null, OBJ_id_smime_cti_ets_proofOfReceipt); // NID: 252 + addObject(NID_id_smime_cti_ets_proofOfDelivery, SN_id_smime_cti_ets_proofOfDelivery, null, OBJ_id_smime_cti_ets_proofOfDelivery); // NID: 253 + addObject(NID_id_smime_cti_ets_proofOfSender, SN_id_smime_cti_ets_proofOfSender, null, OBJ_id_smime_cti_ets_proofOfSender); // NID: 254 + addObject(NID_id_smime_cti_ets_proofOfApproval, SN_id_smime_cti_ets_proofOfApproval, null, OBJ_id_smime_cti_ets_proofOfApproval); // NID: 255 + addObject(NID_id_smime_cti_ets_proofOfCreation, SN_id_smime_cti_ets_proofOfCreation, null, OBJ_id_smime_cti_ets_proofOfCreation); // NID: 256 + addObject(NID_md4, SN_md4, LN_md4, OBJ_md4); // NID: 257 + addObject(NID_id_pkix_mod, SN_id_pkix_mod, null, OBJ_id_pkix_mod); // NID: 258 + addObject(NID_id_qt, SN_id_qt, null, OBJ_id_qt); // NID: 259 + addObject(NID_id_it, SN_id_it, null, OBJ_id_it); // NID: 260 + addObject(NID_id_pkip, SN_id_pkip, null, OBJ_id_pkip); // NID: 261 + addObject(NID_id_alg, SN_id_alg, null, OBJ_id_alg); // NID: 262 + addObject(NID_id_cmc, SN_id_cmc, null, OBJ_id_cmc); // NID: 263 + addObject(NID_id_on, SN_id_on, null, OBJ_id_on); // NID: 264 + addObject(NID_id_pda, SN_id_pda, null, OBJ_id_pda); // NID: 265 + addObject(NID_id_aca, SN_id_aca, null, OBJ_id_aca); // NID: 266 + addObject(NID_id_qcs, SN_id_qcs, null, OBJ_id_qcs); // NID: 267 + addObject(NID_id_cct, SN_id_cct, null, OBJ_id_cct); // NID: 268 + addObject(NID_id_pkix1_explicit_88, SN_id_pkix1_explicit_88, null, OBJ_id_pkix1_explicit_88); // NID: 269 + addObject(NID_id_pkix1_implicit_88, SN_id_pkix1_implicit_88, null, OBJ_id_pkix1_implicit_88); // NID: 270 + addObject(NID_id_pkix1_explicit_93, SN_id_pkix1_explicit_93, null, OBJ_id_pkix1_explicit_93); // NID: 271 + addObject(NID_id_pkix1_implicit_93, SN_id_pkix1_implicit_93, null, OBJ_id_pkix1_implicit_93); // NID: 272 + addObject(NID_id_mod_crmf, SN_id_mod_crmf, null, OBJ_id_mod_crmf); // NID: 273 + addObject(NID_id_mod_cmc, SN_id_mod_cmc, null, OBJ_id_mod_cmc); // NID: 274 + addObject(NID_id_mod_kea_profile_88, SN_id_mod_kea_profile_88, null, OBJ_id_mod_kea_profile_88); // NID: 275 + addObject(NID_id_mod_kea_profile_93, SN_id_mod_kea_profile_93, null, OBJ_id_mod_kea_profile_93); // NID: 276 + addObject(NID_id_mod_cmp, SN_id_mod_cmp, null, OBJ_id_mod_cmp); // NID: 277 + addObject(NID_id_mod_qualified_cert_88, SN_id_mod_qualified_cert_88, null, OBJ_id_mod_qualified_cert_88); // NID: 278 + addObject(NID_id_mod_qualified_cert_93, SN_id_mod_qualified_cert_93, null, OBJ_id_mod_qualified_cert_93); // NID: 279 + addObject(NID_id_mod_attribute_cert, SN_id_mod_attribute_cert, null, OBJ_id_mod_attribute_cert); // NID: 280 + addObject(NID_id_mod_timestamp_protocol, SN_id_mod_timestamp_protocol, null, OBJ_id_mod_timestamp_protocol); // NID: 281 + addObject(NID_id_mod_ocsp, SN_id_mod_ocsp, null, OBJ_id_mod_ocsp); // NID: 282 + addObject(NID_id_mod_dvcs, SN_id_mod_dvcs, null, OBJ_id_mod_dvcs); // NID: 283 + addObject(NID_id_mod_cmp2000, SN_id_mod_cmp2000, null, OBJ_id_mod_cmp2000); // NID: 284 + addObject(NID_biometricInfo, SN_biometricInfo, LN_biometricInfo, OBJ_biometricInfo); // NID: 285 + addObject(NID_qcStatements, SN_qcStatements, null, OBJ_qcStatements); // NID: 286 + addObject(NID_ac_auditEntity, SN_ac_auditEntity, null, OBJ_ac_auditEntity); // NID: 287 + addObject(NID_ac_targeting, SN_ac_targeting, null, OBJ_ac_targeting); // NID: 288 + addObject(NID_aaControls, SN_aaControls, null, OBJ_aaControls); // NID: 289 + addObject(NID_sbgp_ipAddrBlock, SN_sbgp_ipAddrBlock, null, OBJ_sbgp_ipAddrBlock); // NID: 290 + addObject(NID_sbgp_autonomousSysNum, SN_sbgp_autonomousSysNum, null, OBJ_sbgp_autonomousSysNum); // NID: 291 + addObject(NID_sbgp_routerIdentifier, SN_sbgp_routerIdentifier, null, OBJ_sbgp_routerIdentifier); // NID: 292 + addObject(NID_textNotice, SN_textNotice, null, OBJ_textNotice); // NID: 293 + addObject(NID_ipsecEndSystem, SN_ipsecEndSystem, LN_ipsecEndSystem, OBJ_ipsecEndSystem); // NID: 294 + addObject(NID_ipsecTunnel, SN_ipsecTunnel, LN_ipsecTunnel, OBJ_ipsecTunnel); // NID: 295 + addObject(NID_ipsecUser, SN_ipsecUser, LN_ipsecUser, OBJ_ipsecUser); // NID: 296 + addObject(NID_dvcs, SN_dvcs, LN_dvcs, OBJ_dvcs); // NID: 297 + addObject(NID_id_it_caProtEncCert, SN_id_it_caProtEncCert, null, OBJ_id_it_caProtEncCert); // NID: 298 + addObject(NID_id_it_signKeyPairTypes, SN_id_it_signKeyPairTypes, null, OBJ_id_it_signKeyPairTypes); // NID: 299 + addObject(NID_id_it_encKeyPairTypes, SN_id_it_encKeyPairTypes, null, OBJ_id_it_encKeyPairTypes); // NID: 300 + addObject(NID_id_it_preferredSymmAlg, SN_id_it_preferredSymmAlg, null, OBJ_id_it_preferredSymmAlg); // NID: 301 + addObject(NID_id_it_caKeyUpdateInfo, SN_id_it_caKeyUpdateInfo, null, OBJ_id_it_caKeyUpdateInfo); // NID: 302 + addObject(NID_id_it_currentCRL, SN_id_it_currentCRL, null, OBJ_id_it_currentCRL); // NID: 303 + addObject(NID_id_it_unsupportedOIDs, SN_id_it_unsupportedOIDs, null, OBJ_id_it_unsupportedOIDs); // NID: 304 + addObject(NID_id_it_subscriptionRequest, SN_id_it_subscriptionRequest, null, OBJ_id_it_subscriptionRequest); // NID: 305 + addObject(NID_id_it_subscriptionResponse, SN_id_it_subscriptionResponse, null, OBJ_id_it_subscriptionResponse); // NID: 306 + addObject(NID_id_it_keyPairParamReq, SN_id_it_keyPairParamReq, null, OBJ_id_it_keyPairParamReq); // NID: 307 + addObject(NID_id_it_keyPairParamRep, SN_id_it_keyPairParamRep, null, OBJ_id_it_keyPairParamRep); // NID: 308 + addObject(NID_id_it_revPassphrase, SN_id_it_revPassphrase, null, OBJ_id_it_revPassphrase); // NID: 309 + addObject(NID_id_it_implicitConfirm, SN_id_it_implicitConfirm, null, OBJ_id_it_implicitConfirm); // NID: 310 + addObject(NID_id_it_confirmWaitTime, SN_id_it_confirmWaitTime, null, OBJ_id_it_confirmWaitTime); // NID: 311 + addObject(NID_id_it_origPKIMessage, SN_id_it_origPKIMessage, null, OBJ_id_it_origPKIMessage); // NID: 312 + addObject(NID_id_regCtrl, SN_id_regCtrl, null, OBJ_id_regCtrl); // NID: 313 + addObject(NID_id_regInfo, SN_id_regInfo, null, OBJ_id_regInfo); // NID: 314 + addObject(NID_id_regCtrl_regToken, SN_id_regCtrl_regToken, null, OBJ_id_regCtrl_regToken); // NID: 315 + addObject(NID_id_regCtrl_authenticator, SN_id_regCtrl_authenticator, null, OBJ_id_regCtrl_authenticator); // NID: 316 + addObject(NID_id_regCtrl_pkiPublicationInfo, SN_id_regCtrl_pkiPublicationInfo, null, OBJ_id_regCtrl_pkiPublicationInfo); // NID: 317 + addObject(NID_id_regCtrl_pkiArchiveOptions, SN_id_regCtrl_pkiArchiveOptions, null, OBJ_id_regCtrl_pkiArchiveOptions); // NID: 318 + addObject(NID_id_regCtrl_oldCertID, SN_id_regCtrl_oldCertID, null, OBJ_id_regCtrl_oldCertID); // NID: 319 + addObject(NID_id_regCtrl_protocolEncrKey, SN_id_regCtrl_protocolEncrKey, null, OBJ_id_regCtrl_protocolEncrKey); // NID: 320 + addObject(NID_id_regInfo_utf8Pairs, SN_id_regInfo_utf8Pairs, null, OBJ_id_regInfo_utf8Pairs); // NID: 321 + addObject(NID_id_regInfo_certReq, SN_id_regInfo_certReq, null, OBJ_id_regInfo_certReq); // NID: 322 + addObject(NID_id_alg_des40, SN_id_alg_des40, null, OBJ_id_alg_des40); // NID: 323 + addObject(NID_id_alg_noSignature, SN_id_alg_noSignature, null, OBJ_id_alg_noSignature); // NID: 324 + addObject(NID_id_alg_dh_sig_hmac_sha1, SN_id_alg_dh_sig_hmac_sha1, null, OBJ_id_alg_dh_sig_hmac_sha1); // NID: 325 + addObject(NID_id_alg_dh_pop, SN_id_alg_dh_pop, null, OBJ_id_alg_dh_pop); // NID: 326 + addObject(NID_id_cmc_statusInfo, SN_id_cmc_statusInfo, null, OBJ_id_cmc_statusInfo); // NID: 327 + addObject(NID_id_cmc_identification, SN_id_cmc_identification, null, OBJ_id_cmc_identification); // NID: 328 + addObject(NID_id_cmc_identityProof, SN_id_cmc_identityProof, null, OBJ_id_cmc_identityProof); // NID: 329 + addObject(NID_id_cmc_dataReturn, SN_id_cmc_dataReturn, null, OBJ_id_cmc_dataReturn); // NID: 330 + addObject(NID_id_cmc_transactionId, SN_id_cmc_transactionId, null, OBJ_id_cmc_transactionId); // NID: 331 + addObject(NID_id_cmc_senderNonce, SN_id_cmc_senderNonce, null, OBJ_id_cmc_senderNonce); // NID: 332 + addObject(NID_id_cmc_recipientNonce, SN_id_cmc_recipientNonce, null, OBJ_id_cmc_recipientNonce); // NID: 333 + addObject(NID_id_cmc_addExtensions, SN_id_cmc_addExtensions, null, OBJ_id_cmc_addExtensions); // NID: 334 + addObject(NID_id_cmc_encryptedPOP, SN_id_cmc_encryptedPOP, null, OBJ_id_cmc_encryptedPOP); // NID: 335 + addObject(NID_id_cmc_decryptedPOP, SN_id_cmc_decryptedPOP, null, OBJ_id_cmc_decryptedPOP); // NID: 336 + addObject(NID_id_cmc_lraPOPWitness, SN_id_cmc_lraPOPWitness, null, OBJ_id_cmc_lraPOPWitness); // NID: 337 + addObject(NID_id_cmc_getCert, SN_id_cmc_getCert, null, OBJ_id_cmc_getCert); // NID: 338 + addObject(NID_id_cmc_getCRL, SN_id_cmc_getCRL, null, OBJ_id_cmc_getCRL); // NID: 339 + addObject(NID_id_cmc_revokeRequest, SN_id_cmc_revokeRequest, null, OBJ_id_cmc_revokeRequest); // NID: 340 + addObject(NID_id_cmc_regInfo, SN_id_cmc_regInfo, null, OBJ_id_cmc_regInfo); // NID: 341 + addObject(NID_id_cmc_responseInfo, SN_id_cmc_responseInfo, null, OBJ_id_cmc_responseInfo); // NID: 342 + addObject(NID_id_cmc_queryPending, SN_id_cmc_queryPending, null, OBJ_id_cmc_queryPending); // NID: 343 + addObject(NID_id_cmc_popLinkRandom, SN_id_cmc_popLinkRandom, null, OBJ_id_cmc_popLinkRandom); // NID: 344 + addObject(NID_id_cmc_popLinkWitness, SN_id_cmc_popLinkWitness, null, OBJ_id_cmc_popLinkWitness); // NID: 345 + addObject(NID_id_cmc_confirmCertAcceptance, SN_id_cmc_confirmCertAcceptance, null, OBJ_id_cmc_confirmCertAcceptance); // NID: 346 + addObject(NID_id_on_personalData, SN_id_on_personalData, null, OBJ_id_on_personalData); // NID: 347 + addObject(NID_id_pda_dateOfBirth, SN_id_pda_dateOfBirth, null, OBJ_id_pda_dateOfBirth); // NID: 348 + addObject(NID_id_pda_placeOfBirth, SN_id_pda_placeOfBirth, null, OBJ_id_pda_placeOfBirth); // NID: 349 + addObject(NID_id_pda_gender, SN_id_pda_gender, null, OBJ_id_pda_gender); // NID: 351 + addObject(NID_id_pda_countryOfCitizenship, SN_id_pda_countryOfCitizenship, null, OBJ_id_pda_countryOfCitizenship); // NID: 352 + addObject(NID_id_pda_countryOfResidence, SN_id_pda_countryOfResidence, null, OBJ_id_pda_countryOfResidence); // NID: 353 + addObject(NID_id_aca_authenticationInfo, SN_id_aca_authenticationInfo, null, OBJ_id_aca_authenticationInfo); // NID: 354 + addObject(NID_id_aca_accessIdentity, SN_id_aca_accessIdentity, null, OBJ_id_aca_accessIdentity); // NID: 355 + addObject(NID_id_aca_chargingIdentity, SN_id_aca_chargingIdentity, null, OBJ_id_aca_chargingIdentity); // NID: 356 + addObject(NID_id_aca_group, SN_id_aca_group, null, OBJ_id_aca_group); // NID: 357 + addObject(NID_id_aca_role, SN_id_aca_role, null, OBJ_id_aca_role); // NID: 358 + addObject(NID_id_qcs_pkixQCSyntax_v1, SN_id_qcs_pkixQCSyntax_v1, null, OBJ_id_qcs_pkixQCSyntax_v1); // NID: 359 + addObject(NID_id_cct_crs, SN_id_cct_crs, null, OBJ_id_cct_crs); // NID: 360 + addObject(NID_id_cct_PKIData, SN_id_cct_PKIData, null, OBJ_id_cct_PKIData); // NID: 361 + addObject(NID_id_cct_PKIResponse, SN_id_cct_PKIResponse, null, OBJ_id_cct_PKIResponse); // NID: 362 + addObject(NID_ad_timeStamping, SN_ad_timeStamping, LN_ad_timeStamping, OBJ_ad_timeStamping); // NID: 363 + addObject(NID_ad_dvcs, SN_ad_dvcs, LN_ad_dvcs, OBJ_ad_dvcs); // NID: 364 + addObject(NID_id_pkix_OCSP_basic, SN_id_pkix_OCSP_basic, LN_id_pkix_OCSP_basic, OBJ_id_pkix_OCSP_basic); // NID: 365 + addObject(NID_id_pkix_OCSP_Nonce, SN_id_pkix_OCSP_Nonce, LN_id_pkix_OCSP_Nonce, OBJ_id_pkix_OCSP_Nonce); // NID: 366 + addObject(NID_id_pkix_OCSP_CrlID, SN_id_pkix_OCSP_CrlID, LN_id_pkix_OCSP_CrlID, OBJ_id_pkix_OCSP_CrlID); // NID: 367 + addObject(NID_id_pkix_OCSP_acceptableResponses, SN_id_pkix_OCSP_acceptableResponses, LN_id_pkix_OCSP_acceptableResponses, OBJ_id_pkix_OCSP_acceptableResponses); // NID: 368 + addObject(NID_id_pkix_OCSP_noCheck, SN_id_pkix_OCSP_noCheck, LN_id_pkix_OCSP_noCheck, OBJ_id_pkix_OCSP_noCheck); // NID: 369 + addObject(NID_id_pkix_OCSP_archiveCutoff, SN_id_pkix_OCSP_archiveCutoff, LN_id_pkix_OCSP_archiveCutoff, OBJ_id_pkix_OCSP_archiveCutoff); // NID: 370 + addObject(NID_id_pkix_OCSP_serviceLocator, SN_id_pkix_OCSP_serviceLocator, LN_id_pkix_OCSP_serviceLocator, OBJ_id_pkix_OCSP_serviceLocator); // NID: 371 + addObject(NID_id_pkix_OCSP_extendedStatus, SN_id_pkix_OCSP_extendedStatus, LN_id_pkix_OCSP_extendedStatus, OBJ_id_pkix_OCSP_extendedStatus); // NID: 372 + addObject(NID_id_pkix_OCSP_valid, SN_id_pkix_OCSP_valid, null, OBJ_id_pkix_OCSP_valid); // NID: 373 + addObject(NID_id_pkix_OCSP_path, SN_id_pkix_OCSP_path, null, OBJ_id_pkix_OCSP_path); // NID: 374 + addObject(NID_id_pkix_OCSP_trustRoot, SN_id_pkix_OCSP_trustRoot, LN_id_pkix_OCSP_trustRoot, OBJ_id_pkix_OCSP_trustRoot); // NID: 375 + addObject(NID_algorithm, SN_algorithm, LN_algorithm, OBJ_algorithm); // NID: 376 + addObject(NID_rsaSignature, SN_rsaSignature, null, OBJ_rsaSignature); // NID: 377 + addObject(NID_X500algorithms, SN_X500algorithms, LN_X500algorithms, OBJ_X500algorithms); // NID: 378 + addObject(NID_org, SN_org, LN_org, OBJ_org); // NID: 379 + addObject(NID_dod, SN_dod, LN_dod, OBJ_dod); // NID: 380 + addObject(NID_iana, SN_iana, LN_iana, OBJ_iana); // NID: 381 + addObject(NID_Directory, SN_Directory, LN_Directory, OBJ_Directory); // NID: 382 + addObject(NID_Management, SN_Management, LN_Management, OBJ_Management); // NID: 383 + addObject(NID_Experimental, SN_Experimental, LN_Experimental, OBJ_Experimental); // NID: 384 + addObject(NID_Private, SN_Private, LN_Private, OBJ_Private); // NID: 385 + addObject(NID_Security, SN_Security, LN_Security, OBJ_Security); // NID: 386 + addObject(NID_SNMPv2, SN_SNMPv2, LN_SNMPv2, OBJ_SNMPv2); // NID: 387 + addObject(NID_Mail, null, LN_Mail, OBJ_Mail); // NID: 388 + addObject(NID_Enterprises, SN_Enterprises, LN_Enterprises, OBJ_Enterprises); // NID: 389 + addObject(NID_dcObject, SN_dcObject, LN_dcObject, OBJ_dcObject); // NID: 390 + addObject(NID_domainComponent, SN_domainComponent, LN_domainComponent, OBJ_domainComponent); // NID: 391 + addObject(NID_Domain, SN_Domain, LN_Domain, OBJ_Domain); // NID: 392 + addObject(NID_joint_iso_ccitt, null, null, OBJ_joint_iso_ccitt); // NID: 393 + addObject(NID_selected_attribute_types, SN_selected_attribute_types, LN_selected_attribute_types, OBJ_selected_attribute_types); // NID: 394 + addObject(NID_clearance, SN_clearance, null, OBJ_clearance); // NID: 395 + addObject(NID_md4WithRSAEncryption, SN_md4WithRSAEncryption, LN_md4WithRSAEncryption, OBJ_md4WithRSAEncryption); // NID: 396 + addObject(NID_ac_proxying, SN_ac_proxying, null, OBJ_ac_proxying); // NID: 397 + addObject(NID_sinfo_access, SN_sinfo_access, LN_sinfo_access, OBJ_sinfo_access); // NID: 398 + addObject(NID_id_aca_encAttrs, SN_id_aca_encAttrs, null, OBJ_id_aca_encAttrs); // NID: 399 + addObject(NID_role, SN_role, LN_role, OBJ_role); // NID: 400 + addObject(NID_policy_constraints, SN_policy_constraints, LN_policy_constraints, OBJ_policy_constraints); // NID: 401 + addObject(NID_target_information, SN_target_information, LN_target_information, OBJ_target_information); // NID: 402 + addObject(NID_no_rev_avail, SN_no_rev_avail, LN_no_rev_avail, OBJ_no_rev_avail); // NID: 403 + addObject(NID_ccitt, null, null, OBJ_ccitt); // NID: 404 + addObject(NID_ansi_X9_62, SN_ansi_X9_62, LN_ansi_X9_62, OBJ_ansi_X9_62); // NID: 405 + addObject(NID_X9_62_prime_field, SN_X9_62_prime_field, null, OBJ_X9_62_prime_field); // NID: 406 + addObject(NID_X9_62_characteristic_two_field, SN_X9_62_characteristic_two_field, null, OBJ_X9_62_characteristic_two_field); // NID: 407 + addObject(NID_X9_62_id_ecPublicKey, SN_X9_62_id_ecPublicKey, null, OBJ_X9_62_id_ecPublicKey); // NID: 408 + addObject(NID_X9_62_prime192v1, SN_X9_62_prime192v1, null, OBJ_X9_62_prime192v1); // NID: 409 + addObject(NID_X9_62_prime192v2, SN_X9_62_prime192v2, null, OBJ_X9_62_prime192v2); // NID: 410 + addObject(NID_X9_62_prime192v3, SN_X9_62_prime192v3, null, OBJ_X9_62_prime192v3); // NID: 411 + addObject(NID_X9_62_prime239v1, SN_X9_62_prime239v1, null, OBJ_X9_62_prime239v1); // NID: 412 + addObject(NID_X9_62_prime239v2, SN_X9_62_prime239v2, null, OBJ_X9_62_prime239v2); // NID: 413 + addObject(NID_X9_62_prime239v3, SN_X9_62_prime239v3, null, OBJ_X9_62_prime239v3); // NID: 414 + addObject(NID_X9_62_prime256v1, SN_X9_62_prime256v1, null, OBJ_X9_62_prime256v1); // NID: 415 + addObject(NID_ecdsa_with_SHA1, SN_ecdsa_with_SHA1, null, OBJ_ecdsa_with_SHA1); // NID: 416 + addObject(NID_ms_csp_name, SN_ms_csp_name, LN_ms_csp_name, OBJ_ms_csp_name); // NID: 417 + addObject(NID_aes_128_ecb, SN_aes_128_ecb, LN_aes_128_ecb, OBJ_aes_128_ecb); // NID: 418 + addObject(NID_aes_128_cbc, SN_aes_128_cbc, LN_aes_128_cbc, OBJ_aes_128_cbc); // NID: 419 + addObject(NID_aes_128_ofb128, SN_aes_128_ofb128, LN_aes_128_ofb128, OBJ_aes_128_ofb128); // NID: 420 + addObject(NID_aes_128_cfb128, SN_aes_128_cfb128, LN_aes_128_cfb128, OBJ_aes_128_cfb128); // NID: 421 + addObject(NID_aes_192_ecb, SN_aes_192_ecb, LN_aes_192_ecb, OBJ_aes_192_ecb); // NID: 422 + addObject(NID_aes_192_cbc, SN_aes_192_cbc, LN_aes_192_cbc, OBJ_aes_192_cbc); // NID: 423 + addObject(NID_aes_192_ofb128, SN_aes_192_ofb128, LN_aes_192_ofb128, OBJ_aes_192_ofb128); // NID: 424 + addObject(NID_aes_192_cfb128, SN_aes_192_cfb128, LN_aes_192_cfb128, OBJ_aes_192_cfb128); // NID: 425 + addObject(NID_aes_256_ecb, SN_aes_256_ecb, LN_aes_256_ecb, OBJ_aes_256_ecb); // NID: 426 + addObject(NID_aes_256_cbc, SN_aes_256_cbc, LN_aes_256_cbc, OBJ_aes_256_cbc); // NID: 427 + addObject(NID_aes_256_ofb128, SN_aes_256_ofb128, LN_aes_256_ofb128, OBJ_aes_256_ofb128); // NID: 428 + addObject(NID_aes_256_cfb128, SN_aes_256_cfb128, LN_aes_256_cfb128, OBJ_aes_256_cfb128); // NID: 429 + addObject(NID_hold_instruction_code, SN_hold_instruction_code, LN_hold_instruction_code, OBJ_hold_instruction_code); // NID: 430 + addObject(NID_hold_instruction_none, SN_hold_instruction_none, LN_hold_instruction_none, OBJ_hold_instruction_none); // NID: 431 + addObject(NID_hold_instruction_call_issuer, SN_hold_instruction_call_issuer, LN_hold_instruction_call_issuer, OBJ_hold_instruction_call_issuer); // NID: 432 + addObject(NID_hold_instruction_reject, SN_hold_instruction_reject, LN_hold_instruction_reject, OBJ_hold_instruction_reject); // NID: 433 + addObject(NID_data, SN_data, null, OBJ_data); // NID: 434 + addObject(NID_pss, SN_pss, null, OBJ_pss); // NID: 435 + addObject(NID_ucl, SN_ucl, null, OBJ_ucl); // NID: 436 + addObject(NID_pilot, SN_pilot, null, OBJ_pilot); // NID: 437 + addObject(NID_pilotAttributeType, null, LN_pilotAttributeType, OBJ_pilotAttributeType); // NID: 438 + addObject(NID_pilotAttributeSyntax, null, LN_pilotAttributeSyntax, OBJ_pilotAttributeSyntax); // NID: 439 + addObject(NID_pilotObjectClass, null, LN_pilotObjectClass, OBJ_pilotObjectClass); // NID: 440 + addObject(NID_pilotGroups, null, LN_pilotGroups, OBJ_pilotGroups); // NID: 441 + addObject(NID_iA5StringSyntax, null, LN_iA5StringSyntax, OBJ_iA5StringSyntax); // NID: 442 + addObject(NID_caseIgnoreIA5StringSyntax, null, LN_caseIgnoreIA5StringSyntax, OBJ_caseIgnoreIA5StringSyntax); // NID: 443 + addObject(NID_pilotObject, null, LN_pilotObject, OBJ_pilotObject); // NID: 444 + addObject(NID_pilotPerson, null, LN_pilotPerson, OBJ_pilotPerson); // NID: 445 + addObject(NID_account, SN_account, null, OBJ_account); // NID: 446 + addObject(NID_document, SN_document, null, OBJ_document); // NID: 447 + addObject(NID_room, SN_room, null, OBJ_room); // NID: 448 + addObject(NID_documentSeries, null, LN_documentSeries, OBJ_documentSeries); // NID: 449 + addObject(NID_rFC822localPart, null, LN_rFC822localPart, OBJ_rFC822localPart); // NID: 450 + addObject(NID_dNSDomain, null, LN_dNSDomain, OBJ_dNSDomain); // NID: 451 + addObject(NID_domainRelatedObject, null, LN_domainRelatedObject, OBJ_domainRelatedObject); // NID: 452 + addObject(NID_friendlyCountry, null, LN_friendlyCountry, OBJ_friendlyCountry); // NID: 453 + addObject(NID_simpleSecurityObject, null, LN_simpleSecurityObject, OBJ_simpleSecurityObject); // NID: 454 + addObject(NID_pilotOrganization, null, LN_pilotOrganization, OBJ_pilotOrganization); // NID: 455 + addObject(NID_pilotDSA, null, LN_pilotDSA, OBJ_pilotDSA); // NID: 456 + addObject(NID_qualityLabelledData, null, LN_qualityLabelledData, OBJ_qualityLabelledData); // NID: 457 + addObject(NID_userId, SN_userId, LN_userId, OBJ_userId); // NID: 458 + addObject(NID_textEncodedORAddress, null, LN_textEncodedORAddress, OBJ_textEncodedORAddress); // NID: 459 + addObject(NID_rfc822Mailbox, SN_rfc822Mailbox, LN_rfc822Mailbox, OBJ_rfc822Mailbox); // NID: 460 + addObject(NID_info, SN_info, null, OBJ_info); // NID: 461 + addObject(NID_favouriteDrink, null, LN_favouriteDrink, OBJ_favouriteDrink); // NID: 462 + addObject(NID_roomNumber, null, LN_roomNumber, OBJ_roomNumber); // NID: 463 + addObject(NID_photo, SN_photo, null, OBJ_photo); // NID: 464 + addObject(NID_userClass, null, LN_userClass, OBJ_userClass); // NID: 465 + addObject(NID_host, SN_host, null, OBJ_host); // NID: 466 + addObject(NID_manager, SN_manager, null, OBJ_manager); // NID: 467 + addObject(NID_documentIdentifier, null, LN_documentIdentifier, OBJ_documentIdentifier); // NID: 468 + addObject(NID_documentTitle, null, LN_documentTitle, OBJ_documentTitle); // NID: 469 + addObject(NID_documentVersion, null, LN_documentVersion, OBJ_documentVersion); // NID: 470 + addObject(NID_documentAuthor, null, LN_documentAuthor, OBJ_documentAuthor); // NID: 471 + addObject(NID_documentLocation, null, LN_documentLocation, OBJ_documentLocation); // NID: 472 + addObject(NID_homeTelephoneNumber, null, LN_homeTelephoneNumber, OBJ_homeTelephoneNumber); // NID: 473 + addObject(NID_secretary, SN_secretary, null, OBJ_secretary); // NID: 474 + addObject(NID_otherMailbox, null, LN_otherMailbox, OBJ_otherMailbox); // NID: 475 + addObject(NID_lastModifiedTime, null, LN_lastModifiedTime, OBJ_lastModifiedTime); // NID: 476 + addObject(NID_lastModifiedBy, null, LN_lastModifiedBy, OBJ_lastModifiedBy); // NID: 477 + addObject(NID_aRecord, null, LN_aRecord, OBJ_aRecord); // NID: 478 + addObject(NID_pilotAttributeType27, null, LN_pilotAttributeType27, OBJ_pilotAttributeType27); // NID: 479 + addObject(NID_mXRecord, null, LN_mXRecord, OBJ_mXRecord); // NID: 480 + addObject(NID_nSRecord, null, LN_nSRecord, OBJ_nSRecord); // NID: 481 + addObject(NID_sOARecord, null, LN_sOARecord, OBJ_sOARecord); // NID: 482 + addObject(NID_cNAMERecord, null, LN_cNAMERecord, OBJ_cNAMERecord); // NID: 483 + addObject(NID_associatedDomain, null, LN_associatedDomain, OBJ_associatedDomain); // NID: 484 + addObject(NID_associatedName, null, LN_associatedName, OBJ_associatedName); // NID: 485 + addObject(NID_homePostalAddress, null, LN_homePostalAddress, OBJ_homePostalAddress); // NID: 486 + addObject(NID_personalTitle, null, LN_personalTitle, OBJ_personalTitle); // NID: 487 + addObject(NID_mobileTelephoneNumber, null, LN_mobileTelephoneNumber, OBJ_mobileTelephoneNumber); // NID: 488 + addObject(NID_pagerTelephoneNumber, null, LN_pagerTelephoneNumber, OBJ_pagerTelephoneNumber); // NID: 489 + addObject(NID_friendlyCountryName, null, LN_friendlyCountryName, OBJ_friendlyCountryName); // NID: 490 + addObject(NID_organizationalStatus, null, LN_organizationalStatus, OBJ_organizationalStatus); // NID: 491 + addObject(NID_janetMailbox, null, LN_janetMailbox, OBJ_janetMailbox); // NID: 492 + addObject(NID_mailPreferenceOption, null, LN_mailPreferenceOption, OBJ_mailPreferenceOption); // NID: 493 + addObject(NID_buildingName, null, LN_buildingName, OBJ_buildingName); // NID: 494 + addObject(NID_dSAQuality, null, LN_dSAQuality, OBJ_dSAQuality); // NID: 495 + addObject(NID_singleLevelQuality, null, LN_singleLevelQuality, OBJ_singleLevelQuality); // NID: 496 + addObject(NID_subtreeMinimumQuality, null, LN_subtreeMinimumQuality, OBJ_subtreeMinimumQuality); // NID: 497 + addObject(NID_subtreeMaximumQuality, null, LN_subtreeMaximumQuality, OBJ_subtreeMaximumQuality); // NID: 498 + addObject(NID_personalSignature, null, LN_personalSignature, OBJ_personalSignature); // NID: 499 + addObject(NID_dITRedirect, null, LN_dITRedirect, OBJ_dITRedirect); // NID: 500 + addObject(NID_audio, SN_audio, null, OBJ_audio); // NID: 501 + addObject(NID_documentPublisher, null, LN_documentPublisher, OBJ_documentPublisher); // NID: 502 + addObject(NID_x500UniqueIdentifier, null, LN_x500UniqueIdentifier, OBJ_x500UniqueIdentifier); // NID: 503 + addObject(NID_mime_mhs, SN_mime_mhs, LN_mime_mhs, OBJ_mime_mhs); // NID: 504 + addObject(NID_mime_mhs_headings, SN_mime_mhs_headings, LN_mime_mhs_headings, OBJ_mime_mhs_headings); // NID: 505 + addObject(NID_mime_mhs_bodies, SN_mime_mhs_bodies, LN_mime_mhs_bodies, OBJ_mime_mhs_bodies); // NID: 506 + addObject(NID_id_hex_partial_message, SN_id_hex_partial_message, LN_id_hex_partial_message, OBJ_id_hex_partial_message); // NID: 507 + addObject(NID_id_hex_multipart_message, SN_id_hex_multipart_message, LN_id_hex_multipart_message, OBJ_id_hex_multipart_message); // NID: 508 + addObject(NID_generationQualifier, null, LN_generationQualifier, OBJ_generationQualifier); // NID: 509 + addObject(NID_pseudonym, null, LN_pseudonym, OBJ_pseudonym); // NID: 510 + addObject(NID_id_set, SN_id_set, LN_id_set, OBJ_id_set); // NID: 512 + addObject(NID_set_ctype, SN_set_ctype, LN_set_ctype, OBJ_set_ctype); // NID: 513 + addObject(NID_set_msgExt, SN_set_msgExt, LN_set_msgExt, OBJ_set_msgExt); // NID: 514 + addObject(NID_set_attr, SN_set_attr, null, OBJ_set_attr); // NID: 515 + addObject(NID_set_policy, SN_set_policy, null, OBJ_set_policy); // NID: 516 + addObject(NID_set_certExt, SN_set_certExt, LN_set_certExt, OBJ_set_certExt); // NID: 517 + addObject(NID_set_brand, SN_set_brand, null, OBJ_set_brand); // NID: 518 + addObject(NID_setct_PANData, SN_setct_PANData, null, OBJ_setct_PANData); // NID: 519 + addObject(NID_setct_PANToken, SN_setct_PANToken, null, OBJ_setct_PANToken); // NID: 520 + addObject(NID_setct_PANOnly, SN_setct_PANOnly, null, OBJ_setct_PANOnly); // NID: 521 + addObject(NID_setct_OIData, SN_setct_OIData, null, OBJ_setct_OIData); // NID: 522 + addObject(NID_setct_PI, SN_setct_PI, null, OBJ_setct_PI); // NID: 523 + addObject(NID_setct_PIData, SN_setct_PIData, null, OBJ_setct_PIData); // NID: 524 + addObject(NID_setct_PIDataUnsigned, SN_setct_PIDataUnsigned, null, OBJ_setct_PIDataUnsigned); // NID: 525 + addObject(NID_setct_HODInput, SN_setct_HODInput, null, OBJ_setct_HODInput); // NID: 526 + addObject(NID_setct_AuthResBaggage, SN_setct_AuthResBaggage, null, OBJ_setct_AuthResBaggage); // NID: 527 + addObject(NID_setct_AuthRevReqBaggage, SN_setct_AuthRevReqBaggage, null, OBJ_setct_AuthRevReqBaggage); // NID: 528 + addObject(NID_setct_AuthRevResBaggage, SN_setct_AuthRevResBaggage, null, OBJ_setct_AuthRevResBaggage); // NID: 529 + addObject(NID_setct_CapTokenSeq, SN_setct_CapTokenSeq, null, OBJ_setct_CapTokenSeq); // NID: 530 + addObject(NID_setct_PInitResData, SN_setct_PInitResData, null, OBJ_setct_PInitResData); // NID: 531 + addObject(NID_setct_PI_TBS, SN_setct_PI_TBS, null, OBJ_setct_PI_TBS); // NID: 532 + addObject(NID_setct_PResData, SN_setct_PResData, null, OBJ_setct_PResData); // NID: 533 + addObject(NID_setct_AuthReqTBS, SN_setct_AuthReqTBS, null, OBJ_setct_AuthReqTBS); // NID: 534 + addObject(NID_setct_AuthResTBS, SN_setct_AuthResTBS, null, OBJ_setct_AuthResTBS); // NID: 535 + addObject(NID_setct_AuthResTBSX, SN_setct_AuthResTBSX, null, OBJ_setct_AuthResTBSX); // NID: 536 + addObject(NID_setct_AuthTokenTBS, SN_setct_AuthTokenTBS, null, OBJ_setct_AuthTokenTBS); // NID: 537 + addObject(NID_setct_CapTokenData, SN_setct_CapTokenData, null, OBJ_setct_CapTokenData); // NID: 538 + addObject(NID_setct_CapTokenTBS, SN_setct_CapTokenTBS, null, OBJ_setct_CapTokenTBS); // NID: 539 + addObject(NID_setct_AcqCardCodeMsg, SN_setct_AcqCardCodeMsg, null, OBJ_setct_AcqCardCodeMsg); // NID: 540 + addObject(NID_setct_AuthRevReqTBS, SN_setct_AuthRevReqTBS, null, OBJ_setct_AuthRevReqTBS); // NID: 541 + addObject(NID_setct_AuthRevResData, SN_setct_AuthRevResData, null, OBJ_setct_AuthRevResData); // NID: 542 + addObject(NID_setct_AuthRevResTBS, SN_setct_AuthRevResTBS, null, OBJ_setct_AuthRevResTBS); // NID: 543 + addObject(NID_setct_CapReqTBS, SN_setct_CapReqTBS, null, OBJ_setct_CapReqTBS); // NID: 544 + addObject(NID_setct_CapReqTBSX, SN_setct_CapReqTBSX, null, OBJ_setct_CapReqTBSX); // NID: 545 + addObject(NID_setct_CapResData, SN_setct_CapResData, null, OBJ_setct_CapResData); // NID: 546 + addObject(NID_setct_CapRevReqTBS, SN_setct_CapRevReqTBS, null, OBJ_setct_CapRevReqTBS); // NID: 547 + addObject(NID_setct_CapRevReqTBSX, SN_setct_CapRevReqTBSX, null, OBJ_setct_CapRevReqTBSX); // NID: 548 + addObject(NID_setct_CapRevResData, SN_setct_CapRevResData, null, OBJ_setct_CapRevResData); // NID: 549 + addObject(NID_setct_CredReqTBS, SN_setct_CredReqTBS, null, OBJ_setct_CredReqTBS); // NID: 550 + addObject(NID_setct_CredReqTBSX, SN_setct_CredReqTBSX, null, OBJ_setct_CredReqTBSX); // NID: 551 + addObject(NID_setct_CredResData, SN_setct_CredResData, null, OBJ_setct_CredResData); // NID: 552 + addObject(NID_setct_CredRevReqTBS, SN_setct_CredRevReqTBS, null, OBJ_setct_CredRevReqTBS); // NID: 553 + addObject(NID_setct_CredRevReqTBSX, SN_setct_CredRevReqTBSX, null, OBJ_setct_CredRevReqTBSX); // NID: 554 + addObject(NID_setct_CredRevResData, SN_setct_CredRevResData, null, OBJ_setct_CredRevResData); // NID: 555 + addObject(NID_setct_PCertReqData, SN_setct_PCertReqData, null, OBJ_setct_PCertReqData); // NID: 556 + addObject(NID_setct_PCertResTBS, SN_setct_PCertResTBS, null, OBJ_setct_PCertResTBS); // NID: 557 + addObject(NID_setct_BatchAdminReqData, SN_setct_BatchAdminReqData, null, OBJ_setct_BatchAdminReqData); // NID: 558 + addObject(NID_setct_BatchAdminResData, SN_setct_BatchAdminResData, null, OBJ_setct_BatchAdminResData); // NID: 559 + addObject(NID_setct_CardCInitResTBS, SN_setct_CardCInitResTBS, null, OBJ_setct_CardCInitResTBS); // NID: 560 + addObject(NID_setct_MeAqCInitResTBS, SN_setct_MeAqCInitResTBS, null, OBJ_setct_MeAqCInitResTBS); // NID: 561 + addObject(NID_setct_RegFormResTBS, SN_setct_RegFormResTBS, null, OBJ_setct_RegFormResTBS); // NID: 562 + addObject(NID_setct_CertReqData, SN_setct_CertReqData, null, OBJ_setct_CertReqData); // NID: 563 + addObject(NID_setct_CertReqTBS, SN_setct_CertReqTBS, null, OBJ_setct_CertReqTBS); // NID: 564 + addObject(NID_setct_CertResData, SN_setct_CertResData, null, OBJ_setct_CertResData); // NID: 565 + addObject(NID_setct_CertInqReqTBS, SN_setct_CertInqReqTBS, null, OBJ_setct_CertInqReqTBS); // NID: 566 + addObject(NID_setct_ErrorTBS, SN_setct_ErrorTBS, null, OBJ_setct_ErrorTBS); // NID: 567 + addObject(NID_setct_PIDualSignedTBE, SN_setct_PIDualSignedTBE, null, OBJ_setct_PIDualSignedTBE); // NID: 568 + addObject(NID_setct_PIUnsignedTBE, SN_setct_PIUnsignedTBE, null, OBJ_setct_PIUnsignedTBE); // NID: 569 + addObject(NID_setct_AuthReqTBE, SN_setct_AuthReqTBE, null, OBJ_setct_AuthReqTBE); // NID: 570 + addObject(NID_setct_AuthResTBE, SN_setct_AuthResTBE, null, OBJ_setct_AuthResTBE); // NID: 571 + addObject(NID_setct_AuthResTBEX, SN_setct_AuthResTBEX, null, OBJ_setct_AuthResTBEX); // NID: 572 + addObject(NID_setct_AuthTokenTBE, SN_setct_AuthTokenTBE, null, OBJ_setct_AuthTokenTBE); // NID: 573 + addObject(NID_setct_CapTokenTBE, SN_setct_CapTokenTBE, null, OBJ_setct_CapTokenTBE); // NID: 574 + addObject(NID_setct_CapTokenTBEX, SN_setct_CapTokenTBEX, null, OBJ_setct_CapTokenTBEX); // NID: 575 + addObject(NID_setct_AcqCardCodeMsgTBE, SN_setct_AcqCardCodeMsgTBE, null, OBJ_setct_AcqCardCodeMsgTBE); // NID: 576 + addObject(NID_setct_AuthRevReqTBE, SN_setct_AuthRevReqTBE, null, OBJ_setct_AuthRevReqTBE); // NID: 577 + addObject(NID_setct_AuthRevResTBE, SN_setct_AuthRevResTBE, null, OBJ_setct_AuthRevResTBE); // NID: 578 + addObject(NID_setct_AuthRevResTBEB, SN_setct_AuthRevResTBEB, null, OBJ_setct_AuthRevResTBEB); // NID: 579 + addObject(NID_setct_CapReqTBE, SN_setct_CapReqTBE, null, OBJ_setct_CapReqTBE); // NID: 580 + addObject(NID_setct_CapReqTBEX, SN_setct_CapReqTBEX, null, OBJ_setct_CapReqTBEX); // NID: 581 + addObject(NID_setct_CapResTBE, SN_setct_CapResTBE, null, OBJ_setct_CapResTBE); // NID: 582 + addObject(NID_setct_CapRevReqTBE, SN_setct_CapRevReqTBE, null, OBJ_setct_CapRevReqTBE); // NID: 583 + addObject(NID_setct_CapRevReqTBEX, SN_setct_CapRevReqTBEX, null, OBJ_setct_CapRevReqTBEX); // NID: 584 + addObject(NID_setct_CapRevResTBE, SN_setct_CapRevResTBE, null, OBJ_setct_CapRevResTBE); // NID: 585 + addObject(NID_setct_CredReqTBE, SN_setct_CredReqTBE, null, OBJ_setct_CredReqTBE); // NID: 586 + addObject(NID_setct_CredReqTBEX, SN_setct_CredReqTBEX, null, OBJ_setct_CredReqTBEX); // NID: 587 + addObject(NID_setct_CredResTBE, SN_setct_CredResTBE, null, OBJ_setct_CredResTBE); // NID: 588 + addObject(NID_setct_CredRevReqTBE, SN_setct_CredRevReqTBE, null, OBJ_setct_CredRevReqTBE); // NID: 589 + addObject(NID_setct_CredRevReqTBEX, SN_setct_CredRevReqTBEX, null, OBJ_setct_CredRevReqTBEX); // NID: 590 + addObject(NID_setct_CredRevResTBE, SN_setct_CredRevResTBE, null, OBJ_setct_CredRevResTBE); // NID: 591 + addObject(NID_setct_BatchAdminReqTBE, SN_setct_BatchAdminReqTBE, null, OBJ_setct_BatchAdminReqTBE); // NID: 592 + addObject(NID_setct_BatchAdminResTBE, SN_setct_BatchAdminResTBE, null, OBJ_setct_BatchAdminResTBE); // NID: 593 + addObject(NID_setct_RegFormReqTBE, SN_setct_RegFormReqTBE, null, OBJ_setct_RegFormReqTBE); // NID: 594 + addObject(NID_setct_CertReqTBE, SN_setct_CertReqTBE, null, OBJ_setct_CertReqTBE); // NID: 595 + addObject(NID_setct_CertReqTBEX, SN_setct_CertReqTBEX, null, OBJ_setct_CertReqTBEX); // NID: 596 + addObject(NID_setct_CertResTBE, SN_setct_CertResTBE, null, OBJ_setct_CertResTBE); // NID: 597 + addObject(NID_setct_CRLNotificationTBS, SN_setct_CRLNotificationTBS, null, OBJ_setct_CRLNotificationTBS); // NID: 598 + addObject(NID_setct_CRLNotificationResTBS, SN_setct_CRLNotificationResTBS, null, OBJ_setct_CRLNotificationResTBS); // NID: 599 + addObject(NID_setct_BCIDistributionTBS, SN_setct_BCIDistributionTBS, null, OBJ_setct_BCIDistributionTBS); // NID: 600 + addObject(NID_setext_genCrypt, SN_setext_genCrypt, LN_setext_genCrypt, OBJ_setext_genCrypt); // NID: 601 + addObject(NID_setext_miAuth, SN_setext_miAuth, LN_setext_miAuth, OBJ_setext_miAuth); // NID: 602 + addObject(NID_setext_pinSecure, SN_setext_pinSecure, null, OBJ_setext_pinSecure); // NID: 603 + addObject(NID_setext_pinAny, SN_setext_pinAny, null, OBJ_setext_pinAny); // NID: 604 + addObject(NID_setext_track2, SN_setext_track2, null, OBJ_setext_track2); // NID: 605 + addObject(NID_setext_cv, SN_setext_cv, LN_setext_cv, OBJ_setext_cv); // NID: 606 + addObject(NID_set_policy_root, SN_set_policy_root, null, OBJ_set_policy_root); // NID: 607 + addObject(NID_setCext_hashedRoot, SN_setCext_hashedRoot, null, OBJ_setCext_hashedRoot); // NID: 608 + addObject(NID_setCext_certType, SN_setCext_certType, null, OBJ_setCext_certType); // NID: 609 + addObject(NID_setCext_merchData, SN_setCext_merchData, null, OBJ_setCext_merchData); // NID: 610 + addObject(NID_setCext_cCertRequired, SN_setCext_cCertRequired, null, OBJ_setCext_cCertRequired); // NID: 611 + addObject(NID_setCext_tunneling, SN_setCext_tunneling, null, OBJ_setCext_tunneling); // NID: 612 + addObject(NID_setCext_setExt, SN_setCext_setExt, null, OBJ_setCext_setExt); // NID: 613 + addObject(NID_setCext_setQualf, SN_setCext_setQualf, null, OBJ_setCext_setQualf); // NID: 614 + addObject(NID_setCext_PGWYcapabilities, SN_setCext_PGWYcapabilities, null, OBJ_setCext_PGWYcapabilities); // NID: 615 + addObject(NID_setCext_TokenIdentifier, SN_setCext_TokenIdentifier, null, OBJ_setCext_TokenIdentifier); // NID: 616 + addObject(NID_setCext_Track2Data, SN_setCext_Track2Data, null, OBJ_setCext_Track2Data); // NID: 617 + addObject(NID_setCext_TokenType, SN_setCext_TokenType, null, OBJ_setCext_TokenType); // NID: 618 + addObject(NID_setCext_IssuerCapabilities, SN_setCext_IssuerCapabilities, null, OBJ_setCext_IssuerCapabilities); // NID: 619 + addObject(NID_setAttr_Cert, SN_setAttr_Cert, null, OBJ_setAttr_Cert); // NID: 620 + addObject(NID_setAttr_PGWYcap, SN_setAttr_PGWYcap, LN_setAttr_PGWYcap, OBJ_setAttr_PGWYcap); // NID: 621 + addObject(NID_setAttr_TokenType, SN_setAttr_TokenType, null, OBJ_setAttr_TokenType); // NID: 622 + addObject(NID_setAttr_IssCap, SN_setAttr_IssCap, LN_setAttr_IssCap, OBJ_setAttr_IssCap); // NID: 623 + addObject(NID_set_rootKeyThumb, SN_set_rootKeyThumb, null, OBJ_set_rootKeyThumb); // NID: 624 + addObject(NID_set_addPolicy, SN_set_addPolicy, null, OBJ_set_addPolicy); // NID: 625 + addObject(NID_setAttr_Token_EMV, SN_setAttr_Token_EMV, null, OBJ_setAttr_Token_EMV); // NID: 626 + addObject(NID_setAttr_Token_B0Prime, SN_setAttr_Token_B0Prime, null, OBJ_setAttr_Token_B0Prime); // NID: 627 + addObject(NID_setAttr_IssCap_CVM, SN_setAttr_IssCap_CVM, null, OBJ_setAttr_IssCap_CVM); // NID: 628 + addObject(NID_setAttr_IssCap_T2, SN_setAttr_IssCap_T2, null, OBJ_setAttr_IssCap_T2); // NID: 629 + addObject(NID_setAttr_IssCap_Sig, SN_setAttr_IssCap_Sig, null, OBJ_setAttr_IssCap_Sig); // NID: 630 + addObject(NID_setAttr_GenCryptgrm, SN_setAttr_GenCryptgrm, LN_setAttr_GenCryptgrm, OBJ_setAttr_GenCryptgrm); // NID: 631 + addObject(NID_setAttr_T2Enc, SN_setAttr_T2Enc, LN_setAttr_T2Enc, OBJ_setAttr_T2Enc); // NID: 632 + addObject(NID_setAttr_T2cleartxt, SN_setAttr_T2cleartxt, LN_setAttr_T2cleartxt, OBJ_setAttr_T2cleartxt); // NID: 633 + addObject(NID_setAttr_TokICCsig, SN_setAttr_TokICCsig, LN_setAttr_TokICCsig, OBJ_setAttr_TokICCsig); // NID: 634 + addObject(NID_setAttr_SecDevSig, SN_setAttr_SecDevSig, LN_setAttr_SecDevSig, OBJ_setAttr_SecDevSig); // NID: 635 + addObject(NID_set_brand_IATA_ATA, SN_set_brand_IATA_ATA, null, OBJ_set_brand_IATA_ATA); // NID: 636 + addObject(NID_set_brand_Diners, SN_set_brand_Diners, null, OBJ_set_brand_Diners); // NID: 637 + addObject(NID_set_brand_AmericanExpress, SN_set_brand_AmericanExpress, null, OBJ_set_brand_AmericanExpress); // NID: 638 + addObject(NID_set_brand_JCB, SN_set_brand_JCB, null, OBJ_set_brand_JCB); // NID: 639 + addObject(NID_set_brand_Visa, SN_set_brand_Visa, null, OBJ_set_brand_Visa); // NID: 640 + addObject(NID_set_brand_MasterCard, SN_set_brand_MasterCard, null, OBJ_set_brand_MasterCard); // NID: 641 + addObject(NID_set_brand_Novus, SN_set_brand_Novus, null, OBJ_set_brand_Novus); // NID: 642 + addObject(NID_des_cdmf, SN_des_cdmf, LN_des_cdmf, OBJ_des_cdmf); // NID: 643 + addObject(NID_rsaOAEPEncryptionSET, SN_rsaOAEPEncryptionSET, null, OBJ_rsaOAEPEncryptionSET); // NID: 644 + addObject(NID_itu_t, SN_itu_t, LN_itu_t, OBJ_itu_t); // NID: 645 + addObject(NID_joint_iso_itu_t, SN_joint_iso_itu_t, LN_joint_iso_itu_t, OBJ_joint_iso_itu_t); // NID: 646 + addObject(NID_international_organizations, SN_international_organizations, LN_international_organizations, OBJ_international_organizations); // NID: 647 + addObject(NID_ms_smartcard_login, SN_ms_smartcard_login, LN_ms_smartcard_login, OBJ_ms_smartcard_login); // NID: 648 + addObject(NID_ms_upn, SN_ms_upn, LN_ms_upn, OBJ_ms_upn); // NID: 649 + addObject(NID_aes_128_cfb1, SN_aes_128_cfb1, LN_aes_128_cfb1, null); // NID: 650 + addObject(NID_aes_192_cfb1, SN_aes_192_cfb1, LN_aes_192_cfb1, null); // NID: 651 + addObject(NID_aes_256_cfb1, SN_aes_256_cfb1, LN_aes_256_cfb1, null); // NID: 652 + addObject(NID_aes_128_cfb8, SN_aes_128_cfb8, LN_aes_128_cfb8, null); // NID: 653 + addObject(NID_aes_192_cfb8, SN_aes_192_cfb8, LN_aes_192_cfb8, null); // NID: 654 + addObject(NID_aes_256_cfb8, SN_aes_256_cfb8, LN_aes_256_cfb8, null); // NID: 655 + addObject(NID_des_cfb1, SN_des_cfb1, LN_des_cfb1, null); // NID: 656 + addObject(NID_des_cfb8, SN_des_cfb8, LN_des_cfb8, null); // NID: 657 + addObject(NID_des_ede3_cfb1, SN_des_ede3_cfb1, LN_des_ede3_cfb1, null); // NID: 658 + addObject(NID_des_ede3_cfb8, SN_des_ede3_cfb8, LN_des_ede3_cfb8, null); // NID: 659 + addObject(NID_streetAddress, null, LN_streetAddress, OBJ_streetAddress); // NID: 660 + addObject(NID_postalCode, null, LN_postalCode, OBJ_postalCode); // NID: 661 + addObject(NID_id_ppl, SN_id_ppl, null, OBJ_id_ppl); // NID: 662 + addObject(NID_proxyCertInfo, SN_proxyCertInfo, LN_proxyCertInfo, OBJ_proxyCertInfo); // NID: 663 + addObject(NID_id_ppl_anyLanguage, SN_id_ppl_anyLanguage, LN_id_ppl_anyLanguage, OBJ_id_ppl_anyLanguage); // NID: 664 + addObject(NID_id_ppl_inheritAll, SN_id_ppl_inheritAll, LN_id_ppl_inheritAll, OBJ_id_ppl_inheritAll); // NID: 665 + addObject(NID_name_constraints, SN_name_constraints, LN_name_constraints, OBJ_name_constraints); // NID: 666 + addObject(NID_Independent, SN_Independent, LN_Independent, OBJ_Independent); // NID: 667 + addObject(NID_sha256WithRSAEncryption, SN_sha256WithRSAEncryption, LN_sha256WithRSAEncryption, OBJ_sha256WithRSAEncryption); // NID: 668 + addObject(NID_sha384WithRSAEncryption, SN_sha384WithRSAEncryption, LN_sha384WithRSAEncryption, OBJ_sha384WithRSAEncryption); // NID: 669 + addObject(NID_sha512WithRSAEncryption, SN_sha512WithRSAEncryption, LN_sha512WithRSAEncryption, OBJ_sha512WithRSAEncryption); // NID: 670 + addObject(NID_sha224WithRSAEncryption, SN_sha224WithRSAEncryption, LN_sha224WithRSAEncryption, OBJ_sha224WithRSAEncryption); // NID: 671 + addObject(NID_sha256, SN_sha256, LN_sha256, OBJ_sha256); // NID: 672 + addObject(NID_sha384, SN_sha384, LN_sha384, OBJ_sha384); // NID: 673 + addObject(NID_sha512, SN_sha512, LN_sha512, OBJ_sha512); // NID: 674 + addObject(NID_sha224, SN_sha224, LN_sha224, OBJ_sha224); // NID: 675 + addObject(NID_identified_organization, SN_identified_organization, null, OBJ_identified_organization); // NID: 676 + addObject(NID_certicom_arc, SN_certicom_arc, null, OBJ_certicom_arc); // NID: 677 + addObject(NID_wap, SN_wap, null, OBJ_wap); // NID: 678 + addObject(NID_wap_wsg, SN_wap_wsg, null, OBJ_wap_wsg); // NID: 679 + addObject(NID_X9_62_id_characteristic_two_basis, SN_X9_62_id_characteristic_two_basis, null, OBJ_X9_62_id_characteristic_two_basis); // NID: 680 + addObject(NID_X9_62_onBasis, SN_X9_62_onBasis, null, OBJ_X9_62_onBasis); // NID: 681 + addObject(NID_X9_62_tpBasis, SN_X9_62_tpBasis, null, OBJ_X9_62_tpBasis); // NID: 682 + addObject(NID_X9_62_ppBasis, SN_X9_62_ppBasis, null, OBJ_X9_62_ppBasis); // NID: 683 + addObject(NID_X9_62_c2pnb163v1, SN_X9_62_c2pnb163v1, null, OBJ_X9_62_c2pnb163v1); // NID: 684 + addObject(NID_X9_62_c2pnb163v2, SN_X9_62_c2pnb163v2, null, OBJ_X9_62_c2pnb163v2); // NID: 685 + addObject(NID_X9_62_c2pnb163v3, SN_X9_62_c2pnb163v3, null, OBJ_X9_62_c2pnb163v3); // NID: 686 + addObject(NID_X9_62_c2pnb176v1, SN_X9_62_c2pnb176v1, null, OBJ_X9_62_c2pnb176v1); // NID: 687 + addObject(NID_X9_62_c2tnb191v1, SN_X9_62_c2tnb191v1, null, OBJ_X9_62_c2tnb191v1); // NID: 688 + addObject(NID_X9_62_c2tnb191v2, SN_X9_62_c2tnb191v2, null, OBJ_X9_62_c2tnb191v2); // NID: 689 + addObject(NID_X9_62_c2tnb191v3, SN_X9_62_c2tnb191v3, null, OBJ_X9_62_c2tnb191v3); // NID: 690 + addObject(NID_X9_62_c2onb191v4, SN_X9_62_c2onb191v4, null, OBJ_X9_62_c2onb191v4); // NID: 691 + addObject(NID_X9_62_c2onb191v5, SN_X9_62_c2onb191v5, null, OBJ_X9_62_c2onb191v5); // NID: 692 + addObject(NID_X9_62_c2pnb208w1, SN_X9_62_c2pnb208w1, null, OBJ_X9_62_c2pnb208w1); // NID: 693 + addObject(NID_X9_62_c2tnb239v1, SN_X9_62_c2tnb239v1, null, OBJ_X9_62_c2tnb239v1); // NID: 694 + addObject(NID_X9_62_c2tnb239v2, SN_X9_62_c2tnb239v2, null, OBJ_X9_62_c2tnb239v2); // NID: 695 + addObject(NID_X9_62_c2tnb239v3, SN_X9_62_c2tnb239v3, null, OBJ_X9_62_c2tnb239v3); // NID: 696 + addObject(NID_X9_62_c2onb239v4, SN_X9_62_c2onb239v4, null, OBJ_X9_62_c2onb239v4); // NID: 697 + addObject(NID_X9_62_c2onb239v5, SN_X9_62_c2onb239v5, null, OBJ_X9_62_c2onb239v5); // NID: 698 + addObject(NID_X9_62_c2pnb272w1, SN_X9_62_c2pnb272w1, null, OBJ_X9_62_c2pnb272w1); // NID: 699 + addObject(NID_X9_62_c2pnb304w1, SN_X9_62_c2pnb304w1, null, OBJ_X9_62_c2pnb304w1); // NID: 700 + addObject(NID_X9_62_c2tnb359v1, SN_X9_62_c2tnb359v1, null, OBJ_X9_62_c2tnb359v1); // NID: 701 + addObject(NID_X9_62_c2pnb368w1, SN_X9_62_c2pnb368w1, null, OBJ_X9_62_c2pnb368w1); // NID: 702 + addObject(NID_X9_62_c2tnb431r1, SN_X9_62_c2tnb431r1, null, OBJ_X9_62_c2tnb431r1); // NID: 703 + addObject(NID_secp112r1, SN_secp112r1, null, OBJ_secp112r1); // NID: 704 + addObject(NID_secp112r2, SN_secp112r2, null, OBJ_secp112r2); // NID: 705 + addObject(NID_secp128r1, SN_secp128r1, null, OBJ_secp128r1); // NID: 706 + addObject(NID_secp128r2, SN_secp128r2, null, OBJ_secp128r2); // NID: 707 + addObject(NID_secp160k1, SN_secp160k1, null, OBJ_secp160k1); // NID: 708 + addObject(NID_secp160r1, SN_secp160r1, null, OBJ_secp160r1); // NID: 709 + addObject(NID_secp160r2, SN_secp160r2, null, OBJ_secp160r2); // NID: 710 + addObject(NID_secp192k1, SN_secp192k1, null, OBJ_secp192k1); // NID: 711 + addObject(NID_secp224k1, SN_secp224k1, null, OBJ_secp224k1); // NID: 712 + addObject(NID_secp224r1, SN_secp224r1, null, OBJ_secp224r1); // NID: 713 + addObject(NID_secp256k1, SN_secp256k1, null, OBJ_secp256k1); // NID: 714 + addObject(NID_secp384r1, SN_secp384r1, null, OBJ_secp384r1); // NID: 715 + addObject(NID_secp521r1, SN_secp521r1, null, OBJ_secp521r1); // NID: 716 + addObject(NID_sect113r1, SN_sect113r1, null, OBJ_sect113r1); // NID: 717 + addObject(NID_sect113r2, SN_sect113r2, null, OBJ_sect113r2); // NID: 718 + addObject(NID_sect131r1, SN_sect131r1, null, OBJ_sect131r1); // NID: 719 + addObject(NID_sect131r2, SN_sect131r2, null, OBJ_sect131r2); // NID: 720 + addObject(NID_sect163k1, SN_sect163k1, null, OBJ_sect163k1); // NID: 721 + addObject(NID_sect163r1, SN_sect163r1, null, OBJ_sect163r1); // NID: 722 + addObject(NID_sect163r2, SN_sect163r2, null, OBJ_sect163r2); // NID: 723 + addObject(NID_sect193r1, SN_sect193r1, null, OBJ_sect193r1); // NID: 724 + addObject(NID_sect193r2, SN_sect193r2, null, OBJ_sect193r2); // NID: 725 + addObject(NID_sect233k1, SN_sect233k1, null, OBJ_sect233k1); // NID: 726 + addObject(NID_sect233r1, SN_sect233r1, null, OBJ_sect233r1); // NID: 727 + addObject(NID_sect239k1, SN_sect239k1, null, OBJ_sect239k1); // NID: 728 + addObject(NID_sect283k1, SN_sect283k1, null, OBJ_sect283k1); // NID: 729 + addObject(NID_sect283r1, SN_sect283r1, null, OBJ_sect283r1); // NID: 730 + addObject(NID_sect409k1, SN_sect409k1, null, OBJ_sect409k1); // NID: 731 + addObject(NID_sect409r1, SN_sect409r1, null, OBJ_sect409r1); // NID: 732 + addObject(NID_sect571k1, SN_sect571k1, null, OBJ_sect571k1); // NID: 733 + addObject(NID_sect571r1, SN_sect571r1, null, OBJ_sect571r1); // NID: 734 + addObject(NID_wap_wsg_idm_ecid_wtls1, SN_wap_wsg_idm_ecid_wtls1, null, OBJ_wap_wsg_idm_ecid_wtls1); // NID: 735 + addObject(NID_wap_wsg_idm_ecid_wtls3, SN_wap_wsg_idm_ecid_wtls3, null, OBJ_wap_wsg_idm_ecid_wtls3); // NID: 736 + addObject(NID_wap_wsg_idm_ecid_wtls4, SN_wap_wsg_idm_ecid_wtls4, null, OBJ_wap_wsg_idm_ecid_wtls4); // NID: 737 + addObject(NID_wap_wsg_idm_ecid_wtls5, SN_wap_wsg_idm_ecid_wtls5, null, OBJ_wap_wsg_idm_ecid_wtls5); // NID: 738 + addObject(NID_wap_wsg_idm_ecid_wtls6, SN_wap_wsg_idm_ecid_wtls6, null, OBJ_wap_wsg_idm_ecid_wtls6); // NID: 739 + addObject(NID_wap_wsg_idm_ecid_wtls7, SN_wap_wsg_idm_ecid_wtls7, null, OBJ_wap_wsg_idm_ecid_wtls7); // NID: 740 + addObject(NID_wap_wsg_idm_ecid_wtls8, SN_wap_wsg_idm_ecid_wtls8, null, OBJ_wap_wsg_idm_ecid_wtls8); // NID: 741 + addObject(NID_wap_wsg_idm_ecid_wtls9, SN_wap_wsg_idm_ecid_wtls9, null, OBJ_wap_wsg_idm_ecid_wtls9); // NID: 742 + addObject(NID_wap_wsg_idm_ecid_wtls10, SN_wap_wsg_idm_ecid_wtls10, null, OBJ_wap_wsg_idm_ecid_wtls10); // NID: 743 + addObject(NID_wap_wsg_idm_ecid_wtls11, SN_wap_wsg_idm_ecid_wtls11, null, OBJ_wap_wsg_idm_ecid_wtls11); // NID: 744 + addObject(NID_wap_wsg_idm_ecid_wtls12, SN_wap_wsg_idm_ecid_wtls12, null, OBJ_wap_wsg_idm_ecid_wtls12); // NID: 745 + addObject(NID_any_policy, SN_any_policy, LN_any_policy, OBJ_any_policy); // NID: 746 + addObject(NID_policy_mappings, SN_policy_mappings, LN_policy_mappings, OBJ_policy_mappings); // NID: 747 + addObject(NID_inhibit_any_policy, SN_inhibit_any_policy, LN_inhibit_any_policy, OBJ_inhibit_any_policy); // NID: 748 + addObject(NID_ipsec3, SN_ipsec3, LN_ipsec3, null); // NID: 749 + addObject(NID_ipsec4, SN_ipsec4, LN_ipsec4, null); // NID: 750 + addObject(NID_dsa_with_SHA224, SN_dsa_with_SHA224, null, OBJ_dsa_with_SHA224); // NID: 802 + addObject(NID_dsa_with_SHA256, SN_dsa_with_SHA256, null, OBJ_dsa_with_SHA256); // NID: 803 + } + + +// public final static String SN_undef = "UNDEF"; +// public final static String LN_undef = "undefined"; +// public final static int NID_undef = 0; +// public final static String OBJ_undef = "0"; + +// public final static String SN_Algorithm = "Algorithm"; +// public final static String LN_algorithm = "algorithm"; +// public final static int NID_algorithm = 38; +// public final static String OBJ_algorithm = "1.3.14.3.2"; + +// public final static String LN_rsadsi = "rsadsi"; +// public final static int NID_rsadsi = 1; +// public final static String OBJ_rsadsi = "1.2.840.113549"; + +// public final static String LN_pkcs = "pkcs"; +// public final static int NID_pkcs = 2; +// public final static String OBJ_pkcs = OBJ_rsadsi+".1"; + +// public final static String SN_md2 = "MD2"; +// public final static String LN_md2 = "md2"; +// public final static int NID_md2 = 3; +// public final static String OBJ_md2 = OBJ_rsadsi+".2.2"; + +// public final static String SN_md5 = "MD5"; +// public final static String LN_md5 = "md5"; +// public final static int NID_md5 = 4; +// public final static String OBJ_md5 = OBJ_rsadsi+".2.5"; + +// public final static String SN_rc4 = "RC4"; +// public final static String LN_rc4 = "rc4"; +// public final static int NID_rc4 = 5; +// public final static String OBJ_rc4 = OBJ_rsadsi+".3.4"; + +// public final static String LN_rsaEncryption = "rsaEncryption"; +// public final static int NID_rsaEncryption = 6; +// public final static String OBJ_rsaEncryption = OBJ_pkcs+".1.1"; + +// public final static String SN_md2WithRSAEncryption = "RSA-MD2"; +// public final static String LN_md2WithRSAEncryption = "md2WithRSAEncryption"; +// public final static int NID_md2WithRSAEncryption = 7; +// public final static String OBJ_md2WithRSAEncryption = OBJ_pkcs+".1.2"; + +// public final static String SN_md5WithRSAEncryption = "RSA-MD5"; +// public final static String LN_md5WithRSAEncryption = "md5WithRSAEncryption"; +// public final static int NID_md5WithRSAEncryption = 8; +// public final static String OBJ_md5WithRSAEncryption = OBJ_pkcs+".1.4"; + +// public final static String SN_pbeWithMD2AndDES_CBC = "PBE-MD2-DES"; +// public final static String LN_pbeWithMD2AndDES_CBC = "pbeWithMD2AndDES-CBC"; +// public final static int NID_pbeWithMD2AndDES_CBC = 9; +// public final static String OBJ_pbeWithMD2AndDES_CBC = OBJ_pkcs+".5.1"; + +// public final static String SN_pbeWithMD5AndDES_CBC = "PBE-MD5-DES"; +// public final static String LN_pbeWithMD5AndDES_CBC = "pbeWithMD5AndDES-CBC"; +// public final static int NID_pbeWithMD5AndDES_CBC = 10; +// public final static String OBJ_pbeWithMD5AndDES_CBC = OBJ_pkcs+".5.3"; + +// public final static String LN_X500 = "X500"; +// public final static int NID_X500 = 11; +// public final static String OBJ_X500 = "2.5"; + +// public final static String LN_X509 = "X509"; +// public final static int NID_X509 = 12; +// public final static String OBJ_X509 = OBJ_X500+".4"; + +// public final static String SN_commonName = "CN"; +// public final static String LN_commonName = "commonName"; +// public final static int NID_commonName = 13; +// public final static String OBJ_commonName = OBJ_X509+".3"; + +// public final static String SN_countryName = "C"; +// public final static String LN_countryName = "countryName"; +// public final static int NID_countryName = 14; +// public final static String OBJ_countryName = OBJ_X509+".6"; + +// public final static String SN_localityName = ""; +// public final static String LN_localityName = "localityName"; +// public final static int NID_localityName = 15; +// public final static String OBJ_localityName = OBJ_X509+".7"; + +// public final static String SN_stateOrProvinceName = "ST"; +// public final static String LN_stateOrProvinceName = "stateOrProvinceName"; +// public final static int NID_stateOrProvinceName = 16; +// public final static String OBJ_stateOrProvinceName = OBJ_X509+".8"; + +// public final static String SN_organizationName = "O"; +// public final static String LN_organizationName = "organizationName"; +// public final static int NID_organizationName = 17; +// public final static String OBJ_organizationName = OBJ_X509+".10"; + +// public final static String SN_organizationalUnitName = "OU"; +// public final static String LN_organizationalUnitName = "organizationalUnitName"; +// public final static int NID_organizationalUnitName = 18; +// public final static String OBJ_organizationalUnitName = OBJ_X509+".11"; + +// public final static String SN_rsa = "RSA"; +// public final static String LN_rsa = "rsa"; +// public final static int NID_rsa = 19; +// public final static String OBJ_rsa = OBJ_X500+".8.1.1"; + +// public final static String LN_pkcs7 = "pkcs7"; +// public final static int NID_pkcs7 = 20; +// public final static String OBJ_pkcs7 = OBJ_pkcs+".7"; + +// public final static String LN_pkcs7_data = "pkcs7-data"; +// public final static int NID_pkcs7_data = 21; +// public final static String OBJ_pkcs7_data = OBJ_pkcs7+".1"; + +// public final static String LN_pkcs7_signed = "pkcs7-signedData"; +// public final static int NID_pkcs7_signed = 22; +// public final static String OBJ_pkcs7_signed = OBJ_pkcs7+".2"; + +// public final static String LN_pkcs7_enveloped = "pkcs7-envelopedData"; +// public final static int NID_pkcs7_enveloped = 23; +// public final static String OBJ_pkcs7_enveloped = OBJ_pkcs7+".3"; + +// public final static String LN_pkcs7_signedAndEnveloped = "pkcs7-signedAndEnvelopedData"; +// public final static int NID_pkcs7_signedAndEnveloped = 24; +// public final static String OBJ_pkcs7_signedAndEnveloped = OBJ_pkcs7+".4"; + +// public final static String LN_pkcs7_digest = "pkcs7-digestData"; +// public final static int NID_pkcs7_digest = 25; +// public final static String OBJ_pkcs7_digest = OBJ_pkcs7+".5"; + +// public final static String LN_pkcs7_encrypted = "pkcs7-encryptedData"; +// public final static int NID_pkcs7_encrypted = 26; +// public final static String OBJ_pkcs7_encrypted = OBJ_pkcs7+".6"; + +// public final static String LN_pkcs3 = "pkcs3"; +// public final static int NID_pkcs3 = 27; +// public final static String OBJ_pkcs3 = OBJ_pkcs+".3"; + +// public final static String LN_dhKeyAgreement = "dhKeyAgreement"; +// public final static int NID_dhKeyAgreement = 28; +// public final static String OBJ_dhKeyAgreement = OBJ_pkcs3+".1"; + +// public final static String SN_des_ecb = "DES-ECB"; +// public final static String LN_des_ecb = "des-ecb"; +// public final static int NID_des_ecb = 29; +// public final static String OBJ_des_ecb = OBJ_algorithm+".6"; + +// public final static String SN_des_cfb64 = "DES-CFB"; +// public final static String LN_des_cfb64 = "des-cfb"; +// public final static int NID_des_cfb64 = 30; +// public final static String OBJ_des_cfb64 = OBJ_algorithm+".9"; + +// public final static String SN_des_cbc = "DES-CBC"; +// public final static String LN_des_cbc = "des-cbc"; +// public final static int NID_des_cbc = 31; +// public final static String OBJ_des_cbc = OBJ_algorithm+".7"; + +// public final static String SN_des_ede = "DES-EDE"; +// public final static String LN_des_ede = "des-ede"; +// public final static int NID_des_ede = 32; +// public final static String OBJ_des_ede = OBJ_algorithm+".17"; + +// public final static String SN_des_ede3 = "DES-EDE3"; +// public final static String LN_des_ede3 = "des-ede3"; +// public final static int NID_des_ede3 = 33; + +// public final static String SN_idea_cbc = "IDEA-CBC"; +// public final static String LN_idea_cbc = "idea-cbc"; +// public final static int NID_idea_cbc = 34; +// public final static String OBJ_idea_cbc = "1.3.6.1.4.1.188.7.1.1.2"; + +// public final static String SN_idea_cfb64 = "IDEA-CFB"; +// public final static String LN_idea_cfb64 = "idea-cfb"; +// public final static int NID_idea_cfb64 = 35; + +// public final static String SN_idea_ecb = "IDEA-ECB"; +// public final static String LN_idea_ecb = "idea-ecb"; +// public final static int NID_idea_ecb = 36; + +// public final static String SN_rc2_cbc = "RC2-CBC"; +// public final static String LN_rc2_cbc = "rc2-cbc"; +// public final static int NID_rc2_cbc = 37; +// public final static String OBJ_rc2_cbc = OBJ_rsadsi+".3.2"; + +// public final static String SN_rc2_ecb = "RC2-ECB"; +// public final static String LN_rc2_ecb = "rc2-ecb"; +// public final static int NID_rc2_ecb = 38; + +// public final static String SN_rc2_cfb64 = "RC2-CFB"; +// public final static String LN_rc2_cfb64 = "rc2-cfb"; +// public final static int NID_rc2_cfb64 = 39; + +// public final static String SN_rc2_ofb64 = "RC2-OFB"; +// public final static String LN_rc2_ofb64 = "rc2-ofb"; +// public final static int NID_rc2_ofb64 = 40; + +// public final static String SN_sha = "SHA"; +// public final static String LN_sha = "sha"; +// public final static int NID_sha = 41; +// public final static String OBJ_sha = OBJ_algorithm+".18"; + +// public final static String SN_shaWithRSAEncryption = "RSA-SHA"; +// public final static String LN_shaWithRSAEncryption = "shaWithRSAEncryption"; +// public final static int NID_shaWithRSAEncryption = 42; +// public final static String OBJ_shaWithRSAEncryption = OBJ_algorithm+".15"; + +// public final static String SN_des_ede_cbc = "DES-EDE-CBC"; +// public final static String LN_des_ede_cbc = "des-ede-cbc"; +// public final static int NID_des_ede_cbc = 43; + +// public final static String SN_des_ede3_cbc = "DES-EDE3-CBC"; +// public final static String LN_des_ede3_cbc = "des-ede3-cbc"; +// public final static int NID_des_ede3_cbc = 44; +// public final static String OBJ_des_ede3_cbc = OBJ_rsadsi+".3.7"; + +// public final static String SN_des_ofb64 = "DES-OFB"; +// public final static String LN_des_ofb64 = "des-ofb"; +// public final static int NID_des_ofb64 = 45; +// public final static String OBJ_des_ofb64 = OBJ_algorithm+".8"; + +// public final static String SN_idea_ofb64 = "IDEA-OFB"; +// public final static String LN_idea_ofb64 = "idea-ofb"; +// public final static int NID_idea_ofb64 = 46; + +// public final static String LN_pkcs9 = "pkcs9"; +// public final static int NID_pkcs9 = 47; +// public final static String OBJ_pkcs9 = OBJ_pkcs+".9"; + +// public final static String SN_pkcs9_emailAddress = "Email"; +// public final static String LN_pkcs9_emailAddress = "emailAddress"; +// public final static int NID_pkcs9_emailAddress = 48; +// public final static String OBJ_pkcs9_emailAddress = OBJ_pkcs9+".1"; + +// public final static String LN_pkcs9_unstructuredName = "unstructuredName"; +// public final static int NID_pkcs9_unstructuredName = 49; +// public final static String OBJ_pkcs9_unstructuredName = OBJ_pkcs9+".2"; + +// public final static String LN_pkcs9_contentType = "contentType"; +// public final static int NID_pkcs9_contentType = 50; +// public final static String OBJ_pkcs9_contentType = OBJ_pkcs9+".3"; + +// public final static String LN_pkcs9_messageDigest = "messageDigest"; +// public final static int NID_pkcs9_messageDigest = 51; +// public final static String OBJ_pkcs9_messageDigest = OBJ_pkcs9+".4"; + +// public final static String LN_pkcs9_signingTime = "signingTime"; +// public final static int NID_pkcs9_signingTime = 52; +// public final static String OBJ_pkcs9_signingTime = OBJ_pkcs9+".5"; + +// public final static String LN_pkcs9_countersignature = "countersignature"; +// public final static int NID_pkcs9_countersignature = 53; +// public final static String OBJ_pkcs9_countersignature = OBJ_pkcs9+".6"; + +// public final static String LN_pkcs9_challengePassword = "challengePassword"; +// public final static int NID_pkcs9_challengePassword = 54; +// public final static String OBJ_pkcs9_challengePassword = OBJ_pkcs9+".7"; + +// public final static String LN_pkcs9_unstructuredAddress = "unstructuredAddress"; +// public final static int NID_pkcs9_unstructuredAddress = 55; +// public final static String OBJ_pkcs9_unstructuredAddress = OBJ_pkcs9+".8"; + +// public final static String LN_pkcs9_extCertAttributes = "extendedCertificateAttributes"; +// public final static int NID_pkcs9_extCertAttributes = 56; +// public final static String OBJ_pkcs9_extCertAttributes = OBJ_pkcs9+".9"; + +// public final static String SN_netscape = "Netscape"; +// public final static String LN_netscape = "Netscape Communications Corp."; +// public final static int NID_netscape = 57; +// public final static String OBJ_netscape = "2.16.840.1.113730"; + +// public final static String SN_netscape_cert_extension = "nsCertExt"; +// public final static String LN_netscape_cert_extension = "Netscape Certificate Extension"; +// public final static int NID_netscape_cert_extension = 58; +// public final static String OBJ_netscape_cert_extension = OBJ_netscape+".1"; + +// public final static String SN_netscape_data_type = "nsDataType"; +// public final static String LN_netscape_data_type = "Netscape Data Type"; +// public final static int NID_netscape_data_type = 59; +// public final static String OBJ_netscape_data_type = OBJ_netscape+".2"; + +// public final static String SN_des_ede_cfb64 = "DES-EDE-CFB"; +// public final static String LN_des_ede_cfb64 = "des-ede-cfb"; +// public final static int NID_des_ede_cfb64 = 60; + +// public final static String SN_des_ede3_cfb64 = "DES-EDE3-CFB"; +// public final static String LN_des_ede3_cfb64 = "des-ede3-cfb"; +// public final static int NID_des_ede3_cfb64 = 61; + +// public final static String SN_des_ede_ofb64 = "DES-EDE-OFB"; +// public final static String LN_des_ede_ofb64 = "des-ede-ofb"; +// public final static int NID_des_ede_ofb64 = 62; + +// public final static String SN_des_ede3_ofb64 = "DES-EDE3-OFB"; +// public final static String LN_des_ede3_ofb64 = "des-ede3-ofb"; +// public final static int NID_des_ede3_ofb64 = 63; + +// public final static String SN_sha1 = "SHA1"; +// public final static String LN_sha1 = "sha1"; +// public final static int NID_sha1 = 64; +// public final static String OBJ_sha1 = OBJ_algorithm+".26"; + +// public final static String SN_sha1WithRSAEncryption = "RSA-SHA1"; +// public final static String LN_sha1WithRSAEncryption = "sha1WithRSAEncryption"; +// public final static int NID_sha1WithRSAEncryption = 65; +// public final static String OBJ_sha1WithRSAEncryption = OBJ_pkcs+".1.5"; + +// public final static String SN_dsaWithSHA = "DSA-SHA"; +// public final static String LN_dsaWithSHA = "dsaWithSHA"; +// public final static int NID_dsaWithSHA = 66; +// public final static String OBJ_dsaWithSHA = OBJ_algorithm+".13"; + +// public final static String SN_dsa_2 = "DSA-old"; +// public final static String LN_dsa_2 = "dsaEncryption-old"; +// public final static int NID_dsa_2 = 67; +// public final static String OBJ_dsa_2 = OBJ_algorithm+".12"; + +// public final static String SN_pbeWithSHA1AndRC2_CBC = "PBE-SHA1-RC2-64"; +// public final static String LN_pbeWithSHA1AndRC2_CBC = "pbeWithSHA1AndRC2-CBC"; +// public final static int NID_pbeWithSHA1AndRC2_CBC = 68; +// public final static String OBJ_pbeWithSHA1AndRC2_CBC = OBJ_pkcs+".5.11L "; + +// public final static String LN_id_pbkdf2 = "PBKDF2"; +// public final static int NID_id_pbkdf2 = 69; +// public final static String OBJ_id_pbkdf2 = OBJ_pkcs+".5.12L "; + +// public final static String SN_dsaWithSHA1_2 = "DSA-SHA1-old"; +// public final static String LN_dsaWithSHA1_2 = "dsaWithSHA1-old"; +// public final static int NID_dsaWithSHA1_2 = 70; +// public final static String OBJ_dsaWithSHA1_2 = OBJ_algorithm+".27"; + +// public final static String SN_netscape_cert_type = "nsCertType"; +// public final static String LN_netscape_cert_type = "Netscape Cert Type"; +// public final static int NID_netscape_cert_type = 71; +// public final static String OBJ_netscape_cert_type = OBJ_netscape_cert_extension+".1"; + +// public final static String SN_netscape_base_url = "nsBaseUrl"; +// public final static String LN_netscape_base_url = "Netscape Base Url"; +// public final static int NID_netscape_base_url = 72; +// public final static String OBJ_netscape_base_url = OBJ_netscape_cert_extension+".2"; + +// public final static String SN_netscape_revocation_url = "nsRevocationUrl"; +// public final static String LN_netscape_revocation_url = "Netscape Revocation Url"; +// public final static int NID_netscape_revocation_url = 73; +// public final static String OBJ_netscape_revocation_url = OBJ_netscape_cert_extension+".3"; + +// public final static String SN_netscape_ca_revocation_url = "nsCaRevocationUrl"; +// public final static String LN_netscape_ca_revocation_url = "Netscape CA Revocation Url"; +// public final static int NID_netscape_ca_revocation_url = 74; +// public final static String OBJ_netscape_ca_revocation_url = OBJ_netscape_cert_extension+".4"; + +// public final static String SN_netscape_renewal_url = "nsRenewalUrl"; +// public final static String LN_netscape_renewal_url = "Netscape Renewal Url"; +// public final static int NID_netscape_renewal_url = 75; +// public final static String OBJ_netscape_renewal_url = OBJ_netscape_cert_extension+".7"; + +// public final static String SN_netscape_ca_policy_url = "nsCaPolicyUrl"; +// public final static String LN_netscape_ca_policy_url = "Netscape CA Policy Url"; +// public final static int NID_netscape_ca_policy_url = 76; +// public final static String OBJ_netscape_ca_policy_url = OBJ_netscape_cert_extension+".8"; + +// public final static String SN_netscape_ssl_server_name = "nsSslServerName"; +// public final static String LN_netscape_ssl_server_name = "Netscape SSL Server Name"; +// public final static int NID_netscape_ssl_server_name = 77; +// public final static String OBJ_netscape_ssl_server_name = OBJ_netscape_cert_extension+".12"; + +// public final static String SN_netscape_comment = "nsComment"; +// public final static String LN_netscape_comment = "Netscape Comment"; +// public final static int NID_netscape_comment = 78; +// public final static String OBJ_netscape_comment = OBJ_netscape_cert_extension+".13"; + +// public final static String SN_netscape_cert_sequence = "nsCertSequence"; +// public final static String LN_netscape_cert_sequence = "Netscape Certificate Sequence"; +// public final static int NID_netscape_cert_sequence = 79; +// public final static String OBJ_netscape_cert_sequence = OBJ_netscape_data_type+".5"; + +// public final static String SN_desx_cbc = "DESX-CBC"; +// public final static String LN_desx_cbc = "desx-cbc"; +// public final static int NID_desx_cbc = 80; + +// public final static String SN_id_ce = "id-ce"; +// public final static int NID_id_ce = 81; +// public final static String OBJ_id_ce = "2.5.29"; + +// public final static String SN_subject_key_identifier = "subjectKeyIdentifier"; +// public final static String LN_subject_key_identifier = "X509v3 Subject Key Identifier"; +// public final static int NID_subject_key_identifier = 82; +// public final static String OBJ_subject_key_identifier = OBJ_id_ce+".14"; + +// public final static String SN_key_usage = "keyUsage"; +// public final static String LN_key_usage = "X509v3 Key Usage"; +// public final static int NID_key_usage = 83; +// public final static String OBJ_key_usage = OBJ_id_ce+".15"; + +// public final static String SN_private_key_usage_period = "privateKeyUsagePeriod"; +// public final static String LN_private_key_usage_period = "X509v3 Private Key Usage Period"; +// public final static int NID_private_key_usage_period = 84; +// public final static String OBJ_private_key_usage_period = OBJ_id_ce+".16"; + +// public final static String SN_subject_alt_name = "subjectAltName"; +// public final static String LN_subject_alt_name = "X509v3 Subject Alternative Name"; +// public final static int NID_subject_alt_name = 85; +// public final static String OBJ_subject_alt_name = OBJ_id_ce+".17"; + +// public final static String SN_issuer_alt_name = "issuerAltName"; +// public final static String LN_issuer_alt_name = "X509v3 Issuer Alternative Name"; +// public final static int NID_issuer_alt_name = 86; +// public final static String OBJ_issuer_alt_name = OBJ_id_ce+".18"; + +// public final static String SN_basic_constraints = "basicConstraints"; +// public final static String LN_basic_constraints = "X509v3 Basic Constraints"; +// public final static int NID_basic_constraints = 87; +// public final static String OBJ_basic_constraints = OBJ_id_ce+".19"; + +// public final static String SN_crl_number = "crlNumber"; +// public final static String LN_crl_number = "X509v3 CRL Number"; +// public final static int NID_crl_number = 88; +// public final static String OBJ_crl_number = OBJ_id_ce+".20"; + +// public final static String SN_certificate_policies = "certificatePolicies"; +// public final static String LN_certificate_policies = "X509v3 Certificate Policies"; +// public final static int NID_certificate_policies = 89; +// public final static String OBJ_certificate_policies = OBJ_id_ce+".32"; + +// public final static String SN_authority_key_identifier = "authorityKeyIdentifier"; +// public final static String LN_authority_key_identifier = "X509v3 Authority Key Identifier"; +// public final static int NID_authority_key_identifier = 90; +// public final static String OBJ_authority_key_identifier = OBJ_id_ce+".35"; + +// public final static String SN_bf_cbc = "BF-CBC"; +// public final static String LN_bf_cbc = "bf-cbc"; +// public final static int NID_bf_cbc = 91; +// public final static String OBJ_bf_cbc = "1.3.6.1.4.1.3029.1.2"; + +// public final static String SN_bf_ecb = "BF-ECB"; +// public final static String LN_bf_ecb = "bf-ecb"; +// public final static int NID_bf_ecb = 92; + +// public final static String SN_bf_cfb64 = "BF-CFB"; +// public final static String LN_bf_cfb64 = "bf-cfb"; +// public final static int NID_bf_cfb64 = 93; + +// public final static String SN_bf_ofb64 = "BF-OFB"; +// public final static String LN_bf_ofb64 = "bf-ofb"; +// public final static int NID_bf_ofb64 = 94; + +// public final static String SN_mdc2 = "MDC2"; +// public final static String LN_mdc2 = "mdc2"; +// public final static int NID_mdc2 = 95; +// public final static String OBJ_mdc2 = "2.5.8.3.101"; + +// public final static String SN_mdc2WithRSA = "RSA-MDC2"; +// public final static String LN_mdc2WithRSA = "mdc2withRSA"; +// public final static int NID_mdc2WithRSA = 96; +// public final static String OBJ_mdc2WithRSA = "2.5.8.3.100"; + +// public final static String SN_rc4_40 = "RC4-40"; +// public final static String LN_rc4_40 = "rc4-40"; +// public final static int NID_rc4_40 = 97; + +// public final static String SN_rc2_40_cbc = "RC2-40-CBC"; +// public final static String LN_rc2_40_cbc = "rc2-40-cbc"; +// public final static int NID_rc2_40_cbc = 98; + +// public final static String SN_givenName = "G"; +// public final static String LN_givenName = "givenName"; +// public final static int NID_givenName = 99; +// public final static String OBJ_givenName = OBJ_X509+".42"; + +// public final static String SN_surname = "S"; +// public final static String LN_surname = "surname"; +// public final static int NID_surname = 100; +// public final static String OBJ_surname = OBJ_X509+".4"; + +// public final static String SN_initials = "I"; +// public final static String LN_initials = "initials"; +// public final static int NID_initials = 101; +// public final static String OBJ_initials = OBJ_X509+".43"; + +// public final static String SN_uniqueIdentifier = "UID"; +// public final static String LN_uniqueIdentifier = "uniqueIdentifier"; +// public final static int NID_uniqueIdentifier = 102; +// public final static String OBJ_uniqueIdentifier = OBJ_X509+".45"; + +// public final static String SN_crl_distribution_points = "crlDistributionPoints"; +// public final static String LN_crl_distribution_points = "X509v3 CRL Distribution Points"; +// public final static int NID_crl_distribution_points = 103; +// public final static String OBJ_crl_distribution_points = OBJ_id_ce+".31"; + +// public final static String SN_md5WithRSA = "RSA-NP-MD5"; +// public final static String LN_md5WithRSA = "md5WithRSA"; +// public final static int NID_md5WithRSA = 104; +// public final static String OBJ_md5WithRSA = OBJ_algorithm+".3"; + +// public final static String SN_serialNumber = "SN"; +// public final static String LN_serialNumber = "serialNumber"; +// public final static int NID_serialNumber = 105; +// public final static String OBJ_serialNumber = OBJ_X509+".5"; + +// public final static String SN_title = "T"; +// public final static String LN_title = "title"; +// public final static int NID_title = 106; +// public final static String OBJ_title = OBJ_X509+".12"; + +// public final static String SN_description = "D"; +// public final static String LN_description = "description"; +// public final static int NID_description = 107; +// public final static String OBJ_description = OBJ_X509+".13"; + +// public final static String SN_cast5_cbc = "CAST5-CBC"; +// public final static String LN_cast5_cbc = "cast5-cbc"; +// public final static int NID_cast5_cbc = 108; +// public final static String OBJ_cast5_cbc = "1.2.840.113533.7.66.10"; + +// public final static String SN_cast5_ecb = "CAST5-ECB"; +// public final static String LN_cast5_ecb = "cast5-ecb"; +// public final static int NID_cast5_ecb = 109; + +// public final static String SN_cast5_cfb64 = "CAST5-CFB"; +// public final static String LN_cast5_cfb64 = "cast5-cfb"; +// public final static int NID_cast5_cfb64 = 110; + +// public final static String SN_cast5_ofb64 = "CAST5-OFB"; +// public final static String LN_cast5_ofb64 = "cast5-ofb"; +// public final static int NID_cast5_ofb64 = 111; + +// public final static String LN_pbeWithMD5AndCast5_CBC = "pbeWithMD5AndCast5CBC"; +// public final static int NID_pbeWithMD5AndCast5_CBC = 112; +// public final static String OBJ_pbeWithMD5AndCast5_CBC = "1.2.840.113533.7.66.12"; + +// public final static String SN_dsaWithSHA1 = "DSA-SHA1"; +// public final static String LN_dsaWithSHA1 = "dsaWithSHA1"; +// public final static int NID_dsaWithSHA1 = 113; +// public final static String OBJ_dsaWithSHA1 = "1.2.840.10040.4.3"; + +// public final static int NID_md5_sha1 = 114; +// public final static String SN_md5_sha1 = "MD5-SHA1"; +// public final static String LN_md5_sha1 = "md5-sha1"; + +// public final static String SN_sha1WithRSA = "RSA-SHA1-2"; +// public final static String LN_sha1WithRSA = "sha1WithRSA"; +// public final static int NID_sha1WithRSA = 115; +// public final static String OBJ_sha1WithRSA = OBJ_algorithm+".29"; + +// public final static String SN_dsa = "DSA"; +// public final static String LN_dsa = "dsaEncryption"; +// public final static int NID_dsa = 116; +// public final static String OBJ_dsa = "1.2.840.10040.4.1"; + +// public final static String SN_ripemd160 = "RIPEMD160"; +// public final static String LN_ripemd160 = "ripemd160"; +// public final static int NID_ripemd160 = 117; +// public final static String OBJ_ripemd160 = "1.3.36.3.2.1"; + +// public final static String SN_ripemd160WithRSA = "RSA-RIPEMD160"; +// public final static String LN_ripemd160WithRSA = "ripemd160WithRSA"; +// public final static int NID_ripemd160WithRSA = 119; +// public final static String OBJ_ripemd160WithRSA = "1.3.36.3.3.1.2"; + +// public final static String SN_rc5_cbc = "RC5-CBC"; +// public final static String LN_rc5_cbc = "rc5-cbc"; +// public final static int NID_rc5_cbc = 120; +// public final static String OBJ_rc5_cbc = OBJ_rsadsi+".3.8"; + +// public final static String SN_rc5_ecb = "RC5-ECB"; +// public final static String LN_rc5_ecb = "rc5-ecb"; +// public final static int NID_rc5_ecb = 121; + +// public final static String SN_rc5_cfb64 = "RC5-CFB"; +// public final static String LN_rc5_cfb64 = "rc5-cfb"; +// public final static int NID_rc5_cfb64 = 122; + +// public final static String SN_rc5_ofb64 = "RC5-OFB"; +// public final static String LN_rc5_ofb64 = "rc5-ofb"; +// public final static int NID_rc5_ofb64 = 123; + +// public final static String SN_rle_compression = "RLE"; +// public final static String LN_rle_compression = "run length compression"; +// public final static int NID_rle_compression = 124; +// public final static String OBJ_rle_compression = "1.1.1.1.666.1"; + +// public final static String SN_zlib_compression = "ZLIB"; +// public final static String LN_zlib_compression = "zlib compression"; +// public final static int NID_zlib_compression = 125; +// public final static String OBJ_zlib_compression = "1.1.1.1.666.2"; + +// public final static String SN_ext_key_usage = "extendedKeyUsage"; +// public final static String LN_ext_key_usage = "X509v3 Extended Key Usage"; +// public final static int NID_ext_key_usage = 126; +// public final static String OBJ_ext_key_usage = OBJ_id_ce+".37"; + +// public final static String SN_id_pkix = "PKIX"; +// public final static int NID_id_pkix = 127; +// public final static String OBJ_id_pkix = "1.3.6.1.5.5.7"; + +// public final static String SN_id_kp = "id-kp"; +// public final static int NID_id_kp = 128; +// public final static String OBJ_id_kp = OBJ_id_pkix+".3"; + +// public final static String SN_server_auth = "serverAuth"; +// public final static String LN_server_auth = "TLS Web Server Authentication"; +// public final static int NID_server_auth = 129; +// public final static String OBJ_server_auth = OBJ_id_kp+".1"; + +// public final static String SN_client_auth = "clientAuth"; +// public final static String LN_client_auth = "TLS Web Client Authentication"; +// public final static int NID_client_auth = 130; +// public final static String OBJ_client_auth = OBJ_id_kp+".2"; + +// public final static String SN_code_sign = "codeSigning"; +// public final static String LN_code_sign = "Code Signing"; +// public final static int NID_code_sign = 131; +// public final static String OBJ_code_sign = OBJ_id_kp+".3"; + +// public final static String SN_email_protect = "emailProtection"; +// public final static String LN_email_protect = "E-mail Protection"; +// public final static int NID_email_protect = 132; +// public final static String OBJ_email_protect = OBJ_id_kp+".4"; + +// public final static String SN_time_stamp = "timeStamping"; +// public final static String LN_time_stamp = "Time Stamping"; +// public final static int NID_time_stamp = 133; +// public final static String OBJ_time_stamp = OBJ_id_kp+".8"; + +// public final static String SN_ms_code_ind = "msCodeInd"; +// public final static String LN_ms_code_ind = "Microsoft Individual Code Signing"; +// public final static int NID_ms_code_ind = 134; +// public final static String OBJ_ms_code_ind = "1.3.6.1.4.1.311.2.1.21"; + +// public final static String SN_ms_code_com = "msCodeCom"; +// public final static String LN_ms_code_com = "Microsoft Commercial Code Signing"; +// public final static int NID_ms_code_com = 135; +// public final static String OBJ_ms_code_com = "1.3.6.1.4.1.311.2.1.22"; + +// public final static String SN_ms_ctl_sign = "msCTLSign"; +// public final static String LN_ms_ctl_sign = "Microsoft Trust List Signing"; +// public final static int NID_ms_ctl_sign = 136; +// public final static String OBJ_ms_ctl_sign = "1.3.6.1.4.1.311.10.3.1"; + +// public final static String SN_ms_sgc = "msSGC"; +// public final static String LN_ms_sgc = "Microsoft Server Gated Crypto"; +// public final static int NID_ms_sgc = 137; +// public final static String OBJ_ms_sgc = "1.3.6.1.4.1.311.10.3.3"; + +// public final static String SN_ms_efs = "msEFS"; +// public final static String LN_ms_efs = "Microsoft Encrypted File System"; +// public final static int NID_ms_efs = 138; +// public final static String OBJ_ms_efs = "1.3.6.1.4.1.311.10.3.4"; + +// public final static String SN_ns_sgc = "nsSGC"; +// public final static String LN_ns_sgc = "Netscape Server Gated Crypto"; +// public final static int NID_ns_sgc = 139; +// public final static String OBJ_ns_sgc = OBJ_netscape+".4.1"; + +// public final static String SN_delta_crl = "deltaCR"; +// public final static String LN_delta_crl = "X509v3 Delta CRL Indicator"; +// public final static int NID_delta_crl = 140; +// public final static String OBJ_delta_crl = OBJ_id_ce+".27"; + +// public final static String SN_crl_reason = "CRLReason"; +// public final static String LN_crl_reason = "CRL Reason Code"; +// public final static int NID_crl_reason = 141; +// public final static String OBJ_crl_reason = OBJ_id_ce+".21"; + +// public final static String SN_invalidity_date = "invalidityDate"; +// public final static String LN_invalidity_date = "Invalidity Date"; +// public final static int NID_invalidity_date = 142; +// public final static String OBJ_invalidity_date = OBJ_id_ce+".24"; + +// public final static String SN_sxnet = "SXNetID"; +// public final static String LN_sxnet = "Strong Extranet ID"; +// public final static int NID_sxnet = 143; +// public final static String OBJ_sxnet = "1.3.101.1.4.1"; + +// public final static String OBJ_pkcs12 = OBJ_pkcs+".12"; +// public final static String OBJ_pkcs12_pbeids = OBJ_pkcs12+".1"; + +// public final static String SN_pbe_WithSHA1And128BitRC4 = "PBE-SHA1-RC4-128"; +// public final static String LN_pbe_WithSHA1And128BitRC4 = "pbeWithSHA1And128BitRC4"; +// public final static int NID_pbe_WithSHA1And128BitRC4 = 144; +// public final static String OBJ_pbe_WithSHA1And128BitRC4 = OBJ_pkcs12_pbeids+".1"; + +// public final static String SN_pbe_WithSHA1And40BitRC4 = "PBE-SHA1-RC4-40"; +// public final static String LN_pbe_WithSHA1And40BitRC4 = "pbeWithSHA1And40BitRC4"; +// public final static int NID_pbe_WithSHA1And40BitRC4 = 145; +// public final static String OBJ_pbe_WithSHA1And40BitRC4 = OBJ_pkcs12_pbeids+".2"; + +// public final static String SN_pbe_WithSHA1And3_Key_TripleDES_CBC = "PBE-SHA1-3DES"; +// public final static String LN_pbe_WithSHA1And3_Key_TripleDES_CBC = "pbeWithSHA1And3-KeyTripleDES-CBC"; +// public final static int NID_pbe_WithSHA1And3_Key_TripleDES_CBC = 146; +// public final static String OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC = OBJ_pkcs12_pbeids+".3"; + +// public final static String SN_pbe_WithSHA1And2_Key_TripleDES_CBC = "PBE-SHA1-2DES"; +// public final static String LN_pbe_WithSHA1And2_Key_TripleDES_CBC = "pbeWithSHA1And2-KeyTripleDES-CBC"; +// public final static int NID_pbe_WithSHA1And2_Key_TripleDES_CBC = 147; +// public final static String OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC = OBJ_pkcs12_pbeids+".4"; + +// public final static String SN_pbe_WithSHA1And128BitRC2_CBC = "PBE-SHA1-RC2-128"; +// public final static String LN_pbe_WithSHA1And128BitRC2_CBC = "pbeWithSHA1And128BitRC2-CBC"; +// public final static int NID_pbe_WithSHA1And128BitRC2_CBC = 148; +// public final static String OBJ_pbe_WithSHA1And128BitRC2_CBC = OBJ_pkcs12_pbeids+".5"; + +// public final static String SN_pbe_WithSHA1And40BitRC2_CBC = "PBE-SHA1-RC2-40"; +// public final static String LN_pbe_WithSHA1And40BitRC2_CBC = "pbeWithSHA1And40BitRC2-CBC"; +// public final static int NID_pbe_WithSHA1And40BitRC2_CBC = 149; +// public final static String OBJ_pbe_WithSHA1And40BitRC2_CBC = OBJ_pkcs12_pbeids+".6"; + +// public final static String OBJ_pkcs12_Version1 = OBJ_pkcs12+".10"; + +// public final static String OBJ_pkcs12_BagIds = OBJ_pkcs12_Version1+".1"; + +// public final static String LN_keyBag = "keyBag"; +// public final static int NID_keyBag = 150; +// public final static String OBJ_keyBag = OBJ_pkcs12_BagIds+".1"; + +// public final static String LN_pkcs8ShroudedKeyBag = "pkcs8ShroudedKeyBag"; +// public final static int NID_pkcs8ShroudedKeyBag = 151; +// public final static String OBJ_pkcs8ShroudedKeyBag = OBJ_pkcs12_BagIds+".2"; + +// public final static String LN_certBag = "certBag"; +// public final static int NID_certBag = 152; +// public final static String OBJ_certBag = OBJ_pkcs12_BagIds+".3"; + +// public final static String LN_crlBag = "crlBag"; +// public final static int NID_crlBag = 153; +// public final static String OBJ_crlBag = OBJ_pkcs12_BagIds+".4"; + +// public final static String LN_secretBag = "secretBag"; +// public final static int NID_secretBag = 154; +// public final static String OBJ_secretBag = OBJ_pkcs12_BagIds+".5"; + +// public final static String LN_safeContentsBag = "safeContentsBag"; +// public final static int NID_safeContentsBag = 155; +// public final static String OBJ_safeContentsBag = OBJ_pkcs12_BagIds+".6"; + +// public final static String LN_friendlyName = "friendlyName"; +// public final static int NID_friendlyName = 156; +// public final static String OBJ_friendlyName = OBJ_pkcs9+".20"; + +// public final static String LN_localKeyID = "localKeyID"; +// public final static int NID_localKeyID = 157; +// public final static String OBJ_localKeyID = OBJ_pkcs9+".21"; + +// public final static String OBJ_certTypes = OBJ_pkcs9+".22"; + +// public final static String LN_x509Certificate = "x509Certificate"; +// public final static int NID_x509Certificate = 158; +// public final static String OBJ_x509Certificate = OBJ_certTypes+".1"; + +// public final static String LN_sdsiCertificate = "sdsiCertificate"; +// public final static int NID_sdsiCertificate = 159; +// public final static String OBJ_sdsiCertificate = OBJ_certTypes+".2"; + +// public final static String OBJ_crlTypes = OBJ_pkcs9+".23"; + +// public final static String LN_x509Crl = "x509Crl"; +// public final static int NID_x509Crl = 160; +// public final static String OBJ_x509Crl = OBJ_crlTypes+".1"; + +// public final static String LN_pbes2 = "PBES2"; +// public final static int NID_pbes2 = 161; +// public final static String OBJ_pbes2 = OBJ_pkcs+".5.13"; + +// public final static String LN_pbmac1 = "PBMAC1"; +// public final static int NID_pbmac1 = 162; +// public final static String OBJ_pbmac1 = OBJ_pkcs+".5.14"; + +// public final static String LN_hmacWithSHA1 = "hmacWithSHA1"; +// public final static int NID_hmacWithSHA1 = 163; +// public final static String OBJ_hmacWithSHA1 = OBJ_rsadsi+".2.7"; + +// public final static String LN_id_qt_cps = "Policy Qualifier CPS"; +// public final static String SN_id_qt_cps = "id-qt-cps"; +// public final static int NID_id_qt_cps = 164; +// public final static String OBJ_id_qt_cps = OBJ_id_pkix+".2.1"; + +// public final static String LN_id_qt_unotice = "Policy Qualifier User Notice"; +// public final static String SN_id_qt_unotice = "id-qt-unotice"; +// public final static int NID_id_qt_unotice = 165; +// public final static String OBJ_id_qt_unotice = OBJ_id_pkix+".2.2"; + +// public final static String SN_rc2_64_cbc = "RC2-64-CBC"; +// public final static String LN_rc2_64_cbc = "rc2-64-cbc"; +// public final static int NID_rc2_64_cbc = 166; + +// public final static String SN_SMIMECapabilities = "SMIME-CAPS"; +// public final static String LN_SMIMECapabilities = "S/MIME Capabilities"; +// public final static int NID_SMIMECapabilities = 167; +// public final static String OBJ_SMIMECapabilities = OBJ_pkcs9+".15"; + +// public final static String SN_pbeWithMD2AndRC2_CBC = "PBE-MD2-RC2-64"; +// public final static String LN_pbeWithMD2AndRC2_CBC = "pbeWithMD2AndRC2-CBC"; +// public final static int NID_pbeWithMD2AndRC2_CBC = 168; +// public final static String OBJ_pbeWithMD2AndRC2_CBC = OBJ_pkcs+".5.4"; + +// public final static String SN_pbeWithMD5AndRC2_CBC = "PBE-MD5-RC2-64"; +// public final static String LN_pbeWithMD5AndRC2_CBC = "pbeWithMD5AndRC2-CBC"; +// public final static int NID_pbeWithMD5AndRC2_CBC = 169; +// public final static String OBJ_pbeWithMD5AndRC2_CBC = OBJ_pkcs+".5.6"; + +// public final static String SN_pbeWithSHA1AndDES_CBC = "PBE-SHA1-DES"; +// public final static String LN_pbeWithSHA1AndDES_CBC = "pbeWithSHA1AndDES-CBC"; +// public final static int NID_pbeWithSHA1AndDES_CBC = 170; +// public final static String OBJ_pbeWithSHA1AndDES_CBC = OBJ_pkcs+".5.10"; + +// public final static String LN_ms_ext_req = "Microsoft Extension Request"; +// public final static String SN_ms_ext_req = "msExtReq"; +// public final static int NID_ms_ext_req = 171; +// public final static String OBJ_ms_ext_req = "1.3.6.1.4.1.311.2.1.14"; + +// public final static String LN_ext_req = "Extension Request"; +// public final static String SN_ext_req = "extReq"; +// public final static int NID_ext_req = 172; +// public final static String OBJ_ext_req = OBJ_pkcs9+".14"; + +// public final static String SN_name = "name"; +// public final static String LN_name = "name"; +// public final static int NID_name = 173; +// public final static String OBJ_name = OBJ_X509+".41"; + +// public final static String SN_dnQualifier = "dnQualifier"; +// public final static String LN_dnQualifier = "dnQualifier"; +// public final static int NID_dnQualifier = 174; +// public final static String OBJ_dnQualifier = OBJ_X509+".46"; + +// public final static String SN_id_pe = "id-pe"; +// public final static int NID_id_pe = 175; +// public final static String OBJ_id_pe = OBJ_id_pkix+".1"; + +// public final static String SN_id_ad = "id-ad"; +// public final static int NID_id_ad = 176; +// public final static String OBJ_id_ad = OBJ_id_pkix+".48"; + +// public final static String SN_info_access = "authorityInfoAccess"; +// public final static String LN_info_access = "Authority Information Access"; +// public final static int NID_info_access = 177; +// public final static String OBJ_info_access = OBJ_id_pe+".1"; + +// public final static String SN_ad_OCSP = "OCSP"; +// public final static String LN_ad_OCSP = "OCSP"; +// public final static int NID_ad_OCSP = 178; +// public final static String OBJ_ad_OCSP = OBJ_id_ad+".1"; + +// public final static String SN_ad_ca_issuers = "caIssuers"; +// public final static String LN_ad_ca_issuers = "CA Issuers"; +// public final static int NID_ad_ca_issuers = 179; +// public final static String OBJ_ad_ca_issuers = OBJ_id_ad+".2"; + +// public final static String SN_OCSP_sign = "OCSPSigning"; +// public final static String LN_OCSP_sign = "OCSP Signing"; +// public final static int NID_OCSP_sign = 180; +// public final static String OBJ_OCSP_sign = OBJ_id_kp+".9"; + +// static { +// addObject(NID_undef, SN_undef, LN_undef, OBJ_undef); +// addObject(NID_rsadsi, SN_rsadsi, LN_rsadsi, OBJ_rsadsi); +// addObject(NID_pkcs, SN_pkcs, LN_pkcs, OBJ_pkcs); +// addObject(NID_md2, SN_md2, LN_md2, OBJ_md2); +// addObject(NID_md5, SN_md5, LN_md5, OBJ_md5); +// addObject(NID_rc4, SN_rc4, LN_rc4, OBJ_rc4); +// addObject(NID_rsaEncryption, SN_rsaEncryption, LN_rsaEncryption, OBJ_rsaEncryption); +// addObject(NID_md2WithRSAEncryption, SN_md2WithRSAEncryption, LN_md2WithRSAEncryption, OBJ_md2WithRSAEncryption); +// addObject(NID_md5WithRSAEncryption, SN_md5WithRSAEncryption, LN_md5WithRSAEncryption, OBJ_md5WithRSAEncryption); +// addObject(NID_pbeWithMD2AndDES_CBC, SN_pbeWithMD2AndDES_CBC, LN_pbeWithMD2AndDES_CBC, OBJ_pbeWithMD2AndDES_CBC); +// addObject(NID_pbeWithMD5AndDES_CBC, SN_pbeWithMD5AndDES_CBC, LN_pbeWithMD5AndDES_CBC, OBJ_pbeWithMD5AndDES_CBC); +// addObject(NID_X500, SN_X500, LN_X500, OBJ_X500); +// addObject(NID_X509, SN_X509, LN_X509, OBJ_X509); +// addObject(NID_commonName, SN_commonName, LN_commonName, OBJ_commonName); +// addObject(NID_countryName, SN_countryName, LN_countryName, OBJ_countryName); +// addObject(NID_localityName, SN_localityName, LN_localityName, OBJ_localityName); +// addObject(NID_stateOrProvinceName, SN_stateOrProvinceName, LN_stateOrProvinceName, OBJ_stateOrProvinceName); +// addObject(NID_organizationName, SN_organizationName, LN_organizationName, OBJ_organizationName); +// addObject(NID_organizationalUnitName, SN_organizationalUnitName, LN_organizationalUnitName, OBJ_organizationalUnitName); +// addObject(NID_rsa, SN_rsa, LN_rsa, OBJ_rsa); +// addObject(NID_pkcs7, SN_pkcs7, LN_pkcs7, OBJ_pkcs7); +// addObject(NID_pkcs7_data, SN_pkcs7_data, LN_pkcs7_data, OBJ_pkcs7_data); +// addObject(NID_pkcs7_signed, SN_pkcs7_signed, LN_pkcs7_signed, OBJ_pkcs7_signed); +// addObject(NID_pkcs7_enveloped, SN_pkcs7_enveloped, LN_pkcs7_enveloped, OBJ_pkcs7_enveloped); +// addObject(NID_pkcs7_signedAndEnveloped, SN_pkcs7_signedAndEnveloped, LN_pkcs7_signedAndEnveloped, OBJ_pkcs7_signedAndEnveloped); +// addObject(NID_pkcs7_digest, SN_pkcs7_digest, LN_pkcs7_digest, OBJ_pkcs7_digest); +// addObject(NID_pkcs7_encrypted, SN_pkcs7_encrypted, LN_pkcs7_encrypted, OBJ_pkcs7_encrypted); +// addObject(NID_pkcs3, SN_pkcs3, LN_pkcs3, OBJ_pkcs3); +// addObject(NID_dhKeyAgreement, SN_dhKeyAgreement, LN_dhKeyAgreement, OBJ_dhKeyAgreement); +// addObject(NID_des_ecb, SN_des_ecb, LN_des_ecb, OBJ_des_ecb); +// addObject(NID_des_cfb64, SN_des_cfb64, LN_des_cfb64, OBJ_des_cfb64); +// addObject(NID_des_cbc, SN_des_cbc, LN_des_cbc, OBJ_des_cbc); +// addObject(NID_des_ede, SN_des_ede, LN_des_ede, OBJ_des_ede); +// addObject(NID_des_ede3, SN_des_ede3, LN_des_ede3, OBJ_des_ede3); +// addObject(NID_idea_cbc, SN_idea_cbc, LN_idea_cbc, OBJ_idea_cbc); +// addObject(NID_idea_cfb64, SN_idea_cfb64, LN_idea_cfb64, OBJ_idea_cfb64); +// addObject(NID_idea_ecb, SN_idea_ecb, LN_idea_ecb, OBJ_idea_ecb); +// addObject(NID_rc2_cbc, SN_rc2_cbc, LN_rc2_cbc, OBJ_rc2_cbc); +// addObject(NID_rc2_ecb, SN_rc2_ecb, LN_rc2_ecb, OBJ_rc2_ecb); +// addObject(NID_rc2_cfb64, SN_rc2_cfb64, LN_rc2_cfb64, OBJ_rc2_cfb64); +// addObject(NID_rc2_ofb64, SN_rc2_ofb64, LN_rc2_ofb64, OBJ_rc2_ofb64); +// addObject(NID_sha, SN_sha, LN_sha, OBJ_sha); +// addObject(NID_shaWithRSAEncryption, SN_shaWithRSAEncryption, LN_shaWithRSAEncryption, OBJ_shaWithRSAEncryption); +// addObject(NID_des_ede_cbc, SN_des_ede_cbc, LN_des_ede_cbc, OBJ_des_ede_cbc); +// addObject(NID_des_ede3_cbc, SN_des_ede3_cbc, LN_des_ede3_cbc, OBJ_des_ede3_cbc); +// addObject(NID_des_ofb64, SN_des_ofb64, LN_des_ofb64, OBJ_des_ofb64); +// addObject(NID_idea_ofb64, SN_idea_ofb64, LN_idea_ofb64, OBJ_idea_ofb64); +// addObject(NID_pkcs9, SN_pkcs9, LN_pkcs9, OBJ_pkcs9); +// addObject(NID_pkcs9_emailAddress, SN_pkcs9_emailAddress, LN_pkcs9_emailAddress, OBJ_pkcs9_emailAddress); +// addObject(NID_pkcs9_unstructuredName, SN_pkcs9_unstructuredName, LN_pkcs9_unstructuredName, OBJ_pkcs9_unstructuredName); +// addObject(NID_pkcs9_contentType, SN_pkcs9_contentType, LN_pkcs9_contentType, OBJ_pkcs9_contentType); +// addObject(NID_pkcs9_messageDigest, SN_pkcs9_messageDigest, LN_pkcs9_messageDigest, OBJ_pkcs9_messageDigest); +// addObject(NID_pkcs9_signingTime, SN_pkcs9_signingTime, LN_pkcs9_signingTime, OBJ_pkcs9_signingTime); +// addObject(NID_pkcs9_countersignature, SN_pkcs9_countersignature, LN_pkcs9_countersignature, OBJ_pkcs9_countersignature); +// addObject(NID_pkcs9_challengePassword, SN_pkcs9_challengePassword, LN_pkcs9_challengePassword, OBJ_pkcs9_challengePassword); +// addObject(NID_pkcs9_unstructuredAddress, SN_pkcs9_unstructuredAddress, LN_pkcs9_unstructuredAddress, OBJ_pkcs9_unstructuredAddress); +// addObject(NID_pkcs9_extCertAttributes, SN_pkcs9_extCertAttributes, LN_pkcs9_extCertAttributes, OBJ_pkcs9_extCertAttributes); +// addObject(NID_netscape, SN_netscape, LN_netscape, OBJ_netscape); +// addObject(NID_netscape_cert_extension, SN_netscape_cert_extension, LN_netscape_cert_extension, OBJ_netscape_cert_extension); +// addObject(NID_netscape_data_type, SN_netscape_data_type, LN_netscape_data_type, OBJ_netscape_data_type); +// addObject(NID_des_ede_cfb64, SN_des_ede_cfb64, LN_des_ede_cfb64, OBJ_des_ede_cfb64); +// addObject(NID_des_ede3_cfb64, SN_des_ede3_cfb64, LN_des_ede3_cfb64, OBJ_des_ede3_cfb64); +// addObject(NID_des_ede_ofb64, SN_des_ede_ofb64, LN_des_ede_ofb64, OBJ_des_ede_ofb64); +// addObject(NID_des_ede3_ofb64, SN_des_ede3_ofb64, LN_des_ede3_ofb64, OBJ_des_ede3_ofb64); +// addObject(NID_sha1, SN_sha1, LN_sha1, OBJ_sha1); +// addObject(NID_sha1WithRSAEncryption, SN_sha1WithRSAEncryption, LN_sha1WithRSAEncryption, OBJ_sha1WithRSAEncryption); +// addObject(NID_dsaWithSHA, SN_dsaWithSHA, LN_dsaWithSHA, OBJ_dsaWithSHA); +// addObject(NID_dsa_2, SN_dsa_2, LN_dsa_2, OBJ_dsa_2); +// addObject(NID_pbeWithSHA1AndRC2_CBC, SN_pbeWithSHA1AndRC2_CBC, LN_pbeWithSHA1AndRC2_CBC, OBJ_pbeWithSHA1AndRC2_CBC); +// addObject(NID_id_pbkdf2, SN_id_pbkdf2, LN_id_pbkdf2, OBJ_id_pbkdf2); +// addObject(NID_dsaWithSHA1_2, SN_dsaWithSHA1_2, LN_dsaWithSHA1_2, OBJ_dsaWithSHA1_2); +// addObject(NID_netscape_cert_type, SN_netscape_cert_type, LN_netscape_cert_type, OBJ_netscape_cert_type); +// addObject(NID_netscape_base_url, SN_netscape_base_url, LN_netscape_base_url, OBJ_netscape_base_url); +// addObject(NID_netscape_revocation_url, SN_netscape_revocation_url, LN_netscape_revocation_url, OBJ_netscape_revocation_url); +// addObject(NID_netscape_ca_revocation_url, SN_netscape_ca_revocation_url, LN_netscape_ca_revocation_url, OBJ_netscape_ca_revocation_url); +// addObject(NID_netscape_renewal_url, SN_netscape_renewal_url, LN_netscape_renewal_url, OBJ_netscape_renewal_url); +// addObject(NID_netscape_ca_policy_url, SN_netscape_ca_policy_url, LN_netscape_ca_policy_url, OBJ_netscape_ca_policy_url); +// addObject(NID_netscape_ssl_server_name, SN_netscape_ssl_server_name, LN_netscape_ssl_server_name, OBJ_netscape_ssl_server_name); +// addObject(NID_netscape_comment, SN_netscape_comment, LN_netscape_comment, OBJ_netscape_comment); +// addObject(NID_netscape_cert_sequence, SN_netscape_cert_sequence, LN_netscape_cert_sequence, OBJ_netscape_cert_sequence); +// addObject(NID_desx_cbc, SN_desx_cbc, LN_desx_cbc, OBJ_desx_cbc); +// addObject(NID_id_ce, SN_id_ce, LN_id_ce, OBJ_id_ce); +// addObject(NID_subject_key_identifier, SN_subject_key_identifier, LN_subject_key_identifier, OBJ_subject_key_identifier); +// addObject(NID_key_usage, SN_key_usage, LN_key_usage, OBJ_key_usage); +// addObject(NID_private_key_usage_period, SN_private_key_usage_period, LN_private_key_usage_period, OBJ_private_key_usage_period); +// addObject(NID_subject_alt_name, SN_subject_alt_name, LN_subject_alt_name, OBJ_subject_alt_name); +// addObject(NID_issuer_alt_name, SN_issuer_alt_name, LN_issuer_alt_name, OBJ_issuer_alt_name); +// addObject(NID_basic_constraints, SN_basic_constraints, LN_basic_constraints, OBJ_basic_constraints); +// addObject(NID_crl_number, SN_crl_number, LN_crl_number, OBJ_crl_number); +// addObject(NID_certificate_policies, SN_certificate_policies, LN_certificate_policies, OBJ_certificate_policies); +// addObject(NID_authority_key_identifier, SN_authority_key_identifier, LN_authority_key_identifier, OBJ_authority_key_identifier); +// addObject(NID_bf_cbc, SN_bf_cbc, LN_bf_cbc, OBJ_bf_cbc); +// addObject(NID_bf_ecb, SN_bf_ecb, LN_bf_ecb, OBJ_bf_ecb); +// addObject(NID_bf_cfb64, SN_bf_cfb64, LN_bf_cfb64, OBJ_bf_cfb64); +// addObject(NID_bf_ofb64, SN_bf_ofb64, LN_bf_ofb64, OBJ_bf_ofb64); +// addObject(NID_mdc2, SN_mdc2, LN_mdc2, OBJ_mdc2); +// addObject(NID_mdc2WithRSA, SN_mdc2WithRSA, LN_mdc2WithRSA, OBJ_mdc2WithRSA); +// addObject(NID_rc4_40, SN_rc4_40, LN_rc4_40, OBJ_rc4_40); +// addObject(NID_rc2_40_cbc, SN_rc2_40_cbc, LN_rc2_40_cbc, OBJ_rc2_40_cbc); +// addObject(NID_givenName, SN_givenName, LN_givenName, OBJ_givenName); +// addObject(NID_surname, SN_surname, LN_surname, OBJ_surname); +// addObject(NID_initials, SN_initials, LN_initials, OBJ_initials); +// addObject(NID_uniqueIdentifier, SN_uniqueIdentifier, LN_uniqueIdentifier, OBJ_uniqueIdentifier); +// addObject(NID_crl_distribution_points, SN_crl_distribution_points, LN_crl_distribution_points, OBJ_crl_distribution_points); +// addObject(NID_md5WithRSA, SN_md5WithRSA, LN_md5WithRSA, OBJ_md5WithRSA); +// addObject(NID_serialNumber, SN_serialNumber, LN_serialNumber, OBJ_serialNumber); +// addObject(NID_title, SN_title, LN_title, OBJ_title); +// addObject(NID_description, SN_description, LN_description, OBJ_description); +// addObject(NID_cast5_cbc, SN_cast5_cbc, LN_cast5_cbc, OBJ_cast5_cbc); +// addObject(NID_cast5_ecb, SN_cast5_ecb, LN_cast5_ecb, OBJ_cast5_ecb); +// addObject(NID_cast5_cfb64, SN_cast5_cfb64, LN_cast5_cfb64, OBJ_cast5_cfb64); +// addObject(NID_cast5_ofb64, SN_cast5_ofb64, LN_cast5_ofb64, OBJ_cast5_ofb64); +// addObject(NID_pbeWithMD5AndCast5_CBC, SN_pbeWithMD5AndCast5_CBC, LN_pbeWithMD5AndCast5_CBC, OBJ_pbeWithMD5AndCast5_CBC); +// addObject(NID_dsaWithSHA1, SN_dsaWithSHA1, LN_dsaWithSHA1, OBJ_dsaWithSHA1); +// addObject(NID_md5_sha1, SN_md5_sha1, LN_md5_sha1, OBJ_md5_sha1); +// addObject(NID_sha1WithRSA, SN_sha1WithRSA, LN_sha1WithRSA, OBJ_sha1WithRSA); +// addObject(NID_dsa, SN_dsa, LN_dsa, OBJ_dsa); +// addObject(NID_ripemd160, SN_ripemd160, LN_ripemd160, OBJ_ripemd160); +// addObject(NID_ripemd160WithRSA, SN_ripemd160WithRSA, LN_ripemd160WithRSA, OBJ_ripemd160WithRSA); +// addObject(NID_rc5_cbc, SN_rc5_cbc, LN_rc5_cbc, OBJ_rc5_cbc); +// addObject(NID_rc5_ecb, SN_rc5_ecb, LN_rc5_ecb, OBJ_rc5_ecb); +// addObject(NID_rc5_cfb64, SN_rc5_cfb64, LN_rc5_cfb64, OBJ_rc5_cfb64); +// addObject(NID_rc5_ofb64, SN_rc5_ofb64, LN_rc5_ofb64, OBJ_rc5_ofb64); +// addObject(NID_rle_compression, SN_rle_compression, LN_rle_compression, OBJ_rle_compression); +// addObject(NID_zlib_compression, SN_zlib_compression, LN_zlib_compression, OBJ_zlib_compression); +// addObject(NID_ext_key_usage, SN_ext_key_usage, LN_ext_key_usage, OBJ_ext_key_usage); +// addObject(NID_id_pkix, SN_id_pkix, LN_id_pkix, OBJ_id_pkix); +// addObject(NID_id_kp, SN_id_kp, LN_id_kp, OBJ_id_kp); +// addObject(NID_server_auth, SN_server_auth, LN_server_auth, OBJ_server_auth); +// addObject(NID_client_auth, SN_client_auth, LN_client_auth, OBJ_client_auth); +// addObject(NID_code_sign, SN_code_sign, LN_code_sign, OBJ_code_sign); +// addObject(NID_email_protect, SN_email_protect, LN_email_protect, OBJ_email_protect); +// addObject(NID_time_stamp, SN_time_stamp, LN_time_stamp, OBJ_time_stamp); +// addObject(NID_ms_code_ind, SN_ms_code_ind, LN_ms_code_ind, OBJ_ms_code_ind); +// addObject(NID_ms_code_com, SN_ms_code_com, LN_ms_code_com, OBJ_ms_code_com); +// addObject(NID_ms_ctl_sign, SN_ms_ctl_sign, LN_ms_ctl_sign, OBJ_ms_ctl_sign); +// addObject(NID_ms_sgc, SN_ms_sgc, LN_ms_sgc, OBJ_ms_sgc); +// addObject(NID_ms_efs, SN_ms_efs, LN_ms_efs, OBJ_ms_efs); +// addObject(NID_ns_sgc, SN_ns_sgc, LN_ns_sgc, OBJ_ns_sgc); +// addObject(NID_delta_crl, SN_delta_crl, LN_delta_crl, OBJ_delta_crl); +// addObject(NID_crl_reason, SN_crl_reason, LN_crl_reason, OBJ_crl_reason); +// addObject(NID_invalidity_date, SN_invalidity_date, LN_invalidity_date, OBJ_invalidity_date); +// addObject(NID_sxnet, SN_sxnet, LN_sxnet, OBJ_sxnet); +// addObject(NID_pbe_WithSHA1And128BitRC4, SN_pbe_WithSHA1And128BitRC4, LN_pbe_WithSHA1And128BitRC4, OBJ_pbe_WithSHA1And128BitRC4); +// addObject(NID_pbe_WithSHA1And40BitRC4, SN_pbe_WithSHA1And40BitRC4, LN_pbe_WithSHA1And40BitRC4, OBJ_pbe_WithSHA1And40BitRC4); +// addObject(NID_pbe_WithSHA1And3_Key_TripleDES_CBC, SN_pbe_WithSHA1And3_Key_TripleDES_CBC, LN_pbe_WithSHA1And3_Key_TripleDES_CBC, OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC); +// addObject(NID_pbe_WithSHA1And2_Key_TripleDES_CBC, SN_pbe_WithSHA1And2_Key_TripleDES_CBC, LN_pbe_WithSHA1And2_Key_TripleDES_CBC, OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC); +// addObject(NID_pbe_WithSHA1And128BitRC2_CBC, SN_pbe_WithSHA1And128BitRC2_CBC, LN_pbe_WithSHA1And128BitRC2_CBC, OBJ_pbe_WithSHA1And128BitRC2_CBC); +// addObject(NID_pbe_WithSHA1And40BitRC2_CBC, SN_pbe_WithSHA1And40BitRC2_CBC, LN_pbe_WithSHA1And40BitRC2_CBC, OBJ_pbe_WithSHA1And40BitRC2_CBC); +// addObject(NID_keyBag, SN_keyBag, LN_keyBag, OBJ_keyBag); +// addObject(NID_pkcs8ShroudedKeyBag, SN_pkcs8ShroudedKeyBag, LN_pkcs8ShroudedKeyBag, OBJ_pkcs8ShroudedKeyBag); +// addObject(NID_certBag, SN_certBag, LN_certBag, OBJ_certBag); +// addObject(NID_crlBag, SN_crlBag, LN_crlBag, OBJ_crlBag); +// addObject(NID_secretBag, SN_secretBag, LN_secretBag, OBJ_secretBag); +// addObject(NID_safeContentsBag, SN_safeContentsBag, LN_safeContentsBag, OBJ_safeContentsBag); +// addObject(NID_friendlyName, SN_friendlyName, LN_friendlyName, OBJ_friendlyName); +// addObject(NID_localKeyID, SN_localKeyID, LN_localKeyID, OBJ_localKeyID); +// addObject(NID_x509Certificate, SN_x509Certificate, LN_x509Certificate, OBJ_x509Certificate); +// addObject(NID_sdsiCertificate, SN_sdsiCertificate, LN_sdsiCertificate, OBJ_sdsiCertificate); +// addObject(NID_x509Crl, SN_x509Crl, LN_x509Crl, OBJ_x509Crl); +// addObject(NID_pbes2, SN_pbes2, LN_pbes2, OBJ_pbes2); +// addObject(NID_pbmac1, SN_pbmac1, LN_pbmac1, OBJ_pbmac1); +// addObject(NID_hmacWithSHA1, SN_hmacWithSHA1, LN_hmacWithSHA1, OBJ_hmacWithSHA1); +// addObject(NID_id_qt_cps, SN_id_qt_cps, LN_id_qt_cps, OBJ_id_qt_cps); +// addObject(NID_id_qt_unotice, SN_id_qt_unotice, LN_id_qt_unotice, OBJ_id_qt_unotice); +// addObject(NID_rc2_64_cbc, SN_rc2_64_cbc, LN_rc2_64_cbc, OBJ_rc2_64_cbc); +// addObject(NID_SMIMECapabilities, SN_SMIMECapabilities, LN_SMIMECapabilities, OBJ_SMIMECapabilities); +// addObject(NID_pbeWithMD2AndRC2_CBC, SN_pbeWithMD2AndRC2_CBC, LN_pbeWithMD2AndRC2_CBC, OBJ_pbeWithMD2AndRC2_CBC); +// addObject(NID_pbeWithMD5AndRC2_CBC, SN_pbeWithMD5AndRC2_CBC, LN_pbeWithMD5AndRC2_CBC, OBJ_pbeWithMD5AndRC2_CBC); +// addObject(NID_pbeWithSHA1AndDES_CBC, SN_pbeWithSHA1AndDES_CBC, LN_pbeWithSHA1AndDES_CBC, OBJ_pbeWithSHA1AndDES_CBC); +// addObject(NID_ms_ext_req, SN_ms_ext_req, LN_ms_ext_req, OBJ_ms_ext_req); +// addObject(NID_ext_req, SN_ext_req, LN_ext_req, OBJ_ext_req); +// addObject(NID_name, SN_name, LN_name, OBJ_name); +// addObject(NID_dnQualifier, SN_dnQualifier, LN_dnQualifier, OBJ_dnQualifier); +// addObject(NID_id_pe, SN_id_pe, LN_id_pe, OBJ_id_pe); +// addObject(NID_id_ad, SN_id_ad, LN_id_ad, OBJ_id_ad); +// addObject(NID_info_access, SN_info_access, LN_info_access, OBJ_info_access); +// addObject(NID_ad_OCSP, SN_ad_OCSP, LN_ad_OCSP, OBJ_ad_OCSP); +// addObject(NID_ad_ca_issuers, SN_ad_ca_issuers, LN_ad_ca_issuers, OBJ_ad_ca_issuers); +// addObject(NID_OCSP_sign, SN_OCSP_sign, LN_OCSP_sign, OBJ_OCSP_sign); + +// addObject(181, "AES-192-OFB", "aes-192-ofb","2.16.840.1.101.3.4.1.23"); +// addObject(182, "AES-192-CFB", "aes-192-cfb","2.16.840.1.101.3.4.1.24"); +// addObject(183, "AES-256-EBC", "aes-256-ebc","2.16.840.1.101.3.4.1.41"); +// addObject(184, "AES-256-CBC", "aes-256-cbc","2.16.840.1.101.3.4.1.42"); +// addObject(185, "AES-256-OFB", "aes-256-ofb","2.16.840.1.101.3.4.1.43"); +// addObject(186, "AES-256-CFB", "aes-256-cfb","2.16.840.1.101.3.4.1.44"); +// } +}// ASN1Registry diff --git a/src/org/jruby/ext/openssl/impl/Attribute.java b/src/org/jruby/ext/openssl/impl/Attribute.java new file mode 100644 index 00000000000..c2528a7cdc8 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Attribute.java @@ -0,0 +1,88 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.ASN1Encodable; +import java.util.List; +import java.util.ArrayList; + +/** X509_ATTRIBUTE + * + * @author Ola Bini + */ +public class Attribute { + private int type; + private boolean single; + private List set; + + private Attribute() {} + + public static Attribute create(int nid, int atrtype, ASN1Encodable value) { + Attribute ret = new Attribute(); + + ret.type = nid; + ret.single = false; + ret.set = new ArrayList(); + ret.set.add(value); + + return ret; + } + + public int getType() { + return type; + } + + public List getSet() { + return set; + } + + public boolean isSingle() { + return this.single; + } + + @Override + public boolean equals(Object obj) { + boolean ret = this == obj; + if(!ret && (obj instanceof Attribute)) { + Attribute attr2 = (Attribute)obj; + ret = + this.type == attr2.type && + this.set.equals(attr2.set); + } + return ret; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((set == null) ? 0 : set.hashCode()); + result = prime * result + type; + return result; + } +}// Attribute diff --git a/src/org/jruby/ext/openssl/impl/BIO.java b/src/org/jruby/ext/openssl/impl/BIO.java new file mode 100644 index 00000000000..875a6025e5a --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/BIO.java @@ -0,0 +1,345 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.security.MessageDigest; +import javax.crypto.Cipher; + +/** c: BIO + * + * @author Ola Bini + */ +public class BIO { + public final static int TYPE_DESCRIPTOR = 0x0100; + public final static int TYPE_FILTER = 0x0200; + public final static int TYPE_SOURCE_SINK = 0x0400; + + public final static int TYPE_NONE = 0; + public final static int TYPE_MEM = 1 | TYPE_SOURCE_SINK; + public final static int TYPE_FILE = 2 | TYPE_SOURCE_SINK; + public final static int TYPE_FD = 4 | TYPE_SOURCE_SINK | TYPE_DESCRIPTOR; + public final static int TYPE_SOCKET = 5 | TYPE_SOURCE_SINK | TYPE_DESCRIPTOR; + public final static int TYPE_NULL = 6 | TYPE_SOURCE_SINK; + public final static int TYPE_SSL = 7 | TYPE_FILTER; + public final static int TYPE_MD = 8 | TYPE_FILTER; + public final static int TYPE_BUFFER = 9 | TYPE_FILTER; + public final static int TYPE_CIPHER = 10 | TYPE_FILTER; + public final static int TYPE_BASE64 = 11 | TYPE_FILTER; + public final static int TYPE_CONNECT = 12 | TYPE_SOURCE_SINK | TYPE_DESCRIPTOR; + public final static int TYPE_ACCEPT = 13 | TYPE_SOURCE_SINK | TYPE_DESCRIPTOR; + public final static int TYPE_PROXY_CLIENT = 14 | TYPE_FILTER; + public final static int TYPE_PROXY_SERVER = 15 | TYPE_FILTER; + public final static int TYPE_NBIO_TEST = 16 | TYPE_FILTER; + public final static int TYPE_NULL_FILTER = 17 | TYPE_FILTER; + public final static int TYPE_BER = 18 | TYPE_FILTER; + public final static int TYPE_BIO = 19 | TYPE_SOURCE_SINK; + + private static final class BIOInputStream extends InputStream { + private BIO bio; + + public BIOInputStream(BIO bio) { + this.bio = bio; + } + + @Override + public int read() throws IOException { + byte[] buffer = new byte[1]; + int read = bio.read(buffer, 0, 1); + if(read == 0) { + return -1; + } + return ((int)buffer[0])&0xFF; + } + + @Override + public int read(byte[] into) throws IOException { + return this.read(into, 0, into.length); + } + + @Override + public int read(byte[] into, int off, int len) throws IOException { + int read = bio.read(into, off, len); + if(read == 0) { + return -1; + } + return read; + } + } + + private static final class BIOOutputStream extends OutputStream { + private BIO bio; + + public BIOOutputStream(BIO bio) { + this.bio = bio; + } + + @Override + public void write(int b) throws IOException { + } + + @Override + public void write(byte[] out) throws IOException { + this.write(out, 0, out.length); + } + + @Override + public void write(byte[] out, int off, int len) throws IOException { + bio.write(out, off, len); + } + } + + public static InputStream asInputStream(BIO input) { + return new BIOInputStream(input); + } + + public static OutputStream asOutputStream(BIO output) { + return new BIOOutputStream(output); + } + + public static BIO base64Filter(BIO real) { + BIO b64 = new Base64BIOFilter(); + b64.push(real); + return b64; + } + + public static BIO mdFilter(MessageDigest md) { + return new MessageDigestBIOFilter(md); + } + + public static BIO cipherFilter(Cipher cipher) { + return new CipherBIOFilter(cipher); + } + + public static BIO fromString(String input) { + MemBIO bio = new MemBIO(); + byte[] buf = null; + try { + buf = input.getBytes("ISO8859-1"); + bio.write(buf, 0, buf.length); + } catch(Exception e) {} + return bio; + } + + /** c: BIO_new(BIO_f_buffered()) + * + */ + public static BIO buffered() { + return null; + } + + /** c: BIO_new(BIO_s_mem()) + * + */ + public static BIO mem() { + return new MemBIO(); + } + + /** c: BIO_new(BIO_s_null()) + * + */ + public static BIO nullSink() { + return new NullSinkBIO(); + } + + /** c: BIO_new_mem_buf + * + */ + public static BIO memBuf(byte[] arr) { + return memBuf(arr, 0, arr.length); + } + + /** c: BIO_new_mem_buf + * + */ + public static BIO memBuf(byte[] arr, int offset, int length) { + // TODO: create real readonly version of MemBIO. + try { + BIO bio = new MemBIO(); + bio.write(arr, offset, length); + return bio; + } catch(IOException e) { + return null; + } + } + + protected BIO nextBio; + protected BIO prevBio; + + + /** c: BIO_flush + * + */ + public void flush() throws IOException, PKCS7Exception { + } + + private final static byte[] CONTENT_TEXT; + static { + byte[] val = null; + try { + val = "Content-Type: text/plain\r\n\r\n".getBytes("ISO8859-1"); + } catch(Exception e) { + val = null; + } + CONTENT_TEXT = val; + } + + /** c: SMIME_crlf_copy + * + */ + public void crlfCopy(BIO out, int flags) throws IOException { + BIO in = this; + byte[] linebuf = new byte[SMIME.MAX_SMLEN]; + int[] len = new int[]{0}; + + if((flags & PKCS7.BINARY) > 0 ) { + while((len[0] = in.read(linebuf, 0, SMIME.MAX_SMLEN)) > 0) { + out.write(linebuf, 0, len[0]); + } + return; + } + if((flags & PKCS7.TEXT) > 0) { + out.write(CONTENT_TEXT, 0, CONTENT_TEXT.length); + } + while((len[0] = in.gets(linebuf, SMIME.MAX_SMLEN)) > 0) { + boolean eol = SMIME.stripEol(linebuf, len); + if(len[0] != 0) { + out.write(linebuf, 0, len[0]); + } + if(eol) { + out.write(SMIME.NEWLINE, 0, 2); + } + } + } + + /** c: BIO_gets + * + */ + public int gets(byte[] in, int len) throws IOException { + throw new UnsupportedOperationException("for " + this.getClass().getName()); + } + + /** c: BIO_write + * + */ + public int write(byte[] out, int offset, int len) throws IOException { + throw new UnsupportedOperationException("for " + this.getClass().getName()); + } + + /** c: BIO_read + * + */ + public int read(byte[] into, int offset, int len) throws IOException { + throw new UnsupportedOperationException("for " + this.getClass().getName()); + } + + /** c: BIO_set_mem_eof_return + * + */ + public void setMemEofReturn(int value) { + throw new UnsupportedOperationException("for " + this.getClass().getName()); + } + + /** c: BIO_push + * + */ + public BIO push(BIO bio) { + BIO lb = this; + while(lb.nextBio != null) { + lb = lb.nextBio; + } + if(bio != null) { + bio.prevBio = lb; + } + lb.nextBio = bio; + return this; + } + + /** c: BIO_pop + * + */ + public BIO pop() { + BIO ret = this.nextBio; + if(this.prevBio != null) { + this.prevBio.nextBio = this.nextBio; + } + if(this.nextBio != null) { + this.nextBio.prevBio = this.prevBio; + } + this.nextBio = null; + this.prevBio = null; + return ret; + } + + /** c: BIO_find_type + * + */ + public BIO findType(int type) { + int mask = type & 0xFF; + BIO bio = this; + do { + int mt = bio.getType(); + if(mask == 0) { + if((mt & type) != 0) { + return bio; + } + } else if(mt == type) { + return bio; + } + bio = bio.nextBio; + } while(bio != null); + + return null; + } + + /** c: BIO_next + * + */ + public BIO next() { + return this.nextBio; + } + + public int getType() { + return TYPE_BIO; + } + + /** c: BIO_reset + * + */ + public void reset() { + throw new UnsupportedOperationException(); + } + + @Override + public String toString() { + String[] names = getClass().getName().split("\\."); + return "#"; + } +}// BIO diff --git a/src/org/jruby/ext/openssl/impl/BIOFilter.java b/src/org/jruby/ext/openssl/impl/BIOFilter.java new file mode 100644 index 00000000000..be9b58f219d --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/BIOFilter.java @@ -0,0 +1,38 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** + * + * @author Ola Bini + */ +public abstract class BIOFilter extends BIO { + public int getType() { + return TYPE_FILTER; + } +}// BIOFilter diff --git a/src/org/jruby/ext/openssl/impl/Base64.java b/src/org/jruby/ext/openssl/impl/Base64.java new file mode 100644 index 00000000000..ecf596fb8f4 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Base64.java @@ -0,0 +1,2066 @@ +package org.jruby.ext.openssl.impl; +@SuppressWarnings("rawtypes") + +/** + *

Encodes and decodes to and from Base64 notation.

+ *

Homepage: http://iharder.net/base64.

+ * + *

Example:

+ * + * String encoded = Base64.encode( myByteArray ); + *
+ * byte[] myByteArray = Base64.decode( encoded ); + * + *

The options parameter, which appears in a few places, is used to pass + * several pieces of information to the encoder. In the "higher level" methods such as + * encodeBytes( bytes, options ) the options parameter can be used to indicate such + * things as first gzipping the bytes before encoding them, not inserting linefeeds, + * and encoding using the URL-safe and Ordered dialects.

+ * + *

Note, according to RFC3548, + * Section 2.1, implementations should not add line feeds unless explicitly told + * to do so. I've got Base64 set to this behavior now, although earlier versions + * broke lines by default.

+ * + *

The constants defined in Base64 can be OR-ed together to combine options, so you + * might make a call like this:

+ * + * String encoded = Base64.encodeBytes( mybytes, Base64.GZIP | Base64.DO_BREAK_LINES ); + *

to compress the data before encoding it and then making the output have newline characters.

+ *

Also...

+ * String encoded = Base64.encodeBytes( crazyString.getBytes() ); + * + * + * + *

+ * Change Log: + *

+ *
    + *
  • v2.3.7 - Fixed subtle bug when base 64 input stream contained the + * value 01111111, which is an invalid base 64 character but should not + * throw an ArrayIndexOutOfBoundsException either. Led to discovery of + * mishandling (or potential for better handling) of other bad input + * characters. You should now get an IOException if you try decoding + * something that has bad characters in it.
  • + *
  • v2.3.6 - Fixed bug when breaking lines and the final byte of the encoded + * string ended in the last column; the buffer was not properly shrunk and + * contained an extra (null) byte that made it into the string.
  • + *
  • v2.3.5 - Fixed bug in {@link #encodeFromFile} where estimated buffer size + * was wrong for files of size 31, 34, and 37 bytes.
  • + *
  • v2.3.4 - Fixed bug when working with gzipped streams whereby flushing + * the Base64.OutputStream closed the Base64 encoding (by padding with equals + * signs) too soon. Also added an option to suppress the automatic decoding + * of gzipped streams. Also added experimental support for specifying a + * class loader when using the + * {@link #decodeToObject(java.lang.String, int, java.lang.ClassLoader)} + * method.
  • + *
  • v2.3.3 - Changed default char encoding to US-ASCII which reduces the internal Java + * footprint with its CharEncoders and so forth. Fixed some javadocs that were + * inconsistent. Removed imports and specified things like java.io.IOException + * explicitly inline.
  • + *
  • v2.3.2 - Reduced memory footprint! Finally refined the "guessing" of how big the + * final encoded data will be so that the code doesn't have to create two output + * arrays: an oversized initial one and then a final, exact-sized one. Big win + * when using the {@link #encodeBytesToBytes(byte[])} family of methods (and not + * using the gzip options which uses a different mechanism with streams and stuff).
  • + *
  • v2.3.1 - Added {@link #encodeBytesToBytes(byte[], int, int, int)} and some + * similar helper methods to be more efficient with memory by not returning a + * String but just a byte array.
  • + *
  • v2.3 - This is not a drop-in replacement! This is two years of comments + * and bug fixes queued up and finally executed. Thanks to everyone who sent + * me stuff, and I'm sorry I wasn't able to distribute your fixes to everyone else. + * Much bad coding was cleaned up including throwing exceptions where necessary + * instead of returning null values or something similar. Here are some changes + * that may affect you: + *
      + *
    • Does not break lines, by default. This is to keep in compliance with + * RFC3548.
    • + *
    • Throws exceptions instead of returning null values. Because some operations + * (especially those that may permit the GZIP option) use IO streams, there + * is a possiblity of an java.io.IOException being thrown. After some discussion and + * thought, I've changed the behavior of the methods to throw java.io.IOExceptions + * rather than return null if ever there's an error. I think this is more + * appropriate, though it will require some changes to your code. Sorry, + * it should have been done this way to begin with.
    • + *
    • Removed all references to System.out, System.err, and the like. + * Shame on me. All I can say is sorry they were ever there.
    • + *
    • Throws NullPointerExceptions and IllegalArgumentExceptions as needed + * such as when passed arrays are null or offsets are invalid.
    • + *
    • Cleaned up as much javadoc as I could to avoid any javadoc warnings. + * This was especially annoying before for people who were thorough in their + * own projects and then had gobs of javadoc warnings on this file.
    • + *
    + *
  • v2.2.1 - Fixed bug using URL_SAFE and ORDERED encodings. Fixed bug + * when using very small files (~< 40 bytes).
  • + *
  • v2.2 - Added some helper methods for encoding/decoding directly from + * one file to the next. Also added a main() method to support command line + * encoding/decoding from one file to the next. Also added these Base64 dialects: + *
      + *
    1. The default is RFC3548 format.
    2. + *
    3. Calling Base64.setFormat(Base64.BASE64_FORMAT.URLSAFE_FORMAT) generates + * URL and file name friendly format as described in Section 4 of RFC3548. + * http://www.faqs.org/rfcs/rfc3548.html
    4. + *
    5. Calling Base64.setFormat(Base64.BASE64_FORMAT.ORDERED_FORMAT) generates + * URL and file name friendly format that preserves lexical ordering as described + * in http://www.faqs.org/qa/rfcc-1940.html
    6. + *
    + * Special thanks to Jim Kellerman at http://www.powerset.com/ + * for contributing the new Base64 dialects. + *
  • + * + *
  • v2.1 - Cleaned up javadoc comments and unused variables and methods. Added + * some convenience methods for reading and writing to and from files.
  • + *
  • v2.0.2 - Now specifies UTF-8 encoding in places where the code fails on systems + * with other encodings (like EBCDIC).
  • + *
  • v2.0.1 - Fixed an error when decoding a single byte, that is, when the + * encoded data was a single byte.
  • + *
  • v2.0 - I got rid of methods that used booleans to set options. + * Now everything is more consolidated and cleaner. The code now detects + * when data that's being decoded is gzip-compressed and will decompress it + * automatically. Generally things are cleaner. You'll probably have to + * change some method calls that you were making to support the new + * options format (ints that you "OR" together).
  • + *
  • v1.5.1 - Fixed bug when decompressing and decoding to a + * byte[] using decode( String s, boolean gzipCompressed ). + * Added the ability to "suspend" encoding in the Output Stream so + * you can turn on and off the encoding if you need to embed base64 + * data in an otherwise "normal" stream (like an XML file).
  • + *
  • v1.5 - Output stream pases on flush() command but doesn't do anything itself. + * This helps when using GZIP streams. + * Added the ability to GZip-compress objects before encoding them.
  • + *
  • v1.4 - Added helper methods to read/write files.
  • + *
  • v1.3.6 - Fixed OutputStream.flush() so that 'position' is reset.
  • + *
  • v1.3.5 - Added flag to turn on and off line breaks. Fixed bug in input stream + * where last buffer being read, if not completely full, was not returned.
  • + *
  • v1.3.4 - Fixed when "improperly padded stream" error was thrown at the wrong time.
  • + *
  • v1.3.3 - Fixed I/O streams which were totally messed up.
  • + *
+ * + *

+ * I am placing this code in the Public Domain. Do with it as you will. + * This software comes with no guarantees or warranties but with + * plenty of well-wishing instead! + * Please visit http://iharder.net/base64 + * periodically to check for updates or to contribute improvements. + *

+ * + * @author Robert Harder + * @author rob@iharder.net + * @version 2.3.7 + */ +public class Base64 +{ + +/* ******** P U B L I C F I E L D S ******** */ + + + /** No options specified. Value is zero. */ + public final static int NO_OPTIONS = 0; + + /** Specify encoding in first bit. Value is one. */ + public final static int ENCODE = 1; + + + /** Specify decoding in first bit. Value is zero. */ + public final static int DECODE = 0; + + + /** Specify that data should be gzip-compressed in second bit. Value is two. */ + public final static int GZIP = 2; + + /** Specify that gzipped data should not be automatically gunzipped. */ + public final static int DONT_GUNZIP = 4; + + + /** Do break lines when encoding. Value is 8. */ + public final static int DO_BREAK_LINES = 8; + + /** + * Encode using Base64-like encoding that is URL- and Filename-safe as described + * in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * It is important to note that data encoded this way is not officially valid Base64, + * or at the very least should not be called Base64 without also specifying that is + * was encoded using the URL- and Filename-safe dialect. + */ + public final static int URL_SAFE = 16; + + + /** + * Encode using the special "ordered" dialect of Base64 described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + public final static int ORDERED = 32; + + +/* ******** P R I V A T E F I E L D S ******** */ + + + /** Maximum line length (76) of Base64 output. */ + private final static int MAX_LINE_LENGTH = 76; + + + /** The equals sign (=) as a byte. */ + private final static byte EQUALS_SIGN = (byte)'='; + + + /** The new line character (\n) as a byte. */ + private final static byte NEW_LINE = (byte)'\n'; + + + /** Preferred encoding. */ + private final static String PREFERRED_ENCODING = "US-ASCII"; + + + private final static byte WHITE_SPACE_ENC = -5; // Indicates white space in encoding + private final static byte EQUALS_SIGN_ENC = -1; // Indicates equals sign in encoding + + +/* ******** S T A N D A R D B A S E 6 4 A L P H A B E T ******** */ + + /** The 64 valid Base64 values. */ + /* Host platform me be something funny like EBCDIC, so we hardcode these values. */ + private final static byte[] _STANDARD_ALPHABET = { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'+', (byte)'/' + }; + + + /** + * Translates a Base64 value to either its 6-bit reconstruction value + * or a negative number indicating some other meaning. + **/ + private final static byte[] _STANDARD_DECODABET = { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + 62, // Plus sign at decimal 43 + -9,-9,-9, // Decimal 44 - 46 + 63, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9,-9,-9, // Decimal 91 - 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9,-9 // Decimal 123 - 127 + ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 + }; + + +/* ******** U R L S A F E B A S E 6 4 A L P H A B E T ******** */ + + /** + * Used in the URL- and Filename-safe dialect described in Section 4 of RFC3548: + * http://www.faqs.org/rfcs/rfc3548.html. + * Notice that the last two bytes become "hyphen" and "underscore" instead of "plus" and "slash." + */ + private final static byte[] _URL_SAFE_ALPHABET = { + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', (byte)'5', + (byte)'6', (byte)'7', (byte)'8', (byte)'9', (byte)'-', (byte)'_' + }; + + /** + * Used in decoding URL- and Filename-safe dialects of Base64. + */ + private final static byte[] _URL_SAFE_DECODABET = { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 62, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 52,53,54,55,56,57,58,59,60,61, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 0,1,2,3,4,5,6,7,8,9,10,11,12,13, // Letters 'A' through 'N' + 14,15,16,17,18,19,20,21,22,23,24,25, // Letters 'O' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 63, // Underscore at decimal 95 + -9, // Decimal 96 + 26,27,28,29,30,31,32,33,34,35,36,37,38, // Letters 'a' through 'm' + 39,40,41,42,43,44,45,46,47,48,49,50,51, // Letters 'n' through 'z' + -9,-9,-9,-9,-9 // Decimal 123 - 127 + ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 + }; + + + +/* ******** O R D E R E D B A S E 6 4 A L P H A B E T ******** */ + + /** + * I don't get the point of this technique, but someone requested it, + * and it is described here: + * http://www.faqs.org/qa/rfcc-1940.html. + */ + private final static byte[] _ORDERED_ALPHABET = { + (byte)'-', + (byte)'0', (byte)'1', (byte)'2', (byte)'3', (byte)'4', + (byte)'5', (byte)'6', (byte)'7', (byte)'8', (byte)'9', + (byte)'A', (byte)'B', (byte)'C', (byte)'D', (byte)'E', (byte)'F', (byte)'G', + (byte)'H', (byte)'I', (byte)'J', (byte)'K', (byte)'L', (byte)'M', (byte)'N', + (byte)'O', (byte)'P', (byte)'Q', (byte)'R', (byte)'S', (byte)'T', (byte)'U', + (byte)'V', (byte)'W', (byte)'X', (byte)'Y', (byte)'Z', + (byte)'_', + (byte)'a', (byte)'b', (byte)'c', (byte)'d', (byte)'e', (byte)'f', (byte)'g', + (byte)'h', (byte)'i', (byte)'j', (byte)'k', (byte)'l', (byte)'m', (byte)'n', + (byte)'o', (byte)'p', (byte)'q', (byte)'r', (byte)'s', (byte)'t', (byte)'u', + (byte)'v', (byte)'w', (byte)'x', (byte)'y', (byte)'z' + }; + + /** + * Used in decoding the "ordered" dialect of Base64. + */ + private final static byte[] _ORDERED_DECODABET = { + -9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 0 - 8 + -5,-5, // Whitespace: Tab and Linefeed + -9,-9, // Decimal 11 - 12 + -5, // Whitespace: Carriage Return + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 14 - 26 + -9,-9,-9,-9,-9, // Decimal 27 - 31 + -5, // Whitespace: Space + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 33 - 42 + -9, // Plus sign at decimal 43 + -9, // Decimal 44 + 0, // Minus sign at decimal 45 + -9, // Decimal 46 + -9, // Slash at decimal 47 + 1,2,3,4,5,6,7,8,9,10, // Numbers zero through nine + -9,-9,-9, // Decimal 58 - 60 + -1, // Equals sign at decimal 61 + -9,-9,-9, // Decimal 62 - 64 + 11,12,13,14,15,16,17,18,19,20,21,22,23, // Letters 'A' through 'M' + 24,25,26,27,28,29,30,31,32,33,34,35,36, // Letters 'N' through 'Z' + -9,-9,-9,-9, // Decimal 91 - 94 + 37, // Underscore at decimal 95 + -9, // Decimal 96 + 38,39,40,41,42,43,44,45,46,47,48,49,50, // Letters 'a' through 'm' + 51,52,53,54,55,56,57,58,59,60,61,62,63, // Letters 'n' through 'z' + -9,-9,-9,-9,-9 // Decimal 123 - 127 + ,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 128 - 139 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 140 - 152 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 153 - 165 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 166 - 178 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 179 - 191 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 192 - 204 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 205 - 217 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 218 - 230 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9, // Decimal 231 - 243 + -9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9,-9 // Decimal 244 - 255 + }; + + +/* ******** D E T E R M I N E W H I C H A L H A B E T ******** */ + + + /** + * Returns one of the _SOMETHING_ALPHABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URLSAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + */ + private final static byte[] getAlphabet( int options ) { + if ((options & URL_SAFE) == URL_SAFE) { + return _URL_SAFE_ALPHABET; + } else if ((options & ORDERED) == ORDERED) { + return _ORDERED_ALPHABET; + } else { + return _STANDARD_ALPHABET; + } + } // end getAlphabet + + + /** + * Returns one of the _SOMETHING_DECODABET byte arrays depending on + * the options specified. + * It's possible, though silly, to specify ORDERED and URL_SAFE + * in which case one of them will be picked, though there is + * no guarantee as to which one will be picked. + */ + private final static byte[] getDecodabet( int options ) { + if( (options & URL_SAFE) == URL_SAFE) { + return _URL_SAFE_DECODABET; + } else if ((options & ORDERED) == ORDERED) { + return _ORDERED_DECODABET; + } else { + return _STANDARD_DECODABET; + } + } // end getAlphabet + + + + /** Defeats instantiation. */ + private Base64(){} + + + + +/* ******** E N C O D I N G M E T H O D S ******** */ + + + /** + * Encodes up to the first three bytes of array threeBytes + * and returns a four-byte array in Base64 notation. + * The actual number of significant bytes in your array is + * given by numSigBytes. + * The array threeBytes needs only be as big as + * numSigBytes. + * Code can reuse a byte array by passing a four-byte array as b4. + * + * @param b4 A reusable byte array to reduce array instantiation + * @param threeBytes the array to convert + * @param numSigBytes the number of significant bytes in your array + * @return four byte array in Base64 notation. + * @since 1.5.1 + */ + private static byte[] encode3to4( byte[] b4, byte[] threeBytes, int numSigBytes, int options ) { + encode3to4( threeBytes, 0, numSigBytes, b4, 0, options ); + return b4; + } // end encode3to4 + + + /** + *

Encodes up to three bytes of the array source + * and writes the resulting four Base64 bytes to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accomodate srcOffset + 3 for + * the source array or destOffset + 4 for + * the destination array. + * The actual number of significant bytes in your array is + * given by numSigBytes.

+ *

This is the lowest level of the encoding methods with + * all possible parameters.

+ * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param numSigBytes the number of significant bytes in your array + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @return the destination array + * @since 1.3 + */ + private static byte[] encode3to4( + byte[] source, int srcOffset, int numSigBytes, + byte[] destination, int destOffset, int options ) { + + byte[] ALPHABET = getAlphabet( options ); + + // 1 2 3 + // 01234567890123456789012345678901 Bit position + // --------000000001111111122222222 Array position from threeBytes + // --------| || || || | Six bit groups to index ALPHABET + // >>18 >>12 >> 6 >> 0 Right shift necessary + // 0x3f 0x3f 0x3f Additional AND + + // Create buffer with zero-padding if there are only one or two + // significant bytes passed in the array. + // We have to shift left 24 in order to flush out the 1's that appear + // when Java treats a value as negative that is cast from a byte to an int. + int inBuff = ( numSigBytes > 0 ? ((source[ srcOffset ] << 24) >>> 8) : 0 ) + | ( numSigBytes > 1 ? ((source[ srcOffset + 1 ] << 24) >>> 16) : 0 ) + | ( numSigBytes > 2 ? ((source[ srcOffset + 2 ] << 24) >>> 24) : 0 ); + + switch( numSigBytes ) + { + case 3: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = ALPHABET[ (inBuff ) & 0x3f ]; + return destination; + + case 2: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = ALPHABET[ (inBuff >>> 6) & 0x3f ]; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + case 1: + destination[ destOffset ] = ALPHABET[ (inBuff >>> 18) ]; + destination[ destOffset + 1 ] = ALPHABET[ (inBuff >>> 12) & 0x3f ]; + destination[ destOffset + 2 ] = EQUALS_SIGN; + destination[ destOffset + 3 ] = EQUALS_SIGN; + return destination; + + default: + return destination; + } // end switch + } // end encode3to4 + + + + /** + * Performs Base64 encoding on the raw ByteBuffer, + * writing it to the encoded ByteBuffer. + * This is an experimental feature. Currently it does not + * pass along any options (such as {@link #DO_BREAK_LINES} + * or {@link #GZIP}. + * + * @param raw input buffer + * @param encoded output buffer + * @since 2.3 + */ + public static void encode( java.nio.ByteBuffer raw, java.nio.ByteBuffer encoded ){ + byte[] raw3 = new byte[3]; + byte[] enc4 = new byte[4]; + + while( raw.hasRemaining() ){ + int rem = Math.min(3,raw.remaining()); + raw.get(raw3,0,rem); + Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS ); + encoded.put(enc4); + } // end input remaining + } + + + /** + * Performs Base64 encoding on the raw ByteBuffer, + * writing it to the encoded CharBuffer. + * This is an experimental feature. Currently it does not + * pass along any options (such as {@link #DO_BREAK_LINES} + * or {@link #GZIP}. + * + * @param raw input buffer + * @param encoded output buffer + * @since 2.3 + */ + public static void encode( java.nio.ByteBuffer raw, java.nio.CharBuffer encoded ){ + byte[] raw3 = new byte[3]; + byte[] enc4 = new byte[4]; + + while( raw.hasRemaining() ){ + int rem = Math.min(3,raw.remaining()); + raw.get(raw3,0,rem); + Base64.encode3to4(enc4, raw3, rem, Base64.NO_OPTIONS ); + for( int i = 0; i < 4; i++ ){ + encoded.put( (char)(enc4[i] & 0xFF) ); + } + } // end input remaining + } + + + + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. + * + *

As of v 2.3, if the object + * cannot be serialized or there is another error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned a null value, but + * in retrospect that's a pretty poor way to handle it.

+ * + * The object is not GZip-compressed before being encoded. + * + * @param serializableObject The object to encode + * @return The Base64-encoded object + * @throws java.io.IOException if there is an error + * @throws NullPointerException if serializedObject is null + * @since 1.4 + */ + public static String encodeObject( java.io.Serializable serializableObject ) + throws java.io.IOException { + return encodeObject( serializableObject, NO_OPTIONS ); + } // end encodeObject + + + + /** + * Serializes an object and returns the Base64-encoded + * version of that serialized object. + * + *

As of v 2.3, if the object + * cannot be serialized or there is another error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned a null value, but + * in retrospect that's a pretty poor way to handle it.

+ * + * The object is not GZip-compressed before being encoded. + *

+ * Example options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DO_BREAK_LINES: break lines at 76 characters
+     * 
+ *

+ * Example: encodeObject( myObj, Base64.GZIP ) or + *

+ * Example: encodeObject( myObj, Base64.GZIP | Base64.DO_BREAK_LINES ) + * + * @param serializableObject The object to encode + * @param options Specified options + * @return The Base64-encoded object + * @see Base64#GZIP + * @see Base64#DO_BREAK_LINES + * @throws java.io.IOException if there is an error + * @since 2.0 + */ + public static String encodeObject( java.io.Serializable serializableObject, int options ) + throws java.io.IOException { + + if( serializableObject == null ){ + throw new NullPointerException( "Cannot serialize a null object." ); + } // end if: null + + // Streams + java.io.ByteArrayOutputStream baos = null; + java.io.OutputStream b64os = null; + java.util.zip.GZIPOutputStream gzos = null; + java.io.ObjectOutputStream oos = null; + + + try { + // ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream + baos = new java.io.ByteArrayOutputStream(); + b64os = new Base64.OutputStream( baos, ENCODE | options ); + if( (options & GZIP) != 0 ){ + // Gzip + gzos = new java.util.zip.GZIPOutputStream(b64os); + oos = new java.io.ObjectOutputStream( gzos ); + } else { + // Not gzipped + oos = new java.io.ObjectOutputStream( b64os ); + } + oos.writeObject( serializableObject ); + } // end try + catch( java.io.IOException e ) { + // Catch it and then throw it immediately so that + // the finally{} block is called for cleanup. + throw e; + } // end catch + finally { + try{ oos.close(); } catch( Exception e ){} + try{ gzos.close(); } catch( Exception e ){} + try{ b64os.close(); } catch( Exception e ){} + try{ baos.close(); } catch( Exception e ){} + } // end finally + + // Return value according to relevant encoding. + try { + return new String( baos.toByteArray(), PREFERRED_ENCODING ); + } // end try + catch (java.io.UnsupportedEncodingException uue){ + // Fall back to some Java default + return new String( baos.toByteArray() ); + } // end catch + + } // end encode + + + + /** + * Encodes a byte array into Base64 notation. + * Does not GZip-compress data. + * + * @param source The data to convert + * @return The data in Base64-encoded form + * @throws NullPointerException if source array is null + * @since 1.4 + */ + public static String encodeBytes( byte[] source ) { + // Since we're not going to have the GZIP encoding turned on, + // we're not going to have an java.io.IOException thrown, so + // we should not force the user to have to catch it. + String encoded = null; + try { + encoded = encodeBytes(source, 0, source.length, NO_OPTIONS); + } catch (java.io.IOException ex) { + assert false : ex.getMessage(); + } // end catch + assert encoded != null; + return encoded; + } // end encodeBytes + + + + /** + * Encodes a byte array into Base64 notation. + *

+ * Example options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DO_BREAK_LINES: break lines at 76 characters
+     *     Note: Technically, this makes your encoding non-compliant.
+     * 
+ *

+ * Example: encodeBytes( myData, Base64.GZIP ) or + *

+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) + * + * + *

As of v 2.3, if there is an error with the GZIP stream, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned a null value, but + * in retrospect that's a pretty poor way to handle it.

+ * + * + * @param source The data to convert + * @param options Specified options + * @return The Base64-encoded data as a String + * @see Base64#GZIP + * @see Base64#DO_BREAK_LINES + * @throws java.io.IOException if there is an error + * @throws NullPointerException if source array is null + * @since 2.0 + */ + public static String encodeBytes( byte[] source, int options ) throws java.io.IOException { + return encodeBytes( source, 0, source.length, options ); + } // end encodeBytes + + + /** + * Encodes a byte array into Base64 notation. + * Does not GZip-compress data. + * + *

As of v 2.3, if there is an error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned a null value, but + * in retrospect that's a pretty poor way to handle it.

+ * + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @return The Base64-encoded data as a String + * @throws NullPointerException if source array is null + * @throws IllegalArgumentException if source array, offset, or length are invalid + * @since 1.4 + */ + public static String encodeBytes( byte[] source, int off, int len ) { + // Since we're not going to have the GZIP encoding turned on, + // we're not going to have an java.io.IOException thrown, so + // we should not force the user to have to catch it. + String encoded = null; + try { + encoded = encodeBytes( source, off, len, NO_OPTIONS ); + } catch (java.io.IOException ex) { + assert false : ex.getMessage(); + } // end catch + assert encoded != null; + return encoded; + } // end encodeBytes + + + + /** + * Encodes a byte array into Base64 notation. + *

+ * Example options:

+     *   GZIP: gzip-compresses object before encoding it.
+     *   DO_BREAK_LINES: break lines at 76 characters
+     *     Note: Technically, this makes your encoding non-compliant.
+     * 
+ *

+ * Example: encodeBytes( myData, Base64.GZIP ) or + *

+ * Example: encodeBytes( myData, Base64.GZIP | Base64.DO_BREAK_LINES ) + * + * + *

As of v 2.3, if there is an error with the GZIP stream, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned a null value, but + * in retrospect that's a pretty poor way to handle it.

+ * + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @param options Specified options + * @return The Base64-encoded data as a String + * @see Base64#GZIP + * @see Base64#DO_BREAK_LINES + * @throws java.io.IOException if there is an error + * @throws NullPointerException if source array is null + * @throws IllegalArgumentException if source array, offset, or length are invalid + * @since 2.0 + */ + public static String encodeBytes( byte[] source, int off, int len, int options ) throws java.io.IOException { + byte[] encoded = encodeBytesToBytes( source, off, len, options ); + + // Return value according to relevant encoding. + try { + return new String( encoded, PREFERRED_ENCODING ); + } // end try + catch (java.io.UnsupportedEncodingException uue) { + return new String( encoded ); + } // end catch + + } // end encodeBytes + + + + + /** + * Similar to {@link #encodeBytes(byte[])} but returns + * a byte array instead of instantiating a String. This is more efficient + * if you're working with I/O streams and have large data sets to encode. + * + * + * @param source The data to convert + * @return The Base64-encoded data as a byte[] (of ASCII characters) + * @throws NullPointerException if source array is null + * @since 2.3.1 + */ + public static byte[] encodeBytesToBytes( byte[] source ) { + byte[] encoded = null; + try { + encoded = encodeBytesToBytes( source, 0, source.length, Base64.NO_OPTIONS ); + } catch( java.io.IOException ex ) { + assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); + } + return encoded; + } + + + /** + * Similar to {@link #encodeBytes(byte[], int, int, int)} but returns + * a byte array instead of instantiating a String. This is more efficient + * if you're working with I/O streams and have large data sets to encode. + * + * + * @param source The data to convert + * @param off Offset in array where conversion should begin + * @param len Length of data to convert + * @param options Specified options + * @return The Base64-encoded data as a String + * @see Base64#GZIP + * @see Base64#DO_BREAK_LINES + * @throws java.io.IOException if there is an error + * @throws NullPointerException if source array is null + * @throws IllegalArgumentException if source array, offset, or length are invalid + * @since 2.3.1 + */ + public static byte[] encodeBytesToBytes( byte[] source, int off, int len, int options ) throws java.io.IOException { + + if( source == null ){ + throw new NullPointerException( "Cannot serialize a null array." ); + } // end if: null + + if( off < 0 ){ + throw new IllegalArgumentException( "Cannot have negative offset: " + off ); + } // end if: off < 0 + + if( len < 0 ){ + throw new IllegalArgumentException( "Cannot have length offset: " + len ); + } // end if: len < 0 + + if( off + len > source.length ){ + throw new IllegalArgumentException( + String.format( "Cannot have offset of %d and length of %d with array of length %d", off,len,source.length)); + } // end if: off < 0 + + + + // Compress? + if( (options & GZIP) != 0 ) { + java.io.ByteArrayOutputStream baos = null; + java.util.zip.GZIPOutputStream gzos = null; + Base64.OutputStream b64os = null; + + try { + // GZip -> Base64 -> ByteArray + baos = new java.io.ByteArrayOutputStream(); + b64os = new Base64.OutputStream( baos, ENCODE | options ); + gzos = new java.util.zip.GZIPOutputStream( b64os ); + + gzos.write( source, off, len ); + gzos.close(); + } // end try + catch( java.io.IOException e ) { + // Catch it and then throw it immediately so that + // the finally{} block is called for cleanup. + throw e; + } // end catch + finally { + try{ gzos.close(); } catch( Exception e ){} + try{ b64os.close(); } catch( Exception e ){} + try{ baos.close(); } catch( Exception e ){} + } // end finally + + return baos.toByteArray(); + } // end if: compress + + // Else, don't compress. Better not to use streams at all then. + else { + boolean breakLines = (options & DO_BREAK_LINES) != 0; + + //int len43 = len * 4 / 3; + //byte[] outBuff = new byte[ ( len43 ) // Main 4:3 + // + ( (len % 3) > 0 ? 4 : 0 ) // Account for padding + // + (breakLines ? ( len43 / MAX_LINE_LENGTH ) : 0) ]; // New lines + // Try to determine more precisely how big the array needs to be. + // If we get it right, we don't have to do an array copy, and + // we save a bunch of memory. + int encLen = ( len / 3 ) * 4 + ( len % 3 > 0 ? 4 : 0 ); // Bytes needed for actual encoding + if( breakLines ){ + encLen += encLen / MAX_LINE_LENGTH; // Plus extra newline characters + } + byte[] outBuff = new byte[ encLen ]; + + + int d = 0; + int e = 0; + int len2 = len - 2; + int lineLength = 0; + for( ; d < len2; d+=3, e+=4 ) { + encode3to4( source, d+off, 3, outBuff, e, options ); + + lineLength += 4; + if( breakLines && lineLength >= MAX_LINE_LENGTH ) + { + outBuff[e+4] = NEW_LINE; + e++; + lineLength = 0; + } // end if: end of line + } // en dfor: each piece of array + + if( d < len ) { + encode3to4( source, d+off, len - d, outBuff, e, options ); + e += 4; + } // end if: some padding needed + + + // Only resize array if we didn't guess it right. + if( e <= outBuff.length - 1 ){ + // If breaking lines and the last byte falls right at + // the line length (76 bytes per line), there will be + // one extra byte, and the array will need to be resized. + // Not too bad of an estimate on array size, I'd say. + byte[] finalOut = new byte[e]; + System.arraycopy(outBuff,0, finalOut,0,e); + //System.err.println("Having to resize array from " + outBuff.length + " to " + e ); + return finalOut; + } else { + //System.err.println("No need to resize array."); + return outBuff; + } + + } // end else: don't compress + + } // end encodeBytesToBytes + + + + + +/* ******** D E C O D I N G M E T H O D S ******** */ + + + /** + * Decodes four bytes from array source + * and writes the resulting bytes (up to three of them) + * to destination. + * The source and destination arrays can be manipulated + * anywhere along their length by specifying + * srcOffset and destOffset. + * This method does not check to make sure your arrays + * are large enough to accomodate srcOffset + 4 for + * the source array or destOffset + 3 for + * the destination array. + * This method returns the actual number of bytes that + * were converted from the Base64 encoding. + *

This is the lowest level of the decoding methods with + * all possible parameters.

+ * + * + * @param source the array to convert + * @param srcOffset the index where conversion begins + * @param destination the array to hold the conversion + * @param destOffset the index where output will be put + * @param options alphabet type is pulled from this (standard, url-safe, ordered) + * @return the number of decoded bytes converted + * @throws NullPointerException if source or destination arrays are null + * @throws IllegalArgumentException if srcOffset or destOffset are invalid + * or there is not enough room in the array. + * @since 1.3 + */ + private static int decode4to3( + byte[] source, int srcOffset, + byte[] destination, int destOffset, int options ) { + + // Lots of error checking and exception throwing + if( source == null ){ + throw new NullPointerException( "Source array was null." ); + } // end if + if( destination == null ){ + throw new NullPointerException( "Destination array was null." ); + } // end if + if( srcOffset < 0 || srcOffset + 3 >= source.length ){ + throw new IllegalArgumentException( String.format( + "Source array with length %d cannot have offset of %d and still process four bytes.", source.length, srcOffset ) ); + } // end if + if( destOffset < 0 || destOffset +2 >= destination.length ){ + throw new IllegalArgumentException( String.format( + "Destination array with length %d cannot have offset of %d and still store three bytes.", destination.length, destOffset ) ); + } // end if + + + byte[] DECODABET = getDecodabet( options ); + + // Example: Dk== + if( source[ srcOffset + 2] == EQUALS_SIGN ) { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1] ] << 24 ) >>> 12 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1] ] & 0xFF ) << 12 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + return 1; + } + + // Example: DkL= + else if( source[ srcOffset + 3 ] == EQUALS_SIGN ) { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6 ); + + destination[ destOffset ] = (byte)( outBuff >>> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >>> 8 ); + return 2; + } + + // Example: DkLE + else { + // Two ways to do the same thing. Don't know which way I like best. + //int outBuff = ( ( DECODABET[ source[ srcOffset ] ] << 24 ) >>> 6 ) + // | ( ( DECODABET[ source[ srcOffset + 1 ] ] << 24 ) >>> 12 ) + // | ( ( DECODABET[ source[ srcOffset + 2 ] ] << 24 ) >>> 18 ) + // | ( ( DECODABET[ source[ srcOffset + 3 ] ] << 24 ) >>> 24 ); + int outBuff = ( ( DECODABET[ source[ srcOffset ] ] & 0xFF ) << 18 ) + | ( ( DECODABET[ source[ srcOffset + 1 ] ] & 0xFF ) << 12 ) + | ( ( DECODABET[ source[ srcOffset + 2 ] ] & 0xFF ) << 6) + | ( ( DECODABET[ source[ srcOffset + 3 ] ] & 0xFF ) ); + + + destination[ destOffset ] = (byte)( outBuff >> 16 ); + destination[ destOffset + 1 ] = (byte)( outBuff >> 8 ); + destination[ destOffset + 2 ] = (byte)( outBuff ); + + return 3; + } + } // end decodeToBytes + + + + + + /** + * Low-level access to decoding ASCII characters in + * the form of a byte array. Ignores GUNZIP option, if + * it's set. This is not generally a recommended method, + * although it is used internally as part of the decoding process. + * Special case: if len = 0, an empty array is returned. Still, + * if you need more speed and reduced memory footprint (and aren't + * gzipping), consider this method. + * + * @param source The Base64 encoded data + * @return decoded data + * @since 2.3.1 + */ + public static byte[] decode( byte[] source ) + throws java.io.IOException { + byte[] decoded = null; +// try { + decoded = decode( source, 0, source.length, Base64.NO_OPTIONS ); +// } catch( java.io.IOException ex ) { +// assert false : "IOExceptions only come from GZipping, which is turned off: " + ex.getMessage(); +// } + return decoded; + } + + + + /** + * Low-level access to decoding ASCII characters in + * the form of a byte array. Ignores GUNZIP option, if + * it's set. This is not generally a recommended method, + * although it is used internally as part of the decoding process. + * Special case: if len = 0, an empty array is returned. Still, + * if you need more speed and reduced memory footprint (and aren't + * gzipping), consider this method. + * + * @param source The Base64 encoded data + * @param off The offset of where to begin decoding + * @param len The length of characters to decode + * @param options Can specify options such as alphabet type to use + * @return decoded data + * @throws java.io.IOException If bogus characters exist in source data + * @since 1.3 + */ + public static byte[] decode( byte[] source, int off, int len, int options ) + throws java.io.IOException { + + // Lots of error checking and exception throwing + if( source == null ){ + throw new NullPointerException( "Cannot decode null source array." ); + } // end if + if( off < 0 || off + len > source.length ){ + throw new IllegalArgumentException( String.format( + "Source array with length %d cannot have offset of %d and process %d bytes.", source.length, off, len ) ); + } // end if + + if( len == 0 ){ + return new byte[0]; + }else if( len < 4 ){ + throw new IllegalArgumentException( + "Base64-encoded string must have at least four characters, but length specified was " + len ); + } // end if + + byte[] DECODABET = getDecodabet( options ); + + int len34 = len * 3 / 4; // Estimate on array size + byte[] outBuff = new byte[ len34 ]; // Upper limit on size of output + int outBuffPosn = 0; // Keep track of where we're writing + + byte[] b4 = new byte[4]; // Four byte buffer from source, eliminating white space + int b4Posn = 0; // Keep track of four byte input buffer + int i = 0; // Source array counter + byte sbiDecode = 0; // Special value from DECODABET + + for( i = off; i < off+len; i++ ) { // Loop through source + + sbiDecode = DECODABET[ source[i]&0xFF ]; + + // White space, Equals sign, or legit Base64 character + // Note the values such as -5 and -9 in the + // DECODABETs at the top of the file. + if( sbiDecode >= WHITE_SPACE_ENC ) { + if( sbiDecode >= EQUALS_SIGN_ENC ) { + b4[ b4Posn++ ] = source[i]; // Save non-whitespace + if( b4Posn > 3 ) { // Time to decode? + outBuffPosn += decode4to3( b4, 0, outBuff, outBuffPosn, options ); + b4Posn = 0; + + // If that was the equals sign, break out of 'for' loop + if( source[i] == EQUALS_SIGN ) { + break; + } // end if: equals sign + } // end if: quartet built + } // end if: equals sign or better + } // end if: white space, equals sign or better + else { + // There's a bad input character in the Base64 stream. + throw new java.io.IOException( String.format( + "Bad Base64 input character decimal %d in array position %d", ((int)source[i])&0xFF, i ) ); + } // end else: + } // each input character + + byte[] out = new byte[ outBuffPosn ]; + System.arraycopy( outBuff, 0, out, 0, outBuffPosn ); + return out; + } // end decode + + + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @return the decoded data + * @throws java.io.IOException If there is a problem + * @since 1.4 + */ + public static byte[] decode( String s ) throws java.io.IOException { + return decode( s, NO_OPTIONS ); + } + + + + /** + * Decodes data from Base64 notation, automatically + * detecting gzip-compressed data and decompressing it. + * + * @param s the string to decode + * @param options encode options such as URL_SAFE + * @return the decoded data + * @throws java.io.IOException if there is an error + * @throws NullPointerException if s is null + * @since 1.4 + */ + public static byte[] decode( String s, int options ) throws java.io.IOException { + + if( s == null ){ + throw new NullPointerException( "Input string was null." ); + } // end if + + byte[] bytes; + try { + bytes = s.getBytes( PREFERRED_ENCODING ); + } // end try + catch( java.io.UnsupportedEncodingException uee ) { + bytes = s.getBytes(); + } // end catch + // + + // Decode + bytes = decode( bytes, 0, bytes.length, options ); + + // Check to see if it's gzip-compressed + // GZIP Magic Two-Byte Number: 0x8b1f (35615) + boolean dontGunzip = (options & DONT_GUNZIP) != 0; + if( (bytes != null) && (bytes.length >= 4) && (!dontGunzip) ) { + + int head = ((int)bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00); + if( java.util.zip.GZIPInputStream.GZIP_MAGIC == head ) { + java.io.ByteArrayInputStream bais = null; + java.util.zip.GZIPInputStream gzis = null; + java.io.ByteArrayOutputStream baos = null; + byte[] buffer = new byte[2048]; + int length = 0; + + try { + baos = new java.io.ByteArrayOutputStream(); + bais = new java.io.ByteArrayInputStream( bytes ); + gzis = new java.util.zip.GZIPInputStream( bais ); + + while( ( length = gzis.read( buffer ) ) >= 0 ) { + baos.write(buffer,0,length); + } // end while: reading input + + // No error? Get new bytes. + bytes = baos.toByteArray(); + + } // end try + catch( java.io.IOException e ) { + e.printStackTrace(); + // Just return originally-decoded bytes + } // end catch + finally { + try{ baos.close(); } catch( Exception e ){} + try{ gzis.close(); } catch( Exception e ){} + try{ bais.close(); } catch( Exception e ){} + } // end finally + + } // end if: gzipped + } // end if: bytes.length >= 2 + + return bytes; + } // end decode + + + + /** + * Attempts to decode Base64 data and deserialize a Java + * Object within. Returns null if there was an error. + * + * @param encodedObject The Base64 data to decode + * @return The decoded and deserialized object + * @throws NullPointerException if encodedObject is null + * @throws java.io.IOException if there is a general error + * @throws ClassNotFoundException if the decoded object is of a + * class that cannot be found by the JVM + * @since 1.5 + */ + public static Object decodeToObject( String encodedObject ) + throws java.io.IOException, java.lang.ClassNotFoundException { + return decodeToObject(encodedObject,NO_OPTIONS,null); + } + + + /** + * Attempts to decode Base64 data and deserialize a Java + * Object within. Returns null if there was an error. + * If loader is not null, it will be the class loader + * used when deserializing. + * + * @param encodedObject The Base64 data to decode + * @param options Various parameters related to decoding + * @param loader Optional class loader to use in deserializing classes. + * @return The decoded and deserialized object + * @throws NullPointerException if encodedObject is null + * @throws java.io.IOException if there is a general error + * @throws ClassNotFoundException if the decoded object is of a + * class that cannot be found by the JVM + * @since 2.3.4 + */ + public static Object decodeToObject( + String encodedObject, int options, final ClassLoader loader ) + throws java.io.IOException, java.lang.ClassNotFoundException { + + // Decode and gunzip if necessary + byte[] objBytes = decode( encodedObject, options ); + + java.io.ByteArrayInputStream bais = null; + java.io.ObjectInputStream ois = null; + Object obj = null; + + try { + bais = new java.io.ByteArrayInputStream( objBytes ); + + // If no custom class loader is provided, use Java's builtin OIS. + if( loader == null ){ + ois = new java.io.ObjectInputStream( bais ); + } // end if: no loader provided + + // Else make a customized object input stream that uses + // the provided class loader. + else { + ois = new java.io.ObjectInputStream(bais){ + @Override + public Class resolveClass(java.io.ObjectStreamClass streamClass) + throws java.io.IOException, ClassNotFoundException { + Class c = Class.forName(streamClass.getName(), false, loader); + if( c == null ){ + return super.resolveClass(streamClass); + } else { + return c; // Class loader knows of this class. + } // end else: not null + } // end resolveClass + }; // end ois + } // end else: no custom class loader + + obj = ois.readObject(); + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and throw in order to execute finally{} + } // end catch + catch( java.lang.ClassNotFoundException e ) { + throw e; // Catch and throw in order to execute finally{} + } // end catch + finally { + try{ bais.close(); } catch( Exception e ){} + try{ ois.close(); } catch( Exception e ){} + } // end finally + + return obj; + } // end decodeObject + + + + /** + * Convenience method for encoding data to a file. + * + *

As of v 2.3, if there is a error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned false, but + * in retrospect that's a pretty poor way to handle it.

+ * + * @param dataToEncode byte array of data to encode in base64 form + * @param filename Filename for saving encoded data + * @throws java.io.IOException if there is an error + * @throws NullPointerException if dataToEncode is null + * @since 2.1 + */ + public static void encodeToFile( byte[] dataToEncode, String filename ) + throws java.io.IOException { + + if( dataToEncode == null ){ + throw new NullPointerException( "Data to encode was null." ); + } // end iff + + Base64.OutputStream bos = null; + try { + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.ENCODE ); + bos.write( dataToEncode ); + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and throw to execute finally{} block + } // end catch: java.io.IOException + finally { + try{ bos.close(); } catch( Exception e ){} + } // end finally + + } // end encodeToFile + + + /** + * Convenience method for decoding data to a file. + * + *

As of v 2.3, if there is a error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned false, but + * in retrospect that's a pretty poor way to handle it.

+ * + * @param dataToDecode Base64-encoded data as a string + * @param filename Filename for saving decoded data + * @throws java.io.IOException if there is an error + * @since 2.1 + */ + public static void decodeToFile( String dataToDecode, String filename ) + throws java.io.IOException { + + Base64.OutputStream bos = null; + try{ + bos = new Base64.OutputStream( + new java.io.FileOutputStream( filename ), Base64.DECODE ); + bos.write( dataToDecode.getBytes( PREFERRED_ENCODING ) ); + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and throw to execute finally{} block + } // end catch: java.io.IOException + finally { + try{ bos.close(); } catch( Exception e ){} + } // end finally + + } // end decodeToFile + + + + + /** + * Convenience method for reading a base64-encoded + * file and decoding it. + * + *

As of v 2.3, if there is a error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned false, but + * in retrospect that's a pretty poor way to handle it.

+ * + * @param filename Filename for reading encoded data + * @return decoded byte array + * @throws java.io.IOException if there is an error + * @since 2.1 + */ + public static byte[] decodeFromFile( String filename ) + throws java.io.IOException { + + byte[] decodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer = null; + int length = 0; + int numBytes = 0; + + // Check for size of file + if( file.length() > Integer.MAX_VALUE ) + { + throw new java.io.IOException( "File is too big for this convenience method (" + file.length() + " bytes)." ); + } // end if: file too big for int index + buffer = new byte[ (int)file.length() ]; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.DECODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) { + length += numBytes; + } // end while + + // Save in a variable to return + decodedData = new byte[ length ]; + System.arraycopy( buffer, 0, decodedData, 0, length ); + + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and release to execute finally{} + } // end catch: java.io.IOException + finally { + try{ bis.close(); } catch( Exception e) {} + } // end finally + + return decodedData; + } // end decodeFromFile + + + + /** + * Convenience method for reading a binary file + * and base64-encoding it. + * + *

As of v 2.3, if there is a error, + * the method will throw an java.io.IOException. This is new to v2.3! + * In earlier versions, it just returned false, but + * in retrospect that's a pretty poor way to handle it.

+ * + * @param filename Filename for reading binary data + * @return base64-encoded string + * @throws java.io.IOException if there is an error + * @since 2.1 + */ + public static String encodeFromFile( String filename ) + throws java.io.IOException { + + String encodedData = null; + Base64.InputStream bis = null; + try + { + // Set up some useful variables + java.io.File file = new java.io.File( filename ); + byte[] buffer = new byte[ Math.max((int)(file.length() * 1.4+1),40) ]; // Need max() for math on small files (v2.2.1); Need +1 for a few corner cases (v2.3.5) + int length = 0; + int numBytes = 0; + + // Open a stream + bis = new Base64.InputStream( + new java.io.BufferedInputStream( + new java.io.FileInputStream( file ) ), Base64.ENCODE ); + + // Read until done + while( ( numBytes = bis.read( buffer, length, 4096 ) ) >= 0 ) { + length += numBytes; + } // end while + + // Save in a variable to return + encodedData = new String( buffer, 0, length, Base64.PREFERRED_ENCODING ); + + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and release to execute finally{} + } // end catch: java.io.IOException + finally { + try{ bis.close(); } catch( Exception e) {} + } // end finally + + return encodedData; + } // end encodeFromFile + + /** + * Reads infile and encodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @throws java.io.IOException if there is an error + * @since 2.2 + */ + public static void encodeFileToFile( String infile, String outfile ) + throws java.io.IOException { + + String encoded = Base64.encodeFromFile( infile ); + java.io.OutputStream out = null; + try{ + out = new java.io.BufferedOutputStream( + new java.io.FileOutputStream( outfile ) ); + out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output. + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and release to execute finally{} + } // end catch + finally { + try { out.close(); } + catch( Exception ex ){} + } // end finally + } // end encodeFileToFile + + + /** + * Reads infile and decodes it to outfile. + * + * @param infile Input file + * @param outfile Output file + * @throws java.io.IOException if there is an error + * @since 2.2 + */ + public static void decodeFileToFile( String infile, String outfile ) + throws java.io.IOException { + + byte[] decoded = Base64.decodeFromFile( infile ); + java.io.OutputStream out = null; + try{ + out = new java.io.BufferedOutputStream( + new java.io.FileOutputStream( outfile ) ); + out.write( decoded ); + } // end try + catch( java.io.IOException e ) { + throw e; // Catch and release to execute finally{} + } // end catch + finally { + try { out.close(); } + catch( Exception ex ){} + } // end finally + } // end decodeFileToFile + + + /* ******** I N N E R C L A S S I N P U T S T R E A M ******** */ + + + + /** + * A {@link Base64.InputStream} will read data from another + * java.io.InputStream, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @since 1.3 + */ + public static class InputStream extends java.io.FilterInputStream { + + private boolean encode; // Encoding or decoding + private int position; // Current position in the buffer + private byte[] buffer; // Small buffer holding converted data + private int bufferLength; // Length of buffer (3 or 4) + private int numSigBytes; // Number of meaningful bytes in the buffer + private int lineLength; + private boolean breakLines; // Break lines at less than 80 characters + private int options; // Record options used to create the stream. + private byte[] decodabet; // Local copies to avoid extra method calls + + + /** + * Constructs a {@link Base64.InputStream} in DECODE mode. + * + * @param in the java.io.InputStream from which to read data. + * @since 1.3 + */ + public InputStream( java.io.InputStream in ) { + this( in, DECODE ); + } // end constructor + + + /** + * Constructs a {@link Base64.InputStream} in + * either ENCODE or DECODE mode. + *

+ * Valid options:

+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DO_BREAK_LINES: break lines at 76 characters
+         *     (only meaningful when encoding)
+         * 
+ *

+ * Example: new Base64.InputStream( in, Base64.DECODE ) + * + * + * @param in the java.io.InputStream from which to read data. + * @param options Specified options + * @see Base64#ENCODE + * @see Base64#DECODE + * @see Base64#DO_BREAK_LINES + * @since 2.0 + */ + public InputStream( java.io.InputStream in, int options ) { + + super( in ); + this.options = options; // Record for later + this.breakLines = (options & DO_BREAK_LINES) > 0; + this.encode = (options & ENCODE) > 0; + this.bufferLength = encode ? 4 : 3; + this.buffer = new byte[ bufferLength ]; + this.position = -1; + this.lineLength = 0; + this.decodabet = getDecodabet(options); + } // end constructor + + /** + * Reads enough of the input stream to convert + * to/from Base64 and returns the next byte. + * + * @return next byte + * @since 1.3 + */ + @Override + public int read() throws java.io.IOException { + + // Do we need to get data? + if( position < 0 ) { + if( encode ) { + byte[] b3 = new byte[3]; + int numBinaryBytes = 0; + for( int i = 0; i < 3; i++ ) { + int b = in.read(); + + // If end of stream, b is -1. + if( b >= 0 ) { + b3[i] = (byte)b; + numBinaryBytes++; + } else { + break; // out of for loop + } // end else: end of stream + + } // end for: each needed input byte + + if( numBinaryBytes > 0 ) { + encode3to4( b3, 0, numBinaryBytes, buffer, 0, options ); + position = 0; + numSigBytes = 4; + } // end if: got data + else { + return -1; // Must be end of stream + } // end else + } // end if: encoding + + // Else decoding + else { + byte[] b4 = new byte[4]; + int i = 0; + for( i = 0; i < 4; i++ ) { + // Read four "meaningful" bytes: + int b = 0; + do{ b = in.read(); } + while( b >= 0 && decodabet[ b & 0x7f ] <= WHITE_SPACE_ENC ); + + if( b < 0 ) { + break; // Reads a -1 if end of stream + } // end if: end of stream + + b4[i] = (byte)b; + } // end for: each needed input byte + + if( i == 4 ) { + numSigBytes = decode4to3( b4, 0, buffer, 0, options ); + position = 0; + } // end if: got four characters + else if( i == 0 ){ + return -1; + } // end else if: also padded correctly + else { + // Must have broken out from above. + throw new java.io.IOException( "Improperly padded Base64 input." ); + } // end + + } // end else: decode + } // end else: get data + + // Got data? + if( position >= 0 ) { + // End of relevant data? + if( /*!encode &&*/ position >= numSigBytes ){ + return -1; + } // end if: got data + + if( encode && breakLines && lineLength >= MAX_LINE_LENGTH ) { + lineLength = 0; + return '\n'; + } // end if + else { + lineLength++; // This isn't important when decoding + // but throwing an extra "if" seems + // just as wasteful. + + int b = buffer[ position++ ]; + + if( position >= bufferLength ) { + position = -1; + } // end if: end + + return b & 0xFF; // This is how you "cast" a byte that's + // intended to be unsigned. + } // end else + } // end if: position >= 0 + + // Else error + else { + throw new java.io.IOException( "Error in Base64 code reading stream." ); + } // end else + } // end read + + + /** + * Calls {@link #read()} repeatedly until the end of stream + * is reached or len bytes are read. + * Returns number of bytes read into array or -1 if + * end of stream is encountered. + * + * @param dest array to hold values + * @param off offset for array + * @param len max number of bytes to read into array + * @return bytes read into array or -1 if end of stream is encountered. + * @since 1.3 + */ + @Override + public int read( byte[] dest, int off, int len ) + throws java.io.IOException { + int i; + int b; + for( i = 0; i < len; i++ ) { + b = read(); + + if( b >= 0 ) { + dest[off + i] = (byte) b; + } + else if( i == 0 ) { + return -1; + } + else { + break; // Out of 'for' loop + } // Out of 'for' loop + } // end for: each byte read + return i; + } // end read + + } // end inner class InputStream + + + + + + + /* ******** I N N E R C L A S S O U T P U T S T R E A M ******** */ + + + + /** + * A {@link Base64.OutputStream} will write data to another + * java.io.OutputStream, given in the constructor, + * and encode/decode to/from Base64 notation on the fly. + * + * @see Base64 + * @since 1.3 + */ + public static class OutputStream extends java.io.FilterOutputStream { + + private boolean encode; + private int position; + private byte[] buffer; + private int bufferLength; + private int lineLength; + private boolean breakLines; + private byte[] b4; // Scratch used in a few places + private boolean suspendEncoding; + private int options; // Record for later + private byte[] decodabet; // Local copies to avoid extra method calls + + /** + * Constructs a {@link Base64.OutputStream} in ENCODE mode. + * + * @param out the java.io.OutputStream to which data will be written. + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out ) { + this( out, ENCODE ); + } // end constructor + + + /** + * Constructs a {@link Base64.OutputStream} in + * either ENCODE or DECODE mode. + *

+ * Valid options:

+         *   ENCODE or DECODE: Encode or Decode as data is read.
+         *   DO_BREAK_LINES: don't break lines at 76 characters
+         *     (only meaningful when encoding)
+         * 
+ *

+ * Example: new Base64.OutputStream( out, Base64.ENCODE ) + * + * @param out the java.io.OutputStream to which data will be written. + * @param options Specified options. + * @see Base64#ENCODE + * @see Base64#DECODE + * @see Base64#DO_BREAK_LINES + * @since 1.3 + */ + public OutputStream( java.io.OutputStream out, int options ) { + super( out ); + this.breakLines = (options & DO_BREAK_LINES) != 0; + this.encode = (options & ENCODE) != 0; + this.bufferLength = encode ? 3 : 4; + this.buffer = new byte[ bufferLength ]; + this.position = 0; + this.lineLength = 0; + this.suspendEncoding = false; + this.b4 = new byte[4]; + this.options = options; + this.decodabet = getDecodabet(options); + } // end constructor + + + /** + * Writes the byte to the output stream after + * converting to/from Base64 notation. + * When encoding, bytes are buffered three + * at a time before the output stream actually + * gets a write() call. + * When decoding, bytes are buffered four + * at a time. + * + * @param theByte the byte to write + * @since 1.3 + */ + @Override + public void write(int theByte) + throws java.io.IOException { + // Encoding suspended? + if( suspendEncoding ) { + this.out.write( theByte ); + return; + } // end if: supsended + + // Encode? + if( encode ) { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) { // Enough to encode. + + this.out.write( encode3to4( b4, buffer, bufferLength, options ) ); + + lineLength += 4; + if( breakLines && lineLength >= MAX_LINE_LENGTH ) { + this.out.write( NEW_LINE ); + lineLength = 0; + } // end if: end of line + + position = 0; + } // end if: enough to output + } // end if: encoding + + // Else, Decoding + else { + // Meaningful Base64 character? + if( decodabet[ theByte & 0x7f ] > WHITE_SPACE_ENC ) { + buffer[ position++ ] = (byte)theByte; + if( position >= bufferLength ) { // Enough to output. + + int len = Base64.decode4to3( buffer, 0, b4, 0, options ); + out.write( b4, 0, len ); + position = 0; + } // end if: enough to output + } // end if: meaningful base64 character + else if( decodabet[ theByte & 0x7f ] != WHITE_SPACE_ENC ) { + throw new java.io.IOException( "Invalid character in Base64 data." ); + } // end else: not white space either + } // end else: decoding + } // end write + + + + /** + * Calls {@link #write(int)} repeatedly until len + * bytes are written. + * + * @param theBytes array from which to read bytes + * @param off offset for array + * @param len max number of bytes to read into array + * @since 1.3 + */ + @Override + public void write( byte[] theBytes, int off, int len ) + throws java.io.IOException { + // Encoding suspended? + if( suspendEncoding ) { + this.out.write( theBytes, off, len ); + return; + } // end if: supsended + + for( int i = 0; i < len; i++ ) { + write( theBytes[ off + i ] ); + } // end for: each byte written + + } // end write + + + + /** + * Method added by PHIL. [Thanks, PHIL. -Rob] + * This pads the buffer without closing the stream. + * @throws java.io.IOException if there's an error. + */ + public void flushBase64() throws java.io.IOException { + if( position > 0 ) { + if( encode ) { + out.write( encode3to4( b4, buffer, position, options ) ); + position = 0; + } // end if: encoding + else { + throw new java.io.IOException( "Base64 input not properly padded." ); + } // end else: decoding + } // end if: buffer partially full + + } // end flush + + + /** + * Flushes and closes (I think, in the superclass) the stream. + * + * @since 1.3 + */ + @Override + public void close() throws java.io.IOException { + // 1. Ensure that pending characters are written + flushBase64(); + + // 2. Actually close the stream + // Base class both flushes and closes. + super.close(); + + buffer = null; + out = null; + } // end close + + + + /** + * Suspends encoding of the stream. + * May be helpful if you need to embed a piece of + * base64-encoded data in a stream. + * + * @throws java.io.IOException if there's an error flushing + * @since 1.5.1 + */ + public void suspendEncoding() throws java.io.IOException { + flushBase64(); + this.suspendEncoding = true; + } // end suspendEncoding + + + /** + * Resumes encoding of the stream. + * May be helpful if you need to embed a piece of + * base64-encoded data in a stream. + * + * @since 1.5.1 + */ + public void resumeEncoding() { + this.suspendEncoding = false; + } // end resumeEncoding + + + + } // end inner class OutputStream + + +} // end class Base64 diff --git a/src/org/jruby/ext/openssl/impl/Base64BIOFilter.java b/src/org/jruby/ext/openssl/impl/Base64BIOFilter.java new file mode 100644 index 00000000000..99febedc58d --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Base64BIOFilter.java @@ -0,0 +1,74 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * + * @author Ola Bini + */ +public class Base64BIOFilter extends BIOFilter { + private OutputStream nextOutput; + private InputStream nextInput; + + @Override + public int write(byte[] out, int offset, int len) throws IOException { + this.nextOutput.write(out, offset, len); + return len; + } + + @Override + public int read(byte[] into, int offset, int len) throws IOException { + int read = this.nextInput.read(into, offset, len); + if(read == -1) { + return 0; + } + return read; + } + + @Override + public void flush() throws IOException { + this.nextOutput.flush(); + } + + @Override + public BIO push(BIO bio) { + BIO ret = super.push(bio); + this.nextOutput = new Base64.OutputStream(BIO.asOutputStream(this.nextBio)); + this.nextInput = new Base64.InputStream(BIO.asInputStream(this.nextBio)); + return ret; + } + + @Override + public int getType() { + return TYPE_BASE64; + } +}// Base64BIOFilter diff --git a/src/org/jruby/ext/openssl/impl/CipherBIOFilter.java b/src/org/jruby/ext/openssl/impl/CipherBIOFilter.java new file mode 100644 index 00000000000..14ed54e5636 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/CipherBIOFilter.java @@ -0,0 +1,158 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; + +/** + * + * @author Ola Bini + */ +public class CipherBIOFilter extends BIOFilter { + private Cipher cipher; + + private byte[] bufRead = new byte[4096]; + private int fillLen = 0; + private int fillOffset = 0; + + private byte[] tmpBuf = new byte[1024]; + + private boolean finalized = false; + + public CipherBIOFilter(Cipher cipher) { + this.cipher = cipher; + } + + @Override + public void flush() throws IOException, PKCS7Exception { + try { + byte[] result = cipher.doFinal(); + if(result == null) { + return; + } + next().write(result, 0, result.length); + } catch(IllegalBlockSizeException e) { + throw new PKCS7Exception(-1, -1, e); + } catch(BadPaddingException e) { + throw new PKCS7Exception(-1, -1, e); + } + } + + public int read(byte[] into, int offset, int len) throws IOException { + try { + int read = 0; + if(fillLen > 0) { + read = Math.min(fillLen, len); + System.arraycopy(bufRead, fillOffset, into, offset, read); + fillOffset += read; + fillLen -= read; + if(fillLen == 0) { + fillOffset = 0; + } + if(read == len) { + return read; + } + } + + int req = len - read; + int off = offset + read; + + if(finalized) { + return 0; + } + + while(req > 0) { + int readFromNext = next().read(tmpBuf, 0, 1024); + if(readFromNext > 0) { + int required = cipher.getOutputSize(readFromNext); + if(required > (bufRead.length - (fillOffset + fillLen))) { + byte[] newBuf = new byte[required + fillOffset + fillLen]; + System.arraycopy(bufRead, fillOffset, newBuf, 0, fillLen); + fillOffset = 0; + bufRead = newBuf; + } + int outputted = cipher.update(tmpBuf, 0, readFromNext, bufRead, fillOffset + fillLen); + fillLen += outputted; + + read = Math.min(fillLen, req); + System.arraycopy(bufRead, fillOffset, into, off, read); + fillOffset += read; + fillLen -= read; + if(fillLen == 0) { + fillOffset = 0; + } + + req -= read; + off += read; + } else { + int required = cipher.getOutputSize(0); + if(required > (bufRead.length - (fillOffset + fillLen))) { + byte[] newBuf = new byte[required + fillOffset + fillLen]; + System.arraycopy(bufRead, fillOffset, newBuf, 0, fillLen); + fillOffset = 0; + bufRead = newBuf; + } + int outputted = cipher.doFinal(bufRead, fillOffset + fillLen); + finalized = true; + fillLen += outputted; + + read = Math.min(fillLen, req); + System.arraycopy(bufRead, fillOffset, into, off, read); + fillOffset += read; + fillLen -= read; + if(fillLen == 0) { + fillOffset = 0; + } + + req -= read; + return len-req; + } + } + + return len; + } catch(Exception e) { + throw new IllegalArgumentException(e); + } + } + + public int write(byte[] out, int offset, int len) throws IOException { + byte[] result = cipher.update(out, offset, len); + if(result == null) { + return len; + } + next().write(result, 0, result.length); + return len; + } + + public int getType() { + return TYPE_CIPHER; + } +}// CipherBIOFilter diff --git a/src/org/jruby/ext/openssl/impl/CipherSpec.java b/src/org/jruby/ext/openssl/impl/CipherSpec.java new file mode 100644 index 00000000000..1891cd94de1 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/CipherSpec.java @@ -0,0 +1,78 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2009 Hiroshi Nakamura + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import javax.crypto.Cipher; + +/** + * + * @author Ola Bini + */ +public class CipherSpec extends BIOFilter { + private final Cipher cipher; + private final String osslName; + private final int keyLenInBits; + + public CipherSpec(Cipher cipher, String osslName, int keyLenInBits) { + this.cipher = cipher; + this.osslName = osslName; + this.keyLenInBits = keyLenInBits; + } + + public Cipher getCipher() { + return cipher; + } + + public String getOsslName() { + return osslName; + } + + public int getKeyLenInBits() { + return keyLenInBits; + } + + public String getAlgorithm() { + return getCipher().getAlgorithm(); + } + + public String getWrappingAlgorithm() { + return getWrappingAlgorithm(getAlgorithm()); + } + + public static String getWrappingAlgorithm(String algorithm) { + if (algorithm == null) { + return null; + } + if (algorithm.equalsIgnoreCase("RSA")) { + return "RSA/ECB/PKCS1Padding"; + } else { + return algorithm; + } + } + +}// CipherSpec diff --git a/src/org/jruby/ext/openssl/impl/Digest.java b/src/org/jruby/ext/openssl/impl/Digest.java new file mode 100644 index 00000000000..9de032e91f3 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Digest.java @@ -0,0 +1,126 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** PKCS7_DIGEST + * + * @author Ola Bini + */ +public class Digest { + /** + * Describe version here. + */ + private int version; + + /** + * Describe md here. + */ + private AlgorithmIdentifier md; + + /** + * Describe digest here. + */ + private ASN1OctetString digest; + + PKCS7 contents; + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the Contents value. + * + * @return a PKCS7 value + */ + public final PKCS7 getContents() { + return contents; + } + + /** + * Set the Contents value. + * + * @param newContents The new Contents value. + */ + public final void setContents(final PKCS7 newContents) { + this.contents = newContents; + } + + /** + * Get the Md value. + * + * @return an AlgorithmIdentifier value + */ + public final AlgorithmIdentifier getMd() { + return md; + } + + /** + * Set the Md value. + * + * @param newMd The new Md value. + */ + public final void setMd(final AlgorithmIdentifier newMd) { + this.md = newMd; + } + + /** + * Get the Digest value. + * + * @return an ASN1OctetString value + */ + public final ASN1OctetString getDigest() { + return digest; + } + + /** + * Set the Digest value. + * + * @param newDigest The new Digest value. + */ + public final void setDigest(final ASN1OctetString newDigest) { + this.digest = newDigest; + } +}// Digest diff --git a/src/org/jruby/ext/openssl/impl/EVP.java b/src/org/jruby/ext/openssl/impl/EVP.java new file mode 100644 index 00000000000..b46060fb748 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/EVP.java @@ -0,0 +1,147 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.security.GeneralSecurityException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import org.bouncycastle.asn1.DERObjectIdentifier; + +/** + * + * @author Ola Bini + */ +public class EVP { + // This is a class that will collect mappings from ASN1 stuff to + // matching Cipher and other algorithms. + + // Typical examples: + // EVP_get_cipherbyobj + // EVP_get_digestbynid + + /* c: EVP_get_cipherbyobj + * + */ + public static Cipher getCipher(DERObjectIdentifier oid) throws GeneralSecurityException { + String algorithm = getAlgorithmName(oid); + String[] cipher = org.jruby.ext.openssl.Cipher.Algorithm.osslToJsse(algorithm); + String realName = cipher[3]; + return Cipher.getInstance(realName); + } + + /* c: EVP_get_cipherbynid + * + */ + public static Cipher getCipher(int nid) throws GeneralSecurityException { + return getCipher(ASN1Registry.nid2obj(nid)); + } + + /* c: EVP_get_digestbyobj + * + */ + public static MessageDigest getDigest(DERObjectIdentifier oid) throws GeneralSecurityException { + String algorithm = getAlgorithmName(oid); + return MessageDigest.getInstance(algorithm); + } + + /* c: EVP_get_digestbynid + * + */ + public static MessageDigest getDigest(int nid) throws GeneralSecurityException { + return getDigest(ASN1Registry.nid2obj(nid)); + } + + /* c: EVP_sha1 + * + */ + public static MessageDigest sha1() { + try { + return MessageDigest.getInstance("SHA1"); + } catch(Exception e) { + return null; + } + } + + public static int type(MessageDigest digest) { + String name = digest.getAlgorithm(); + DERObjectIdentifier obj = ASN1Registry.sym2oid(name); + if(obj == null) { + name = name.toLowerCase().replace("sha-", "sha"); + obj = ASN1Registry.sym2oid(name); + } + return ASN1Registry.obj2nid(obj); + } + + public static String signatureAlgorithm(MessageDigest digest, Key key) { + String sig = digest.getAlgorithm().toLowerCase().replace("sha-", "sha"); + String type = key.getAlgorithm().toLowerCase(); + if(sig == null) { + sig = "none"; + } + return sig + "with" + type; + } + + /* c: EVP_PKEY_decrypt + * + */ + public static byte[] decrypt(byte[] input, int offset, int len, Key key) throws InvalidKeyException, + NoSuchAlgorithmException, + NoSuchPaddingException, + IllegalBlockSizeException, + BadPaddingException { + Cipher cipher = Cipher.getInstance(key.getAlgorithm()); + cipher.init(Cipher.DECRYPT_MODE, key); + return cipher.doFinal(input, offset, len); + } + + /* c: EVP_PKEY_decrypt + * + */ + public static byte[] decrypt(byte[] input, Key key) throws InvalidKeyException, + NoSuchAlgorithmException, + NoSuchPaddingException, + IllegalBlockSizeException, + BadPaddingException { + return decrypt(input, 0, input.length, key); + } + + private static String getAlgorithmName(DERObjectIdentifier oid) { + String algorithm = ASN1Registry.o2a(oid); + if (algorithm != null) { + return algorithm.toUpperCase(); + } else { + return oid.getId(); + } + } +}// EVP diff --git a/src/org/jruby/ext/openssl/impl/EncContent.java b/src/org/jruby/ext/openssl/impl/EncContent.java new file mode 100644 index 00000000000..a2d8a0333e2 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/EncContent.java @@ -0,0 +1,177 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; + +/** PKCS7_ENC_CONTENT + * + * @author Ola Bini + */ +public class EncContent { + /** + * Describe contentType here. + */ + private int contentType; + + /** + * Describe cipher here. + */ + private CipherSpec cipher; + + /** + * Describe algorithm here. + */ + private AlgorithmIdentifier algorithm; + + /** + * Describe encData here. + */ + private ASN1OctetString encData; + + /** + * Get the ContentType value. + * + * @return an int value + */ + public final int getContentType() { + return contentType; + } + + /** + * Set the ContentType value. + * + * @param newContentType The new ContentType value. + */ + public final void setContentType(final int newContentType) { + this.contentType = newContentType; + } + + /** + * Get the Cipher value. + * + * @return a Cipher value + */ + public final CipherSpec getCipher() { + return cipher; + } + + /** + * Set the Cipher value. + * + * @param newCipher The new Cipher value. + */ + public final void setCipher(final CipherSpec newCipher) { + this.cipher = newCipher; + } + + /** + * Get the Algorithm value. + * + * @return an AlgorithmIdentifier value + */ + public final AlgorithmIdentifier getAlgorithm() { + return algorithm; + } + + /** + * Set the Algorithm value. + * + * @param newAlgorithm The new Algorithm value. + */ + public final void setAlgorithm(final AlgorithmIdentifier newAlgorithm) { + this.algorithm = newAlgorithm; + } + + /** + * Get the EncData value. + * + * @return an ASN1OctetString value + */ + public final ASN1OctetString getEncData() { + return encData; + } + + /** + * Set the EncData value. + * + * @param newEncData The new EncData value. + */ + public final void setEncData(final ASN1OctetString newEncData) { + this.encData = newEncData; + } + + @Override + public String toString() { + return "#"; + } + + /** + * EncryptedContentInfo ::= SEQUENCE { + * contentType ContentType, + * contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, + * encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } + * + * EncryptedContent ::= OCTET STRING + */ + public static EncContent fromASN1(DEREncodable content) { + ASN1Sequence sequence = (ASN1Sequence)content; + DERObjectIdentifier contentType = (DERObjectIdentifier)(sequence.getObjectAt(0)); + int nid = ASN1Registry.obj2nid(contentType); + + EncContent ec = new EncContent(); + ec.setContentType(nid); + ec.setAlgorithm(AlgorithmIdentifier.getInstance(sequence.getObjectAt(1))); + if(sequence.size() > 2 && sequence.getObjectAt(2) instanceof DERTaggedObject && ((DERTaggedObject)(sequence.getObjectAt(2))).getTagNo() == 0) { + DEREncodable ee = ((DERTaggedObject)(sequence.getObjectAt(2))).getObject(); + if(ee instanceof ASN1Sequence) { + } else { + ec.setEncData((ASN1OctetString)ee); + } + } + return ec; + } + + public ASN1Encodable asASN1() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(ASN1Registry.nid2obj(contentType).toASN1Object()); + vector.add(algorithm.toASN1Object()); + if(encData != null) { + vector.add(new DERTaggedObject(false, 0, encData)); + } + return new DERSequence(vector); + } +}// EncContent diff --git a/src/org/jruby/ext/openssl/impl/Encrypt.java b/src/org/jruby/ext/openssl/impl/Encrypt.java new file mode 100644 index 00000000000..00b0a97de3d --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Encrypt.java @@ -0,0 +1,77 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** PKCS7_ENCRYPT + * + * @author Ola Bini + */ +public class Encrypt { + private int version; + + /** + * Describe encContent here. + */ + private EncContent encData = new EncContent(); + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the EncData value. + * + * @return an EncContent value + */ + public final EncContent getEncData() { + return encData; + } + + /** + * Set the EncData value. + * + * @param newEncContent The new EncContent value. + */ + public final void setEncData(final EncContent newEncData) { + this.encData = newEncData; + } +}// Encrypt diff --git a/src/org/jruby/ext/openssl/impl/Envelope.java b/src/org/jruby/ext/openssl/impl/Envelope.java new file mode 100644 index 00000000000..b508bfbe8df --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Envelope.java @@ -0,0 +1,167 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; + +/** PKCS7_ENVELOPE + * + * @author Ola Bini + */ +public class Envelope { + private int version; + + /** + * Describe encContent here. + */ + private EncContent encData = new EncContent(); + + /** + * Describe recipientInfo here. + */ + private Collection recipientInfo = new ArrayList(); + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the EncData value. + * + * @return an EncContent value + */ + public final EncContent getEncData() { + return encData; + } + + /** + * Set the EncData value. + * + * @param newEncContent The new EncContent value. + */ + public final void setEncData(final EncContent newEncData) { + this.encData = newEncData; + } + + /** + * Get the RecipientInfo value. + * + * @return a Collection value + */ + public final Collection getRecipientInfo() { + return recipientInfo; + } + + /** + * Set the RecipientInfo value. + * + * @param newRecipientInfo The new RecipientInfo value. + */ + public final void setRecipientInfo(final Collection newRecipientInfo) { + this.recipientInfo = newRecipientInfo; + } + + @Override + public String toString() { + return "#"; + } + + /** + * EnvelopedData ::= SEQUENCE { + * version Version, + * recipientInfos RecipientInfos, + * encryptedContentInfo EncryptedContentInfo } + * + * Version ::= INTEGER + * + * RecipientInfos ::= SET OF RecipientInfo + * + */ + public static Envelope fromASN1(DEREncodable content) { + ASN1Sequence sequence = (ASN1Sequence)content; + DERInteger version = (DERInteger)sequence.getObjectAt(0); + ASN1Set recipients = (ASN1Set)sequence.getObjectAt(1); + DEREncodable encContent = sequence.getObjectAt(2); + + Envelope envelope = new Envelope(); + envelope.setVersion(version.getValue().intValue()); + envelope.setRecipientInfo(recipientInfosFromASN1Set(recipients)); + envelope.setEncData(EncContent.fromASN1(encContent)); + + return envelope; + } + + public ASN1Encodable asASN1() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new DERInteger(version)); + vector.add(receipientInfosToASN1Set()); + vector.add(encData.asASN1()); + return new DERSequence(vector); + } + + private ASN1Set receipientInfosToASN1Set() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + for(RecipInfo ri : getRecipientInfo()) { + vector.add(ri.asASN1()); + } + return new DERSet(vector); + } + + private static Collection recipientInfosFromASN1Set(DEREncodable content) { + ASN1Set set = (ASN1Set)content; + Collection result = new ArrayList(); + for(Enumeration e = set.getObjects(); e.hasMoreElements();) { + result.add(RecipInfo.fromASN1((DEREncodable)e.nextElement())); + } + return result; + } +}// Envelope diff --git a/src/org/jruby/ext/openssl/impl/IssuerAndSerial.java b/src/org/jruby/ext/openssl/impl/IssuerAndSerial.java new file mode 100644 index 00000000000..f6dc109ac1d --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/IssuerAndSerial.java @@ -0,0 +1,35 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** PKCS7_ISSUER_AND_SERIAL + * + * @author Ola Bini + */ +public class IssuerAndSerial { +}// IssuerAndSerial diff --git a/src/org/jruby/ext/openssl/impl/MemBIO.java b/src/org/jruby/ext/openssl/impl/MemBIO.java new file mode 100644 index 00000000000..eab205ef15b --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/MemBIO.java @@ -0,0 +1,117 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; + +/** + * + * @author Ola Bini + */ +public class MemBIO extends BIO { + private byte[] buffer = new byte[1024]; + private int wpointer = 0; + private int rpointer = 0; + private int slen = 0; + + private void realloc() { + byte[] newBuffer = new byte[buffer.length*2]; + System.arraycopy(buffer, 0, newBuffer, 0, wpointer); + buffer = newBuffer; + } + + @Override + public int gets(byte[] in, int len) throws IOException { + if(rpointer == slen) { + return 0; + } + + int i=0; + for(;i buffer.length) { + realloc(); + } + + System.arraycopy(out, offset, buffer, wpointer, len); + wpointer += len; + slen += len; + + return len; + } + + @Override + public String toString() { + try { + return ""; + } catch(Exception e) {} + + return null; + } + + @Override + public void setMemEofReturn(int value) { + } + + public int getType() { + return TYPE_MEM; + } + + public byte[] getMemCopy() { + byte[] nbuf = new byte[slen]; + System.arraycopy(buffer, 0, nbuf, 0, slen); + return nbuf; + } + + public void reset() { + this.rpointer = 0; + } +}// MemBIO diff --git a/src/org/jruby/ext/openssl/impl/MessageDigestBIOFilter.java b/src/org/jruby/ext/openssl/impl/MessageDigestBIOFilter.java new file mode 100644 index 00000000000..68462feb654 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/MessageDigestBIOFilter.java @@ -0,0 +1,76 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.security.MessageDigest; + +/** + * + * @author Ola Bini + */ +public class MessageDigestBIOFilter extends BIOFilter { + private MessageDigest md; + + public MessageDigestBIOFilter(MessageDigest md) { + this.md = md; + } + + public int gets(byte[] in, int len) throws IOException { + int read = next().gets(in, len); + if(read > 0) { + md.update(in, 0, read); + } + return read; + } + + public int read(byte[] into, int offset, int len) throws IOException { + int read = next().read(into, offset, len); + if(read > 0) { + md.update(into, offset, read); + } + return read; + } + + public int write(byte[] out, int offset, int len) throws IOException { + int written = next().write(out, offset, len); + md.update(out, offset, written); + return written; + } + + public int getType() { + return TYPE_MD; + } + + /** c: BIO_get_md_ctx + * + */ + public MessageDigest getMessageDigest() { + return md; + } +}// MessageDigestBIOFilter diff --git a/src/org/jruby/ext/openssl/impl/Mime.java b/src/org/jruby/ext/openssl/impl/Mime.java new file mode 100644 index 00000000000..4d0cd6c8f86 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Mime.java @@ -0,0 +1,244 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Ola Bini + */ +public interface Mime { + Mime DEFAULT = new Mime() { + private final static int MIME_START = 1; + private final static int MIME_TYPE = 2; + private final static int MIME_NAME = 3; + private final static int MIME_VALUE = 4; + private final static int MIME_QUOTE = 5; + private final static int MIME_COMMENT = 6; + + private final static int MAX_SMLEN = 1024; + + /* c: static strip_start + */ + private int stripStart(byte[] buffer, int start, int end) { + byte c; + for(int p = start; p= start; p--) { + mimeDebug(" p = "+p+", c = "+(char)buffer[p] + "(" + buffer[p] + ")"); + c = buffer[p]; + if(c == '"') { + if(p - 1 == start) { + return -1; + } + return p; + } + if(!Character.isWhitespace((char)c)) { + return p+1; + } + } + + return -1; + } + + /* c: static strip_ends + */ + private String stripEnds(byte[] buffer, int start, int end) { + start = stripStart(buffer, start, end); + end = stripEnd(buffer, start, end); + + try { + return new String(buffer, start, end-start, "ISO8859-1"); + } catch(Exception e) { + return null; + } + } + + public void mimeDebug(String str) { + // System.err.println(str); + } + + public List parseHeaders(BIO bio) throws IOException { + mimeDebug("\n!!!!!!!!!!!!!!!!!\n" + bio + "\n^^^^^^^^^^^^^^^^^^^^^^^^\n"); + int state = 0; + byte[] linebuf = new byte[MAX_SMLEN]; + int len = 0; + String ntmp = null; + int p, q; + byte c; + MimeHeader mhdr = null; + int saveState = -1; + + List headers = new ArrayList(); + + while((len = bio.gets(linebuf, MAX_SMLEN)) > 0) { + if(mhdr != null && Character.isWhitespace((char)linebuf[0])) { + state = MIME_NAME; + } else { + state = MIME_START; + } + + for(p = 0, q = 0; p headers, String key) { + for(MimeHeader hdr : headers) { + if(hdr.getName().equals(key)) { + return hdr; + } + } + + return null; + } + + public MimeParam findParam(MimeHeader header, String key) { + for(MimeParam par : header.getParams()) { + if(par.getParamName().equals(key)) { + return par; + } + } + + return null; + } + }; + + + /* c: mime_parse_hdr + * + */ + List parseHeaders(BIO bio) throws IOException; + + /* c: mime_hdr_find + * + */ + MimeHeader findHeader(List headers, String key); + + /* c: mime_param_find + * + */ + MimeParam findParam(MimeHeader header, String key); +}// Mime diff --git a/src/org/jruby/ext/openssl/impl/MimeHeader.java b/src/org/jruby/ext/openssl/impl/MimeHeader.java new file mode 100644 index 00000000000..ce7c37c0a8b --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/MimeHeader.java @@ -0,0 +1,113 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.util.ArrayList; +import java.util.List; + +/** MIME_HEADER + * + * @author Ola Bini + */ +public class MimeHeader { + private String name; + private String value; + + /** + * Describe params here. + */ + private List params; + + public MimeHeader(String name, String value) { + this(name, value, new ArrayList()); + } + + public MimeHeader(String name, String value, List params) { + this.name = (name == null) ? + null : + name.toLowerCase(); + this.value = (value == null) ? + null : + value.toLowerCase(); + this.params = params; + } + + public String getName() { + return this.name; + } + + public String getValue() { + return this.value; + } + + /** + * Get the Params value. + * + * @return a List value + */ + public final List getParams() { + return params; + } + + /** + * Set the Params value. + * + * @param newParams The new Params value. + */ + public final void setParams(final List newParams) { + this.params = newParams; + } + + @Override + public boolean equals(Object other) { + boolean ret = this == other; + if(!ret && (other instanceof MimeHeader)) { + MimeHeader mh = (MimeHeader)other; + ret = + ((this.name == null) ? mh.name == null : this.name.equals(mh.name)) && + ((this.value == null) ? mh.value == null : this.value.equals(mh.value)) && + ((this.params == null) ? mh.params == null : this.params.equals(mh.params)); + } + return ret; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((params == null) ? 0 : params.hashCode()); + result = prime * result + ((value == null) ? 0 : value.hashCode()); + return result; + } + + @Override + public String toString() { + return "#"; + } +}// MimeHeader diff --git a/src/org/jruby/ext/openssl/impl/MimeParam.java b/src/org/jruby/ext/openssl/impl/MimeParam.java new file mode 100644 index 00000000000..b34e5282bce --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/MimeParam.java @@ -0,0 +1,80 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** MIME_PARAM + * + * @author Ola Bini + */ +public class MimeParam { + private String paramName; + private String paramValue; + + public MimeParam(String name, String value) { + this.paramName = (name == null) ? + null : + name.toLowerCase(); + this.paramValue = value; + } + + public String getParamName() { + return this.paramName; + } + + public String getParamValue() { + return this.paramValue; + } + + @Override + public boolean equals(Object other) { + boolean ret = this == other; + if(!ret && (other instanceof MimeParam)) { + MimeParam mh = (MimeParam)other; + ret = + ((this.paramName == null) ? mh.paramName == null : this.paramName.equals(mh.paramName)) && + ((this.paramValue == null) ? mh.paramValue == null : this.paramValue.equals(mh.paramValue)); + } + return ret; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((paramName == null) ? 0 : paramName.hashCode()); + result = prime * result + + ((paramValue == null) ? 0 : paramValue.hashCode()); + return result; + } + + @Override + public String toString() { + return "#"; + } +}// MimeParam diff --git a/src/org/jruby/ext/openssl/impl/NotVerifiedPKCS7Exception.java b/src/org/jruby/ext/openssl/impl/NotVerifiedPKCS7Exception.java new file mode 100644 index 00000000000..12d5b0f9652 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/NotVerifiedPKCS7Exception.java @@ -0,0 +1,40 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** + * + * @author Ola Bini + */ +public class NotVerifiedPKCS7Exception extends PKCS7Exception { + private static final long serialVersionUID = 1L; + + public NotVerifiedPKCS7Exception() { + super(-1, -1); + } +}// NotVerifiedPKCS7Exception diff --git a/src/org/jruby/ext/openssl/impl/NullSinkBIO.java b/src/org/jruby/ext/openssl/impl/NullSinkBIO.java new file mode 100644 index 00000000000..f75dd2734a8 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/NullSinkBIO.java @@ -0,0 +1,52 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; + +/** + * + * @author Ola Bini + */ +public class NullSinkBIO extends BIO { + public int gets(byte[] in, int len) throws IOException { + return 0; + } + + public int write(byte[] out, int offset, int len) throws IOException { + return len; + } + + public int read(byte[] into, int offset, int len) throws IOException { + return 0; + } + + public int getType() { + return TYPE_NULL; + } +}// NullSinkBIO diff --git a/src/org/jruby/ext/openssl/impl/PKCS7.java b/src/org/jruby/ext/openssl/impl/PKCS7.java new file mode 100644 index 00000000000..4b4118cd44a --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7.java @@ -0,0 +1,1265 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Signature; +import java.security.cert.X509CRL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.TimeZone; +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.SecretKey; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.RC2ParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.DERUTCTime; +import org.bouncycastle.asn1.pkcs.IssuerAndSerialNumber; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.X509Name; +import org.jruby.ext.openssl.OpenSSLReal; +import org.jruby.ext.openssl.x509store.Name; +import org.jruby.ext.openssl.x509store.Store; +import org.jruby.ext.openssl.x509store.StoreContext; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; +import org.jruby.ext.openssl.x509store.X509Utils; + +/** c: PKCS7 + * + * Basically equivalent of the ContentInfo structures in PKCS#7. + * + * @author Ola Bini + */ +public class PKCS7 { + /* content as defined by the type */ + /* all encryption/message digests are applied to the 'contents', + * leaving out the 'type' field. */ + private PKCS7Data data; + + public Object ctrl(int cmd, Object v, Object ignored) throws PKCS7Exception { + return this.data.ctrl(cmd, v, ignored); + } + + public void setDetached(int v) throws PKCS7Exception { + ctrl(OP_SET_DETACHED_SIGNATURE, Integer.valueOf(v), null); + } + + public int getDetached() throws PKCS7Exception { + return ((Integer)ctrl(OP_GET_DETACHED_SIGNATURE, null, null)).intValue(); + } + + public boolean isDetached() throws PKCS7Exception { + return isSigned() && getDetached() != 0; + } + + private void initiateWith(Integer nid, DEREncodable content) throws PKCS7Exception { + this.data = PKCS7Data.fromASN1(nid, content); + } + + /** + * ContentInfo ::= SEQUENCE { + * contentType ContentType, + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + * + * ContentType ::= OBJECT IDENTIFIER + */ + public static PKCS7 fromASN1(DEREncodable obj) throws PKCS7Exception { + int size = ((ASN1Sequence)obj).size(); + if(size == 0) { + return new PKCS7(); + } + + DERObjectIdentifier contentType = (DERObjectIdentifier)(((ASN1Sequence)obj).getObjectAt(0)); + int nid = ASN1Registry.obj2nid(contentType); + + DEREncodable content = size == 1 ? (DEREncodable)null : ((ASN1Sequence)obj).getObjectAt(1); + + if(content != null && content instanceof DERTaggedObject && ((DERTaggedObject)content).getTagNo() == 0) { + content = ((DERTaggedObject)content).getObject(); + } + + PKCS7 p7 = new PKCS7(); + p7.initiateWith(nid, content); + return p7; + } + + /* c: d2i_PKCS7_bio + * + */ + public static PKCS7 fromASN1(BIO bio) throws IOException, PKCS7Exception { + ASN1InputStream ais = new ASN1InputStream(BIO.asInputStream(bio)); + return fromASN1(ais.readObject()); + } + + public ASN1Encodable asASN1() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + DERObjectIdentifier contentType = ASN1Registry.nid2obj(getType()); + vector.add(contentType); + vector.add(new DERTaggedObject(0, data.asASN1())); + + return new DERSequence(vector); + } + + /* c: i2d_PKCS7 + * + */ + public byte[] toASN1() throws IOException { + return asASN1().getEncoded(); + } + + /* c: PKCS7_add_signature + * + */ + public SignerInfoWithPkey addSignature(X509AuxCertificate x509, PrivateKey pkey, MessageDigest dgst) throws PKCS7Exception{ + SignerInfoWithPkey si = new SignerInfoWithPkey(); + si.set(x509, pkey, dgst); + addSigner(si); + return si; + } + + /* c: X509_find_by_issuer_and_serial + * + */ + public static X509AuxCertificate findByIssuerAndSerial(Collection certs, X509Name issuer, BigInteger serial) { + Name name = new Name(issuer); + for(X509AuxCertificate cert : certs) { + if(name.isEqual(cert.getIssuerX500Principal()) && serial.equals(cert.getSerialNumber())) { + return cert; + } + } + return null; + } + + + /* c: PKCS7_get0_signers + * + */ + public List getSigners(Collection certs, List sinfos, int flags) throws PKCS7Exception { + List signers = new ArrayList(); + + if(!isSigned()) { + throw new PKCS7Exception(F_PKCS7_GET0_SIGNERS,R_WRONG_CONTENT_TYPE); + } + + if(sinfos.size() == 0) { + throw new PKCS7Exception(F_PKCS7_GET0_SIGNERS,R_NO_SIGNERS); + } + + for(SignerInfoWithPkey si : sinfos) { + IssuerAndSerialNumber ias = si.getIssuerAndSerialNumber(); + X509AuxCertificate signer = null; +// System.err.println("looking for: " + ias.getName() + " and " + ias.getCertificateSerialNumber()); +// System.err.println(" in: " + certs); +// System.err.println(" in: " + getSign().getCert()); + if(certs != null) { + signer = findByIssuerAndSerial(certs, ias.getName(), ias.getCertificateSerialNumber().getValue()); + } + if(signer == null && (flags & NOINTERN) == 0 && getSign().getCert() != null) { + signer = findByIssuerAndSerial(getSign().getCert(), ias.getName(), ias.getCertificateSerialNumber().getValue()); + } + if(signer == null) { + throw new PKCS7Exception(F_PKCS7_GET0_SIGNERS,R_SIGNER_CERTIFICATE_NOT_FOUND); + } + signers.add(signer); + } + return signers; + } + + /* c: PKCS7_digest_from_attributes + * + */ + public ASN1OctetString digestFromAttributes(ASN1Set attributes) { + return (ASN1OctetString)SignerInfoWithPkey.getAttribute(attributes, ASN1Registry.NID_pkcs9_messageDigest); + } + + /* c: PKCS7_signatureVerify + * + */ + public void signatureVerify(BIO bio, SignerInfoWithPkey si, X509AuxCertificate x509) throws PKCS7Exception { + if(!isSigned() && !isSignedAndEnveloped()) { + throw new PKCS7Exception(F_PKCS7_SIGNATUREVERIFY, R_WRONG_PKCS7_TYPE); + } + + int md_type = ASN1Registry.obj2nid(si.getDigestAlgorithm().getObjectId()); + BIO btmp = bio; + MessageDigest mdc = null; + + for(;;) { + if(btmp == null || (btmp = bio.findType(BIO.TYPE_MD)) == null) { + throw new PKCS7Exception(F_PKCS7_SIGNATUREVERIFY, R_UNABLE_TO_FIND_MESSAGE_DIGEST); + } + + mdc = ((MessageDigestBIOFilter)btmp).getMessageDigest(); + if(null == mdc) { + throw new PKCS7Exception(F_PKCS7_SIGNATUREVERIFY, -1); + } + + if(EVP.type(mdc) == md_type) { + break; + } + + btmp = btmp.next(); + } + + MessageDigest mdc_tmp = null; + try { + mdc_tmp = (MessageDigest)mdc.clone(); + } catch(Exception e) {} + + byte[] currentData = new byte[0]; + + ASN1Set sk = si.getAuthenticatedAttributes(); + try { + if(sk != null && sk.size() > 0) { + byte[] md_dat = mdc_tmp.digest(); + ASN1OctetString message_digest = digestFromAttributes(sk); + if(message_digest == null) { + throw new PKCS7Exception(F_PKCS7_SIGNATUREVERIFY, R_UNABLE_TO_FIND_MESSAGE_DIGEST); + } + if(!Arrays.equals(md_dat, message_digest.getOctets())) { + throw new NotVerifiedPKCS7Exception(); + } + + currentData = sk.getEncoded(); + } + + ASN1OctetString os = si.getEncryptedDigest(); + PublicKey pkey = x509.getPublicKey(); + + Signature sign = Signature.getInstance(EVP.signatureAlgorithm(mdc_tmp, pkey)); + sign.initVerify(pkey); + if(currentData.length > 0) { + sign.update(currentData); + } + if(!sign.verify(os.getOctets())) { + throw new NotVerifiedPKCS7Exception(); + } + } catch(NotVerifiedPKCS7Exception e) { + throw e; + } catch(Exception e) { + System.err.println("Other exception"); + e.printStackTrace(); + throw new NotVerifiedPKCS7Exception(); + } + } + + /* c: PKCS7_verify + * + */ + public void verify(Collection certs, Store store, BIO indata, BIO out, int flags) throws PKCS7Exception { + if(!isSigned()) { + throw new PKCS7Exception(F_PKCS7_VERIFY, R_WRONG_CONTENT_TYPE); + } + + if(getDetached() != 0 && indata == null) { + throw new PKCS7Exception(F_PKCS7_VERIFY, R_NO_CONTENT); + } + + List sinfos = new ArrayList(getSignerInfo()); + if(sinfos.size() == 0) { + throw new PKCS7Exception(F_PKCS7_VERIFY, R_NO_SIGNATURES_ON_DATA); + } + + List signers = getSigners(certs, sinfos, flags); + if(signers == null) { + throw new NotVerifiedPKCS7Exception(); + } + + /* Now verify the certificates */ + if((flags & NOVERIFY) == 0) { + for(X509AuxCertificate signer : signers) { + StoreContext cert_ctx = new StoreContext(); + if((flags & NOCHAIN) == 0) { + if(cert_ctx.init(store, signer, new ArrayList(getSign().getCert())) == 0) { + throw new PKCS7Exception(F_PKCS7_VERIFY, -1); + } + cert_ctx.setPurpose(X509Utils.X509_PURPOSE_SMIME_SIGN); + } else if(cert_ctx.init(store, signer, null) == 0) { + throw new PKCS7Exception(F_PKCS7_VERIFY, -1); + } + cert_ctx.setExtraData(1, store.getExtraData(1)); + if((flags & NOCRL) == 0) { + cert_ctx.setCRLs((List)getSign().getCrl()); + } + try { + int i = cert_ctx.verifyCertificate(); + int j = 0; + if(i <= 0) { + j = cert_ctx.getError(); + } + cert_ctx.cleanup(); + if(i <= 0) { + throw new PKCS7Exception(F_PKCS7_VERIFY, R_CERTIFICATE_VERIFY_ERROR, "Verify error:" + X509Utils.verifyCertificateErrorString(j)); + } + } catch(PKCS7Exception e) { + throw e; + } catch(Exception e) { + throw new PKCS7Exception(F_PKCS7_VERIFY, R_CERTIFICATE_VERIFY_ERROR, e); + } + } + } + + BIO tmpin = indata; + BIO p7bio = dataInit(tmpin); + BIO tmpout = null; + if((flags & TEXT) != 0) { + tmpout = BIO.mem(); + } else { + tmpout = out; + } + + byte[] buf = new byte[4096]; + for(;;) { + try { + int i = p7bio.read(buf, 0, buf.length); + if(i <= 0) { + break; + } + if(tmpout != null) { + tmpout.write(buf, 0, i); + } + } catch(IOException e) { + throw new PKCS7Exception(F_PKCS7_VERIFY, -1, e); + } + } + + if((flags & TEXT) != 0) { + new SMIME(Mime.DEFAULT).text(tmpout, out); + } + + if((flags & NOSIGS) == 0) { + for(int i=0; i certs, BIO data, int flags) throws PKCS7Exception { + PKCS7 p7 = new PKCS7(); + p7.setType(ASN1Registry.NID_pkcs7_signed); + p7.contentNew(ASN1Registry.NID_pkcs7_data); + SignerInfoWithPkey si = p7.addSignature(signcert, pkey, EVP.sha1()); + if((flags & NOCERTS) == 0) { + p7.addCertificate(signcert); + if(certs != null) { + for(X509AuxCertificate c : certs) { + p7.addCertificate(c); + } + } + } + + if((flags & NOATTR) == 0) { + si.addSignedAttribute(ASN1Registry.NID_pkcs9_contentType, ASN1Registry.nid2obj(ASN1Registry.NID_pkcs7_data)); + if((flags & NOSMIMECAP) == 0) { + ASN1EncodableVector smcap = new ASN1EncodableVector(); + smcap.add(new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_des_ede3_cbc))); + smcap.add(new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_rc2_cbc), new DERInteger(128))); + smcap.add(new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_rc2_cbc), new DERInteger(64))); + smcap.add(new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_rc2_cbc), new DERInteger(40))); + smcap.add(new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_des_cbc))); + si.addSignedAttribute(ASN1Registry.NID_SMIMECapabilities, new DERSequence(smcap)); + } + } + + if((flags & STREAM) != 0) { + return p7; + } + + BIO p7bio = p7.dataInit(null); + + try { + data.crlfCopy(p7bio, flags); + } catch(IOException e) { + throw new PKCS7Exception(F_PKCS7_SIGN, R_PKCS7_DATAFINAL_ERROR, e); + } + + if((flags & DETACHED) != 0) { + p7.setDetached(1); + } + + p7.dataFinal(p7bio); + + return p7; + } + + /* c: PKCS7_encrypt + * + */ + public static PKCS7 encrypt(Collection certs, byte[] in, CipherSpec cipher, int flags) throws PKCS7Exception { + PKCS7 p7 = new PKCS7(); + + p7.setType(ASN1Registry.NID_pkcs7_enveloped); + + try { + p7.setCipher(cipher); + + for(X509AuxCertificate x509 : certs) { + p7.addRecipient(x509); + } + + BIO p7bio = p7.dataInit(null); + + BIO.memBuf(in).crlfCopy(p7bio, flags); + p7bio.flush(); + p7.dataFinal(p7bio); + + return p7; + } catch(IOException e) { + throw new PKCS7Exception(F_PKCS7_ENCRYPT, R_PKCS7_DATAFINAL_ERROR, e); + } + } + + /* c: PKCS7_decrypt + * + */ + public void decrypt(PrivateKey pkey, X509AuxCertificate cert, BIO data, int flags) throws PKCS7Exception { + if(!isEnveloped()) { + throw new PKCS7Exception(F_PKCS7_DECRYPT, R_WRONG_CONTENT_TYPE); + } + try { + BIO tmpmem = dataDecode(pkey, null, cert); + if((flags & TEXT) == TEXT) { + BIO tmpbuf = BIO.buffered(); + BIO bread = tmpbuf.push(tmpmem); + new SMIME(Mime.DEFAULT).text(bread, data); + } else { + int i; + byte[] buf = new byte[4096]; + while((i = tmpmem.read(buf, 0, 4096)) > 0) { + data.write(buf, 0, i); + } + } + } catch(IOException e) { + throw new PKCS7Exception(F_PKCS7_DECRYPT, R_DECRYPT_ERROR, e); + } + } + + /** c: PKCS7_set_type + * + */ + public void setType(int type) throws PKCS7Exception { + switch(type) { + case ASN1Registry.NID_pkcs7_signed: + this.data = new PKCS7DataSigned(); + break; + case ASN1Registry.NID_pkcs7_data: + this.data = new PKCS7DataData(); + break; + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + this.data = new PKCS7DataSignedAndEnveloped(); + break; + case ASN1Registry.NID_pkcs7_enveloped: + this.data = new PKCS7DataEnveloped(); + break; + case ASN1Registry.NID_pkcs7_encrypted: + this.data = new PKCS7DataEncrypted(); + break; + case ASN1Registry.NID_pkcs7_digest: + this.data = new PKCS7DataDigest(); + break; + default: + throw new PKCS7Exception(F_PKCS7_SET_TYPE,R_UNSUPPORTED_CONTENT_TYPE); + } + } + + /** c: PKCS7_set_cipher + * + */ + public void setCipher(CipherSpec cipher) throws PKCS7Exception { + this.data.setCipher(cipher); + } + + /** c: PKCS7_add_recipient + * + */ + public RecipInfo addRecipient(X509AuxCertificate recip) throws PKCS7Exception { + RecipInfo ri = new RecipInfo(); + ri.set(recip); + addRecipientInfo(ri); + return ri; + } + + /** c: PKCS7_content_new + * + */ + public void contentNew(int nid) throws PKCS7Exception { + PKCS7 ret = new PKCS7(); + ret.setType(nid); + this.setContent(ret); + } + + /** c: PKCS7_add_signer + * + */ + public void addSigner(SignerInfoWithPkey psi) throws PKCS7Exception { + this.data.addSigner(psi); + } + + /** c: PKCS7_add_certificate + * + */ + public void addCertificate(X509AuxCertificate cert) throws PKCS7Exception { + this.data.addCertificate(cert); + } + + /** c: PKCS7_add_crl + * + */ + public void addCRL(X509CRL crl) throws PKCS7Exception { + this.data.addCRL(crl); + } + + /** c: PKCS7_add_recipient_info + * + */ + public void addRecipientInfo(RecipInfo ri) throws PKCS7Exception { + this.data.addRecipientInfo(ri); + } + + /** c: PKCS7_set_content + * + */ + public void setContent(PKCS7 p7) throws PKCS7Exception { + this.data.setContent(p7); + } + + /** c: PKCS7_get_signer_info + * + */ + public Collection getSignerInfo() { + return this.data.getSignerInfo(); + } + + private final static byte[] PEM_STRING_PKCS7_START = "-----BEGIN PKCS7-----".getBytes(); + + /** c: PEM_read_bio_PKCS7 + * + */ + public static PKCS7 readPEM(BIO input) throws PKCS7Exception { + try { + byte[] buffer = new byte[SMIME.MAX_SMLEN]; + int read = -1; + read = input.gets(buffer, SMIME.MAX_SMLEN); + if(read > PEM_STRING_PKCS7_START.length) { + byte[] tmp = new byte[PEM_STRING_PKCS7_START.length]; + System.arraycopy(buffer, 0, tmp, 0, tmp.length); + if(Arrays.equals(PEM_STRING_PKCS7_START, tmp)) { + return fromASN1(BIO.base64Filter(input)); + } else { + return null; + } + } else { + return null; + } + } catch(IOException e) { + return null; + } + } + + /** c: stati PKCS7_bio_add_digest + * + */ + public BIO bioAddDigest(BIO pbio, AlgorithmIdentifier alg) throws PKCS7Exception { + try { + MessageDigest md = EVP.getDigest(alg.getObjectId()); + BIO btmp = BIO.mdFilter(md); + if(pbio == null) { + return btmp; + } else { + pbio.push(btmp); + return pbio; + } + } catch(Exception e) { + throw new PKCS7Exception(F_PKCS7_BIO_ADD_DIGEST, R_UNKNOWN_DIGEST_TYPE, e); + } + } + + /** c: PKCS7_dataDecode + * + */ + public BIO dataDecode(PrivateKey pkey, BIO inBio, X509AuxCertificate pcert) throws PKCS7Exception { + BIO out = null; + BIO btmp = null; + BIO etmp = null; + BIO bio = null; + byte[] dataBody = null; + Collection mdSk = null; + Collection rsk = null; + AlgorithmIdentifier encAlg = null; + Cipher evpCipher = null; + RecipInfo ri = null; + + int i = getType(); + switch(i) { + case ASN1Registry.NID_pkcs7_signed: + dataBody = getSign().getContents().getOctetString().getOctets(); + mdSk = getSign().getMdAlgs(); + break; + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + rsk = getSignedAndEnveloped().getRecipientInfo(); + mdSk = getSignedAndEnveloped().getMdAlgs(); + dataBody = getSignedAndEnveloped().getEncData().getEncData().getOctets(); + encAlg = getSignedAndEnveloped().getEncData().getAlgorithm(); + try { + evpCipher = getCipher(encAlg.getObjectId()); + } catch(Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_UNSUPPORTED_CIPHER_TYPE, e); + } + break; + case ASN1Registry.NID_pkcs7_enveloped: + rsk = getEnveloped().getRecipientInfo(); + dataBody = getEnveloped().getEncData().getEncData().getOctets(); + encAlg = getEnveloped().getEncData().getAlgorithm(); + try { + evpCipher = getCipher(encAlg.getObjectId()); + } catch(Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_UNSUPPORTED_CIPHER_TYPE, e); + } + break; + default: + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_UNSUPPORTED_CONTENT_TYPE); + } + + /* We will be checking the signature */ + if(mdSk != null) { + for(AlgorithmIdentifier xa : mdSk) { + try { + MessageDigest evpMd = EVP.getDigest(xa.getObjectId()); + btmp = BIO.mdFilter(evpMd); + if(out == null) { + out = btmp; + } else { + out.push(btmp); + } + btmp = null; + } catch(Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_UNKNOWN_DIGEST_TYPE, e); + } + } + } + + + if(evpCipher != null) { + + /* It was encrypted, we need to decrypt the secret key + * with the private key */ + + /* Find the recipientInfo which matches the passed certificate + * (if any) + */ + if(pcert != null) { + for(Iterator iter = rsk.iterator(); iter.hasNext();) { + ri = iter.next(); + if(ri.compare(pcert)) { + break; + } + ri = null; + } + if(null == ri) { + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_NO_RECIPIENT_MATCHES_CERTIFICATE); + } + } + + byte[] tmp = null; + /* If we haven't got a certificate try each ri in turn */ + if(null == pcert) { + for(Iterator iter = rsk.iterator(); iter.hasNext();) { + ri = iter.next(); + try { + tmp = EVP.decrypt(ri.getEncKey().getOctets(), pkey); + if(tmp != null) { + break; + } + } catch(Exception e) { + tmp = null; + } + ri = null; + } + if(ri == null) { + throw new PKCS7Exception(F_PKCS7_DATADECODE, R_NO_RECIPIENT_MATCHES_KEY); + } + } else { + try { + Cipher cipher = Cipher.getInstance(CipherSpec.getWrappingAlgorithm(pkey.getAlgorithm())); + cipher.init(Cipher.DECRYPT_MODE, pkey); + tmp = cipher.doFinal(ri.getEncKey().getOctets()); + } catch (Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATADECODE, -1, e); + } + } + + DEREncodable params = encAlg.getParameters(); + try { + if(params != null && params instanceof ASN1OctetString) { + if (evpCipher.getAlgorithm().startsWith("RC2")) { + // J9's IBMJCE needs this exceptional RC2 support. + // Giving IvParameterSpec throws 'Illegal parameter' on IBMJCE. + SecretKeySpec sks = new SecretKeySpec(tmp, evpCipher.getAlgorithm()); + RC2ParameterSpec s = new RC2ParameterSpec(tmp.length * 8, ((ASN1OctetString) params).getOctets()); + evpCipher.init(Cipher.DECRYPT_MODE, sks, s); + } else { + SecretKeySpec sks = new SecretKeySpec(tmp, evpCipher.getAlgorithm()); + IvParameterSpec iv = new IvParameterSpec(((ASN1OctetString) params).getOctets()); + evpCipher.init(Cipher.DECRYPT_MODE, sks, iv); + } + } else { + evpCipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(tmp, evpCipher.getAlgorithm())); + } + } catch(Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATADECODE, -1, e); + } + + etmp = BIO.cipherFilter(evpCipher); + if(out == null) { + out = etmp; + } else { + out.push(etmp); + } + etmp = null; + } + + if(isDetached() || inBio != null) { + bio = inBio; + } else { + if(dataBody != null && dataBody.length > 0) { + bio = BIO.memBuf(dataBody); + } else { + bio = BIO.mem(); + } + } + out.push(bio); + bio = null; + return out; + } + + // Without Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files, + // getting Cipher object via OID(1.2.840.113549.3.7 - DES-EDE3-CBC) causes 'Illegal Key Length' + // exception. To avoid this, we get Cipher object via algo name(DESede/cbc/PKCS5Padding). + private static Cipher getCipher(DERObjectIdentifier oid) throws GeneralSecurityException { + // check DES-EDE3-CBC + if (oid.getId().equals("1.2.840.113549.3.7")) { + return OpenSSLReal.getCipherBC("DESede/cbc/PKCS5Padding"); + } + return EVP.getCipher(oid); + } + + /** c: PKCS7_dataInit + * + */ + public BIO dataInit(BIO bio) throws PKCS7Exception { + Collection mdSk = null; + ASN1OctetString os = null; + int i = this.data.getType(); + Collection rsk = null; + AlgorithmIdentifier xa = null; + CipherSpec evpCipher = null; + BIO out = null; + BIO btmp = null; + EncContent enc = null; + switch (i) { + case ASN1Registry.NID_pkcs7_signed: + mdSk = getSign().getMdAlgs(); + os = getSign().getContents().getOctetString(); + break; + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + rsk = getSignedAndEnveloped().getRecipientInfo(); + mdSk = getSignedAndEnveloped().getMdAlgs(); + enc = getSignedAndEnveloped().getEncData(); + evpCipher = getSignedAndEnveloped().getEncData().getCipher(); + if (null == evpCipher) { + throw new PKCS7Exception(F_PKCS7_DATAINIT, R_CIPHER_NOT_INITIALIZED); + } + break; + case ASN1Registry.NID_pkcs7_enveloped: + rsk = getEnveloped().getRecipientInfo(); + enc = getEnveloped().getEncData(); + evpCipher = getEnveloped().getEncData().getCipher(); + if (null == evpCipher) { + throw new PKCS7Exception(F_PKCS7_DATAINIT, R_CIPHER_NOT_INITIALIZED); + } + break; + case ASN1Registry.NID_pkcs7_digest: + xa = getDigest().getMd(); + os = getDigest().getContents().getOctetString(); + break; + default: + throw new PKCS7Exception(F_PKCS7_DATAINIT, R_UNSUPPORTED_CONTENT_TYPE); + } + + if (mdSk != null) { + for (AlgorithmIdentifier ai : mdSk) { + if ((out = bioAddDigest(out, ai)) == null) { + return null; + } + } + } + + if (xa != null && (out = bioAddDigest(out, xa)) == null) { + return null; + } + + if (evpCipher != null) { + byte[] tmp; + btmp = BIO.cipherFilter(evpCipher.getCipher()); + String algoBase = evpCipher.getCipher().getAlgorithm(); + if (algoBase.indexOf('/') != -1) { + algoBase = algoBase.split("/")[0]; + } + try { + KeyGenerator gen = KeyGenerator.getInstance(algoBase); + gen.init(evpCipher.getKeyLenInBits(), new SecureRandom()); + SecretKey key = gen.generateKey(); + evpCipher.getCipher().init(Cipher.ENCRYPT_MODE, key); + if (null != rsk) { + for (RecipInfo ri : rsk) { + PublicKey pkey = ri.getCert().getPublicKey(); + Cipher cipher = Cipher.getInstance(CipherSpec.getWrappingAlgorithm(pkey.getAlgorithm())); + cipher.init(Cipher.ENCRYPT_MODE, pkey); + tmp = cipher.doFinal(key.getEncoded()); + ri.setEncKey(new DEROctetString(tmp)); + } + } + } catch (Exception e) { + e.printStackTrace(System.err); + throw new PKCS7Exception(F_PKCS7_DATAINIT, R_ERROR_SETTING_CIPHER, e); + } + + DERObjectIdentifier encAlgo = ASN1Registry.sym2oid(evpCipher.getOsslName()); + if (encAlgo == null) { + throw new PKCS7Exception(F_PKCS7_DATAINIT, R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); + } + if (evpCipher.getCipher().getIV() != null) { + enc.setAlgorithm(new AlgorithmIdentifier(encAlgo, new DEROctetString(evpCipher.getCipher().getIV()))); + } else { + enc.setAlgorithm(new AlgorithmIdentifier(encAlgo)); + } + + if (out == null) { + out = btmp; + } else { + out.push(btmp); + } + btmp = null; + } + + if (bio == null) { + if (isDetached()) { + bio = BIO.nullSink(); + } else if (os != null && os.getOctets().length > 0) { + bio = BIO.memBuf(os.getOctets()); + } + if (bio == null) { + bio = BIO.mem(); + bio.setMemEofReturn(0); + } + } + out.push(bio); + bio = null; + return out; + } + + /** c: static PKCS7_find_digest + * + */ + public BIO findDigest(MessageDigest[] pmd, BIO bio, int nid) throws PKCS7Exception { + while(true) { + bio = bio.findType(BIO.TYPE_MD); + if(bio == null) { + throw new PKCS7Exception(F_PKCS7_FIND_DIGEST, R_UNABLE_TO_FIND_MESSAGE_DIGEST); + } + pmd[0] = ((MessageDigestBIOFilter)bio).getMessageDigest(); + if(pmd[0] == null) { + throw new PKCS7Exception(F_PKCS7_FIND_DIGEST, -1); + } + + if(nid == EVP.type(pmd[0])) { + return bio; + } + + bio = bio.next(); + } + } + + /** c: PKCS7_dataFinal + * + */ + public int dataFinal(BIO bio) throws PKCS7Exception { + Collection siSk = null; + BIO btmp; + byte[] buf; + MessageDigest mdc = null; + MessageDigest ctx_tmp = null; + ASN1Set sk; + + int i = this.data.getType(); + + switch(i) { + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + siSk = getSignedAndEnveloped().getSignerInfo(); + break; + case ASN1Registry.NID_pkcs7_signed: + siSk = getSign().getSignerInfo(); + break; + case ASN1Registry.NID_pkcs7_digest: + break; + default: + break; + } + + if(siSk != null) { + for(SignerInfoWithPkey si : siSk) { + if(si.getPkey() == null) { + continue; + } + int j = ASN1Registry.obj2nid(si.getDigestAlgorithm().getObjectId()); + btmp = bio; + MessageDigest[] _mdc = new MessageDigest[] {mdc}; + btmp = findDigest(_mdc, btmp, j); + mdc = _mdc[0]; + if(btmp == null) { + return 0; + } + + try { + ctx_tmp = (MessageDigest)mdc.clone(); + } catch(CloneNotSupportedException e) { + throw new RuntimeException(e); + } + + sk = si.getAuthenticatedAttributes(); + + Signature sign = null; + + try { + if(sk != null && sk.size() > 0) { + /* Add signing time if not already present */ + if(null == si.getSignedAttribute(ASN1Registry.NID_pkcs9_signingTime)) { + DERUTCTime signTime = new DERUTCTime(Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime()); + si.addSignedAttribute(ASN1Registry.NID_pkcs9_signingTime, signTime); + } + + byte[] md_data = ctx_tmp.digest(); + ASN1OctetString digest = new DEROctetString(md_data); + si.addSignedAttribute(ASN1Registry.NID_pkcs9_messageDigest, digest); + + sk = si.getAuthenticatedAttributes(); + sign = Signature.getInstance(EVP.signatureAlgorithm(ctx_tmp, si.getPkey())); + sign.initSign(si.getPkey()); + + byte[] abuf = sk.getEncoded(); + sign.update(abuf); + } + + if(sign != null) { + byte[] out = sign.sign(); + si.setEncryptedDigest(new DEROctetString(out)); + } + } catch(Exception e) { + throw new PKCS7Exception(F_PKCS7_DATAFINAL, -1, e); + } + } + } else if(i == ASN1Registry.NID_pkcs7_digest) { + int nid = ASN1Registry.obj2nid(getDigest().getMd().getObjectId()); + MessageDigest[] _mdc = new MessageDigest[] {mdc}; + bio = findDigest(_mdc, bio, nid); + mdc = _mdc[0]; + byte[] md_data = mdc.digest(); + ASN1OctetString digest = new DEROctetString(md_data); + getDigest().setDigest(digest); + } + + if(!isDetached()) { + btmp = bio.findType(BIO.TYPE_MEM); + if(null == btmp) { + throw new PKCS7Exception(F_PKCS7_DATAFINAL, R_UNABLE_TO_FIND_MEM_BIO); + } + buf = ((MemBIO)btmp).getMemCopy(); + switch(i) { + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + getSignedAndEnveloped().getEncData().setEncData(new DEROctetString(buf)); + break; + case ASN1Registry.NID_pkcs7_enveloped: + getEnveloped().getEncData().setEncData(new DEROctetString(buf)); + break; + case ASN1Registry.NID_pkcs7_signed: + if(getSign().getContents().isData() && getDetached() != 0) { + getSign().getContents().setData(null); + } else { + getSign().getContents().setData(new DEROctetString(buf)); + } + break; + case ASN1Registry.NID_pkcs7_digest: + if(getDigest().getContents().isData() && getDetached() != 0) { + getDigest().getContents().setData(null); + } else { + getDigest().getContents().setData(new DEROctetString(buf)); + } + break; + } + } + + return 1; + } + + @Override + public String toString() { + return "#"; + } + + public static final int S_HEADER = 0; + public static final int S_BODY = 1; + public static final int S_TAIL = 2; + + public static final int OP_SET_DETACHED_SIGNATURE = 1; + public static final int OP_GET_DETACHED_SIGNATURE = 2; + + /* S/MIME related flags */ + public static final int TEXT = 0x1; + public static final int NOCERTS = 0x2; + public static final int NOSIGS = 0x4; + public static final int NOCHAIN = 0x8; + public static final int NOINTERN = 0x10; + public static final int NOVERIFY = 0x20; + public static final int DETACHED = 0x40; + public static final int BINARY = 0x80; + public static final int NOATTR = 0x100; + public static final int NOSMIMECAP = 0x200; + public static final int NOOLDMIMETYPE = 0x400; + public static final int CRLFEOL = 0x800; + public static final int STREAM = 0x1000; + public static final int NOCRL = 0x2000; + + /* Flags: for compatibility with older code */ + public static final int SMIME_TEXT = TEXT; + public static final int SMIME_NOCERTS = NOCERTS; + public static final int SMIME_NOSIGS = NOSIGS; + public static final int SMIME_NOCHAIN = NOCHAIN; + public static final int SMIME_NOINTERN = NOINTERN; + public static final int SMIME_NOVERIFY = NOVERIFY; + public static final int SMIME_DETACHED = DETACHED; + public static final int SMIME_BINARY = BINARY; + public static final int SMIME_NOATTR = NOATTR; + + /* Function codes. */ + public static final int F_B64_READ_PKCS7 = 120; + public static final int F_B64_WRITE_PKCS7 = 121; + public static final int F_PKCS7_ADD_ATTRIB_SMIMECAP = 118; + public static final int F_PKCS7_ADD_CERTIFICATE = 100; + public static final int F_PKCS7_ADD_CRL = 101; + public static final int F_PKCS7_ADD_RECIPIENT_INFO = 102; + public static final int F_PKCS7_ADD_SIGNER = 103; + public static final int F_PKCS7_BIO_ADD_DIGEST = 125; + public static final int F_PKCS7_CTRL = 104; + public static final int F_PKCS7_DATADECODE = 112; + public static final int F_PKCS7_DATAFINAL = 128; + public static final int F_PKCS7_DATAINIT = 105; + public static final int F_PKCS7_DATASIGN = 106; + public static final int F_PKCS7_DATAVERIFY = 107; + public static final int F_PKCS7_DECRYPT = 114; + public static final int F_PKCS7_ENCRYPT = 115; + public static final int F_PKCS7_FIND_DIGEST = 127; + public static final int F_PKCS7_GET0_SIGNERS = 124; + public static final int F_PKCS7_SET_CIPHER = 108; + public static final int F_PKCS7_SET_CONTENT = 109; + public static final int F_PKCS7_SET_DIGEST = 126; + public static final int F_PKCS7_SET_TYPE = 110; + public static final int F_PKCS7_SIGN = 116; + public static final int F_PKCS7_SIGNATUREVERIFY = 113; + public static final int F_PKCS7_SIMPLE_SMIMECAP = 119; + public static final int F_PKCS7_VERIFY = 117; + public static final int F_SMIME_READ_PKCS7 = 122; + public static final int F_SMIME_TEXT = 123; + + /* Reason codes. */ + public static final int R_CERTIFICATE_VERIFY_ERROR = 117; + public static final int R_CIPHER_HAS_NO_OBJECT_IDENTIFIER = 144; + public static final int R_CIPHER_NOT_INITIALIZED = 116; + public static final int R_CONTENT_AND_DATA_PRESENT = 118; + public static final int R_DECODE_ERROR = 130; + public static final int R_DECRYPTED_KEY_IS_WRONG_LENGTH = 100; + public static final int R_DECRYPT_ERROR = 119; + public static final int R_DIGEST_FAILURE = 101; + public static final int R_ERROR_ADDING_RECIPIENT = 120; + public static final int R_ERROR_SETTING_CIPHER = 121; + public static final int R_INVALID_MIME_TYPE = 131; + public static final int R_INVALID_NULL_POINTER = 143; + public static final int R_MIME_NO_CONTENT_TYPE = 132; + public static final int R_MIME_PARSE_ERROR = 133; + public static final int R_MIME_SIG_PARSE_ERROR = 134; + public static final int R_MISSING_CERIPEND_INFO = 103; + public static final int R_NO_CONTENT = 122; + public static final int R_NO_CONTENT_TYPE = 135; + public static final int R_NO_MULTIPART_BODY_FAILURE = 136; + public static final int R_NO_MULTIPART_BOUNDARY = 137; + public static final int R_NO_RECIPIENT_MATCHES_CERTIFICATE = 115; + public static final int R_NO_RECIPIENT_MATCHES_KEY = 146; + public static final int R_NO_SIGNATURES_ON_DATA = 123; + public static final int R_NO_SIGNERS = 142; + public static final int R_NO_SIG_CONTENT_TYPE = 138; + public static final int R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE = 104; + public static final int R_PKCS7_ADD_SIGNATURE_ERROR = 124; + public static final int R_PKCS7_DATAFINAL = 126; + public static final int R_PKCS7_DATAFINAL_ERROR = 125; + public static final int R_PKCS7_DATASIGN = 145; + public static final int R_PKCS7_PARSE_ERROR = 139; + public static final int R_PKCS7_SIG_PARSE_ERROR = 140; + public static final int R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE = 127; + public static final int R_SIGNATURE_FAILURE = 105; + public static final int R_SIGNER_CERTIFICATE_NOT_FOUND = 128; + public static final int R_SIG_INVALID_MIME_TYPE = 141; + public static final int R_SMIME_TEXT_ERROR = 129; + public static final int R_UNABLE_TO_FIND_CERTIFICATE = 106; + public static final int R_UNABLE_TO_FIND_MEM_BIO = 107; + public static final int R_UNABLE_TO_FIND_MESSAGE_DIGEST = 108; + public static final int R_UNKNOWN_DIGEST_TYPE = 109; + public static final int R_UNKNOWN_OPERATION = 110; + public static final int R_UNSUPPORTED_CIPHER_TYPE = 111; + public static final int R_UNSUPPORTED_CONTENT_TYPE = 112; + public static final int R_WRONG_CONTENT_TYPE = 113; + public static final int R_WRONG_PKCS7_TYPE = 114; + + public Envelope getEnveloped() { + return this.data.getEnveloped(); + } + + public SignEnvelope getSignedAndEnveloped() { + return this.data.getSignedAndEnveloped(); + } + + public Digest getDigest() { + return this.data.getDigest(); + } + + public Encrypt getEncrypted() { + return this.data.getEncrypted(); + } + + public ASN1Encodable getOther() { + return this.data.getOther(); + } + + public void setSign(Signed sign) { + this.data.setSign(sign); + } + + public Signed getSign() { + return this.data.getSign(); + } + + public void setData(ASN1OctetString data) { + this.data.setData(data); + } + + public ASN1OctetString getData() { + return this.data.getData(); + } + + public boolean isSigned() { + return this.data.isSigned(); + } + + public boolean isEncrypted() { + return this.data.isEncrypted(); + } + + public boolean isEnveloped() { + return this.data.isEnveloped(); + } + + public boolean isSignedAndEnveloped() { + return this.data.isSignedAndEnveloped(); + } + + public boolean isData() { + return this.data.isData(); + } + + public boolean isDigest() { + return this.data.isDigest(); + } + + public boolean isOther() { + return this.data.isOther(); + } + + public int getType() { + return this.data.getType(); + } + + /* c: static PKCS7_get_octet_string + * + */ + public ASN1OctetString getOctetString() { + if(isData()) { + return getData(); + } else if(isOther() && getOther() != null && getOther() instanceof ASN1OctetString) { + return (ASN1OctetString)getOther(); + } + return null; + } +}// PKCS7 + diff --git a/src/org/jruby/ext/openssl/impl/PKCS7Data.java b/src/org/jruby/ext/openssl/impl/PKCS7Data.java new file mode 100644 index 00000000000..ad34a565316 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7Data.java @@ -0,0 +1,166 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.security.cert.X509CRL; +import java.util.Collection; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DEREncodable; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** + * @author Ola Bini + */ +public abstract class PKCS7Data { + public abstract int getType(); + + public Object ctrl(int cmd, Object v, Object ignored) throws PKCS7Exception { + switch(cmd) { + case PKCS7.OP_SET_DETACHED_SIGNATURE: + throw new PKCS7Exception(PKCS7.F_PKCS7_CTRL,PKCS7.R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); + case PKCS7.OP_GET_DETACHED_SIGNATURE: + throw new PKCS7Exception(PKCS7.F_PKCS7_CTRL,PKCS7.R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE); + default: + throw new PKCS7Exception(PKCS7.F_PKCS7_CTRL,PKCS7.R_UNKNOWN_OPERATION); + } + } + + public Envelope getEnveloped() { + return null; + } + + public SignEnvelope getSignedAndEnveloped() { + return null; + } + + public Digest getDigest() { + return null; + } + + public Encrypt getEncrypted() { + return null; + } + + public ASN1Encodable getOther() { + return null; + } + + public void setSign(Signed sign) { + } + + public Signed getSign() { + return null; + } + + public void setData(ASN1OctetString data) { + } + + public ASN1OctetString getData() { + return null; + } + + public boolean isSigned() { + return false; + } + + public boolean isEncrypted() { + return false; + } + + public boolean isEnveloped() { + return false; + } + + public boolean isSignedAndEnveloped() { + return false; + } + + public boolean isData() { + return false; + } + + public boolean isDigest() { + return false; + } + + public boolean isOther() { + return false; + } + + public void setCipher(CipherSpec cipher) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_SET_CIPHER,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public void addRecipientInfo(RecipInfo ri) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_ADD_RECIPIENT_INFO,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public void addSigner(SignerInfoWithPkey psi) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_ADD_SIGNER,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public void setContent(PKCS7 p7) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_SET_CONTENT,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public Collection getSignerInfo() { + return null; + } + + public void addCertificate(X509AuxCertificate cert) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_ADD_CERTIFICATE,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public void addCRL(X509CRL crl) throws PKCS7Exception { + throw new PKCS7Exception(PKCS7.F_PKCS7_ADD_CRL,PKCS7.R_WRONG_CONTENT_TYPE); + } + + public static PKCS7Data fromASN1(Integer nid, DEREncodable content) throws PKCS7Exception { + switch(nid) { + case ASN1Registry.NID_pkcs7_data: + return PKCS7DataData.fromASN1(content); + case ASN1Registry.NID_pkcs7_signed: + return PKCS7DataSigned.fromASN1(content); + case ASN1Registry.NID_pkcs7_enveloped: + return PKCS7DataEnveloped.fromASN1(content); + case ASN1Registry.NID_pkcs7_signedAndEnveloped: + return PKCS7DataSignedAndEnveloped.fromASN1(content); + case ASN1Registry.NID_pkcs7_digest: + return PKCS7DataDigest.fromASN1(content); + case ASN1Registry.NID_pkcs7_encrypted: + return PKCS7DataEncrypted.fromASN1(content); + default: + throw new UnsupportedOperationException("can't handle PKCS#7 with content type " + ASN1Registry.nid2ln(nid)); + } + } + + public ASN1Encodable asASN1() { + throw new UnsupportedOperationException("can't ASN1 PKCS#7 with content type " + ASN1Registry.nid2ln(getType())); + } +}// PKCS7Data diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataData.java b/src/org/jruby/ext/openssl/impl/PKCS7DataData.java new file mode 100644 index 00000000000..fc92a6ccef5 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataData.java @@ -0,0 +1,92 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DEROctetString; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataData extends PKCS7Data { + /* NID_pkcs7_data */ + private ASN1OctetString data; + + public PKCS7DataData() { + this(new DEROctetString(new byte[0])); + } + + public PKCS7DataData(ASN1OctetString data) { + this.data = data; + } + + public int getType() { + return ASN1Registry.NID_pkcs7_data; + } + + @Override + public void setData(ASN1OctetString data) { + this.data = data; + } + + @Override + public ASN1OctetString getData() { + return this.data; + } + + @Override + public boolean isData() { + return true; + } + + @Override + public String toString() { + return "#"; + } + + /** + * Data ::= OCTET STRING + */ + public static PKCS7DataData fromASN1(DEREncodable content) { + if(content == null) { + return new PKCS7DataData(); + } + return new PKCS7DataData((ASN1OctetString)content); + } + + @Override + public ASN1Encodable asASN1() { + if(data == null) { + return new DEROctetString(new byte[0]).toASN1Object(); + } + return data.toASN1Object(); + } +}// PKCS7DataData diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataDigest.java b/src/org/jruby/ext/openssl/impl/PKCS7DataDigest.java new file mode 100644 index 00000000000..7395d23f2a4 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataDigest.java @@ -0,0 +1,64 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.DEREncodable; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataDigest extends PKCS7Data { + /* NID_pkcs7_digest */ + private Digest digest; + + public PKCS7DataDigest() { + this.digest = new Digest(); + this.digest.setVersion(0); + } + + public int getType() { + return ASN1Registry.NID_pkcs7_digest; + } + + public Digest getDigest() { + return this.digest; + } + + public boolean isDigest() { + return true; + } + + public void setContent(PKCS7 p7) { + this.digest.setContents(p7); + } + + public static PKCS7DataDigest fromASN1(DEREncodable content) { + throw new UnsupportedOperationException("TODO: can't create DataDigest from ASN1 yet"); + } +}// PKCS7DataDigest diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataEncrypted.java b/src/org/jruby/ext/openssl/impl/PKCS7DataEncrypted.java new file mode 100644 index 00000000000..2a685ea25a9 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataEncrypted.java @@ -0,0 +1,61 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import org.bouncycastle.asn1.DEREncodable; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataEncrypted extends PKCS7Data { + /* NID_pkcs7_encrypted */ + private Encrypt encrypted; + + public PKCS7DataEncrypted() { + this.encrypted = new Encrypt(); + this.encrypted.setVersion(0); + this.encrypted.getEncData().setContentType(ASN1Registry.NID_pkcs7_data); + } + + public int getType() { + return ASN1Registry.NID_pkcs7_encrypted; + } + + public Encrypt getEncrypted() { + return this.encrypted; + } + + public boolean isEncrypted() { + return true; + } + + public static PKCS7DataEncrypted fromASN1(DEREncodable content) { + throw new UnsupportedOperationException("TODO: can't create DataEncrypted from ASN1 yet"); + } +}// PKCS7DataEncrypted diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataEnveloped.java b/src/org/jruby/ext/openssl/impl/PKCS7DataEnveloped.java new file mode 100644 index 00000000000..84d099ef535 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataEnveloped.java @@ -0,0 +1,89 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.DEREncodable; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataEnveloped extends PKCS7Data { + /* NID_pkcs7_enveloped */ + private Envelope enveloped; + + public PKCS7DataEnveloped() { + this.enveloped = new Envelope(); + this.enveloped.setVersion(0); + this.enveloped.getEncData().setContentType(ASN1Registry.NID_pkcs7_data); + } + + public PKCS7DataEnveloped(Envelope enveloped) { + this.enveloped = enveloped; + } + + public int getType() { + return ASN1Registry.NID_pkcs7_enveloped; + } + + @Override + public Envelope getEnveloped() { + return this.enveloped; + } + + @Override + public boolean isEnveloped() { + return true; + } + + @Override + public void setCipher(CipherSpec cipher) { + this.enveloped.getEncData().setCipher(cipher); + } + + @Override + public void addRecipientInfo(RecipInfo ri) { + this.enveloped.getRecipientInfo().add(ri); + } + + @Override + public String toString() { + return this.enveloped.toString(); + } + + public static PKCS7DataEnveloped fromASN1(DEREncodable content) { + return new PKCS7DataEnveloped(Envelope.fromASN1(content)); + } + + @Override + public ASN1Encodable asASN1() { + return enveloped.asASN1(); + } +}// PKCS7DataEnveloped diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataSigned.java b/src/org/jruby/ext/openssl/impl/PKCS7DataSigned.java new file mode 100644 index 00000000000..fb41f1db95f --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataSigned.java @@ -0,0 +1,134 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.security.cert.X509CRL; +import java.util.Collection; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.DEREncodable; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataSigned extends PKCS7Data { + /* NID_pkcs7_signed */ + private Signed sign; + + public PKCS7DataSigned() { + this.sign = new Signed(); + this.sign.setVersion(1); + } + + public PKCS7DataSigned(Signed sign) { + this.sign = sign; + } + + public int getType() { + return ASN1Registry.NID_pkcs7_signed; + } + + @Override + public Object ctrl(int cmd, Object v, Object ignored) { + int ret = 0; + switch(cmd) { + case PKCS7.OP_SET_DETACHED_SIGNATURE: + ret = ((Integer)v).intValue(); + if(ret != 0 && sign.contents.isData()) { + sign.contents.setData(null); + } + break; + case PKCS7.OP_GET_DETACHED_SIGNATURE: + if(sign == null || sign.contents.getData() == null) { + ret = 1; + } else { + ret = 0; + } + break; + default: + throw new RuntimeException("TODO: implement error handling"); + } + return Integer.valueOf(ret); + } + + @Override + public void setSign(Signed sign) { + this.sign = sign; + } + + @Override + public Signed getSign() { + return this.sign; + } + + @Override + public boolean isSigned() { + return true; + } + + @Override + public void addSigner(SignerInfoWithPkey psi) { + this.sign.getMdAlgs().add(psi.getDigestAlgorithm()); + this.sign.getSignerInfo().add(psi); + } + + @Override + public void setContent(PKCS7 p7) { + this.sign.setContents(p7); + } + + @Override + public Collection getSignerInfo() { + return this.sign.getSignerInfo(); + } + + @Override + public void addCertificate(X509AuxCertificate cert) { + this.sign.getCert().add(cert); + } + + @Override + public void addCRL(X509CRL crl) { + this.sign.getCrl().add(crl); + } + + @Override + public String toString() { + return this.sign.toString(); + } + + public static PKCS7DataSigned fromASN1(DEREncodable content) throws PKCS7Exception { + return new PKCS7DataSigned(Signed.fromASN1(content)); + } + + @Override + public ASN1Encodable asASN1() { + return sign.asASN1(); + } +}// PKCS7DataSigned diff --git a/src/org/jruby/ext/openssl/impl/PKCS7DataSignedAndEnveloped.java b/src/org/jruby/ext/openssl/impl/PKCS7DataSignedAndEnveloped.java new file mode 100644 index 00000000000..9664da051fa --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7DataSignedAndEnveloped.java @@ -0,0 +1,97 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.security.cert.X509CRL; +import java.util.Collection; +import org.bouncycastle.asn1.DEREncodable; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** + * + * @author Ola Bini + */ +public class PKCS7DataSignedAndEnveloped extends PKCS7Data { + /* NID_pkcs7_signedAndEnveloped */ + private SignEnvelope signedAndEnveloped; + + public PKCS7DataSignedAndEnveloped() { + this.signedAndEnveloped = new SignEnvelope(); + this.signedAndEnveloped.setVersion(1); + this.signedAndEnveloped.getEncData().setContentType(ASN1Registry.NID_pkcs7_data); + } + + public int getType() { + return ASN1Registry.NID_pkcs7_signedAndEnveloped; + } + + @Override + public boolean isSignedAndEnveloped() { + return true; + } + + @Override + public SignEnvelope getSignedAndEnveloped() { + return signedAndEnveloped; + } + + @Override + public void setCipher(CipherSpec cipher) { + this.signedAndEnveloped.getEncData().setCipher(cipher); + } + + @Override + public void addRecipientInfo(RecipInfo ri) { + this.signedAndEnveloped.getRecipientInfo().add(ri); + } + + @Override + public void addSigner(SignerInfoWithPkey psi) { + this.signedAndEnveloped.getMdAlgs().add(psi.getDigestAlgorithm()); + this.signedAndEnveloped.getSignerInfo().add(psi); + } + + @Override + public Collection getSignerInfo() { + return this.signedAndEnveloped.getSignerInfo(); + } + + @Override + public void addCertificate(X509AuxCertificate cert) { + this.signedAndEnveloped.getCert().add(cert); + } + + @Override + public void addCRL(X509CRL crl) { + this.signedAndEnveloped.getCrl().add(crl); + } + + public static PKCS7DataSignedAndEnveloped fromASN1(DEREncodable content) { + throw new UnsupportedOperationException("TODO: can't create DataSignedAndEnveloped from ASN1 yet"); + } +}// PKCS7DataSignedAndEnveloped diff --git a/src/org/jruby/ext/openssl/impl/PKCS7Exception.java b/src/org/jruby/ext/openssl/impl/PKCS7Exception.java new file mode 100644 index 00000000000..3efcaff5a29 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKCS7Exception.java @@ -0,0 +1,70 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** + * + * @author Ola Bini + */ +public class PKCS7Exception extends Exception { + private static final long serialVersionUID = 1L; + + private int method; + private int reason; + private String errorData; + + public PKCS7Exception(int method, int reason) { + this(method, reason, ""+null); + } + + public PKCS7Exception(int method, int reason, String errorData) { + super("PKCS7[Method: " + method + ", Reason: " + reason + ", Data: " + errorData + "]"); + this.method = method; + this.reason = reason; + this.errorData = errorData; + } + + public PKCS7Exception(int method, int reason, Throwable cause) { + super("PKCS7[Method: " + method + ", Reason: " + reason + "]", cause); + this.method = method; + this.reason = reason; + this.errorData = cause.getMessage(); + } + + public int getMethod() { + return this.method; + } + + public int getReason() { + return this.reason; + } + + public String getErrorData() { + return this.errorData; + } +}// PKCS7Exception diff --git a/src/org/jruby/ext/openssl/impl/PKey.java b/src/org/jruby/ext/openssl/impl/PKey.java new file mode 100644 index 00000000000..918f07a1ab4 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/PKey.java @@ -0,0 +1,174 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2010 Hiroshi Nakamura + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.GeneralSecurityException; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.interfaces.DSAParams; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.security.spec.RSAPublicKeySpec; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERSequence; +import org.jruby.util.ByteList; + +/** + * + * Handles PKey related ASN.1 handling. + * + * @author Hiroshi Nakamura + */ +public class PKey { + + // d2i_RSAPrivateKey_bio + public static PrivateKey readRSAPrivateKey(byte[] input) throws IOException, GeneralSecurityException { + KeyFactory fact = KeyFactory.getInstance("RSA"); + DERSequence seq = (DERSequence) (new ASN1InputStream(input).readObject()); + if (seq.size() == 9) { + BigInteger mod = ((DERInteger) seq.getObjectAt(1)).getValue(); + BigInteger pubexp = ((DERInteger) seq.getObjectAt(2)).getValue(); + BigInteger privexp = ((DERInteger) seq.getObjectAt(3)).getValue(); + BigInteger primep = ((DERInteger) seq.getObjectAt(4)).getValue(); + BigInteger primeq = ((DERInteger) seq.getObjectAt(5)).getValue(); + BigInteger primeep = ((DERInteger) seq.getObjectAt(6)).getValue(); + BigInteger primeeq = ((DERInteger) seq.getObjectAt(7)).getValue(); + BigInteger crtcoeff = ((DERInteger) seq.getObjectAt(8)).getValue(); + return fact.generatePrivate(new RSAPrivateCrtKeySpec(mod, pubexp, privexp, primep, primeq, primeep, primeeq, crtcoeff)); + } else { + return null; + } + } + + // d2i_RSAPublicKey_bio + public static PublicKey readRSAPublicKey(byte[] input) throws IOException, GeneralSecurityException { + KeyFactory fact = KeyFactory.getInstance("RSA"); + DERSequence seq = (DERSequence) (new ASN1InputStream(input).readObject()); + if (seq.size() == 2) { + BigInteger mod = ((DERInteger) seq.getObjectAt(0)).getValue(); + BigInteger pubexp = ((DERInteger) seq.getObjectAt(1)).getValue(); + return fact.generatePublic(new RSAPublicKeySpec(mod, pubexp)); + } else { + return null; + } + } + + // d2i_DSAPrivateKey_bio + public static KeyPair readDSAPrivateKey(byte[] input) throws IOException, GeneralSecurityException { + KeyFactory fact = KeyFactory.getInstance("DSA"); + DERSequence seq = (DERSequence) (new ASN1InputStream(input).readObject()); + if (seq.size() == 6) { + BigInteger p = ((DERInteger) seq.getObjectAt(1)).getValue(); + BigInteger q = ((DERInteger) seq.getObjectAt(2)).getValue(); + BigInteger g = ((DERInteger) seq.getObjectAt(3)).getValue(); + BigInteger y = ((DERInteger) seq.getObjectAt(4)).getValue(); + BigInteger x = ((DERInteger) seq.getObjectAt(5)).getValue(); + PrivateKey priv = fact.generatePrivate(new DSAPrivateKeySpec(x, p, q, g)); + PublicKey pub = fact.generatePublic(new DSAPublicKeySpec(y, p, q, g)); + return new KeyPair(pub, priv); + } else { + return null; + } + } + + // d2i_DSA_PUBKEY_bio + public static PublicKey readDSAPublicKey(byte[] input) throws IOException, GeneralSecurityException { + KeyFactory fact = KeyFactory.getInstance("RSA"); + DERSequence seq = (DERSequence) (new ASN1InputStream(input).readObject()); + if (seq.size() == 4) { + BigInteger y = ((DERInteger) seq.getObjectAt(0)).getValue(); + BigInteger p = ((DERInteger) seq.getObjectAt(1)).getValue(); + BigInteger q = ((DERInteger) seq.getObjectAt(2)).getValue(); + BigInteger g = ((DERInteger) seq.getObjectAt(3)).getValue(); + return fact.generatePublic(new DSAPublicKeySpec(y, p, q, g)); + } else { + return null; + } + } + + public static byte[] toDerRSAKey(RSAPublicKey pubKey, RSAPrivateCrtKey privKey) throws IOException { + ASN1EncodableVector v1 = new ASN1EncodableVector(); + if (pubKey != null && privKey == null) { + v1.add(new DERInteger(pubKey.getModulus())); + v1.add(new DERInteger(pubKey.getPublicExponent())); + } else { + v1.add(new DERInteger(0)); + v1.add(new DERInteger(privKey.getModulus())); + v1.add(new DERInteger(privKey.getPublicExponent())); + v1.add(new DERInteger(privKey.getPrivateExponent())); + v1.add(new DERInteger(privKey.getPrimeP())); + v1.add(new DERInteger(privKey.getPrimeQ())); + v1.add(new DERInteger(privKey.getPrimeExponentP())); + v1.add(new DERInteger(privKey.getPrimeExponentQ())); + v1.add(new DERInteger(privKey.getCrtCoefficient())); + } + return new DERSequence(v1).getEncoded(); + } + + public static byte[] toDerDSAKey(DSAPublicKey pubKey, DSAPrivateKey privKey) throws IOException { + if (pubKey != null && privKey == null) { + return pubKey.getEncoded(); + } else if (privKey != null && pubKey != null) { + DSAParams params = privKey.getParams(); + ASN1EncodableVector v1 = new ASN1EncodableVector(); + v1.add(new DERInteger(0)); + v1.add(new DERInteger(params.getP())); + v1.add(new DERInteger(params.getQ())); + v1.add(new DERInteger(params.getG())); + v1.add(new DERInteger(pubKey.getY())); + v1.add(new DERInteger(privKey.getX())); + return new DERSequence(v1).getEncoded(); + } else { + return privKey.getEncoded(); + } + } + + public static byte[] toDerDHKey(BigInteger p, BigInteger g) throws IOException { + ASN1EncodableVector v = new ASN1EncodableVector(); + if (p != null) { + v.add(new DERInteger(p)); + } + if (g != null) { + v.add(new DERInteger(g)); + } + return new DERSequence(v).getEncoded(); + } +} + + diff --git a/src/org/jruby/ext/openssl/impl/RecipInfo.java b/src/org/jruby/ext/openssl/impl/RecipInfo.java new file mode 100644 index 00000000000..71617f9a879 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/RecipInfo.java @@ -0,0 +1,244 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.pkcs.IssuerAndSerialNumber; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.X509Name; +import org.jruby.ext.openssl.x509store.Name; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** PKCS7_RECIP_INFO + * + * @author Ola Bini + */ +public class RecipInfo { + private int version; + private IssuerAndSerialNumber issuerAndSerial; + private AlgorithmIdentifier keyEncAlgor; + private ASN1OctetString encKey; + + /** + * Describe cert here. + */ + private X509AuxCertificate cert; + + /** c: PKCS7_RECIP_INFO_set + * + */ + public void set(X509AuxCertificate cert) throws PKCS7Exception { + version = 0; + try { + X509Name issuer = X509Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(cert.getIssuerX500Principal().getEncoded())).readObject()); + BigInteger serial = cert.getSerialNumber(); + issuerAndSerial = new IssuerAndSerialNumber(issuer, serial); + String algo = addEncryptionIfNeeded(cert.getPublicKey().getAlgorithm()); + keyEncAlgor = new AlgorithmIdentifier(ASN1Registry.sym2oid(algo)); + this.cert = cert; + } catch(IOException e) { + throw new PKCS7Exception(-1, -1, e); + } + } + + private String addEncryptionIfNeeded(String input) { + input = input.toLowerCase(); + if(input.equals("rsa")) { + return input + "Encryption"; + } else if(input.equals("dsa")) { + return input + "Encryption"; + } + return input; + } + + @Override + public boolean equals(Object other) { + boolean ret = this == other; + if(!ret && (other instanceof RecipInfo)) { + RecipInfo o = (RecipInfo)other; + ret = + this.version == o.version && + (this.issuerAndSerial == null ? o.issuerAndSerial == null : (this.issuerAndSerial.equals(o.issuerAndSerial))) && + (this.keyEncAlgor == null ? o.keyEncAlgor == null : (this.keyEncAlgor.equals(o.keyEncAlgor))) && + (this.encKey == null ? o.encKey == null : (this.encKey.equals(o.encKey))); + } + return ret; + } + + @Override + public int hashCode() { + int result = 31; + result = result + 13 * version; + result = result + ((issuerAndSerial == null) ? 0 : 13 * issuerAndSerial.hashCode()); + result = result + ((keyEncAlgor == null) ? 0 : 13 * keyEncAlgor.hashCode()); + result = result + ((encKey == null) ? 0 : 13 * encKey.hashCode()); + return result; + } + + @Override + public String toString() { + return "#"; + } + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the IssuerAndSerial value. + * + * @return an IssuerAndSerialNumber value + */ + public final IssuerAndSerialNumber getIssuerAndSerial() { + return issuerAndSerial; + } + + /** + * Set the IssuerAndSerial value. + * + * @param newIssuerAndSerial The new IssuerAndSerial value. + */ + public final void setIssuerAndSerial(final IssuerAndSerialNumber newIssuerAndSerial) { + this.issuerAndSerial = newIssuerAndSerial; + } + + /** + * Get the KeyEncAlgor value. + * + * @return an AlgorithmIdentifier value + */ + public final AlgorithmIdentifier getKeyEncAlgor() { + return keyEncAlgor; + } + + /** + * Set the KeyEncAlgor value. + * + * @param newKeyEncAlgor The new KeyEncAlgor value. + */ + public final void setKeyEncAlgor(final AlgorithmIdentifier newKeyEncAlgor) { + this.keyEncAlgor = newKeyEncAlgor; + } + + /** + * Get the EncKey value. + * + * @return an ASN1OctetString value + */ + public final ASN1OctetString getEncKey() { + return encKey; + } + + /** + * Set the EncKey value. + * + * @param newEncKey The new EncKey value. + */ + public final void setEncKey(final ASN1OctetString newEncKey) { + this.encKey = newEncKey; + } + + /** + * Get the Cert value. + * + * @return a X509AuxCertificate value + */ + public final X509AuxCertificate getCert() { + return cert; + } + + /** + * Set the Cert value. + * + * @param newCert The new Cert value. + */ + public final void setCert(final X509AuxCertificate newCert) { + this.cert = newCert; + } + + /* c: static pkcs7_cmp_ri + * + */ + public boolean compare(X509AuxCertificate pcert) { + if(!new Name(issuerAndSerial.getName()).isEqual(pcert.getIssuerX500Principal())) { + return false; + } + return pcert.getSerialNumber().compareTo(issuerAndSerial.getCertificateSerialNumber().getValue()) == 0; + } + + /** + * RecipientInfo ::= SEQUENCE { + * version Version, + * issuerAndSerialNumber IssuerAndSerialNumber, + * keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier, + * encryptedKey EncryptedKey } + * + * EncryptedKey ::= OCTET STRING + */ + public static RecipInfo fromASN1(DEREncodable content) { + DERSequence sequence = (DERSequence)content; + RecipInfo ri = new RecipInfo(); + ri.setVersion(((DERInteger)sequence.getObjectAt(0)).getValue().intValue()); + ri.setIssuerAndSerial(IssuerAndSerialNumber.getInstance(sequence.getObjectAt(1))); + ri.setKeyEncAlgor(AlgorithmIdentifier.getInstance(sequence.getObjectAt(2))); + ri.setEncKey((ASN1OctetString)sequence.getObjectAt(3)); + return ri; + } + + public ASN1Encodable asASN1() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new DERInteger(getVersion())); + vector.add(issuerAndSerial.toASN1Object()); + vector.add(keyEncAlgor.toASN1Object()); + vector.add(encKey.toASN1Object()); + return new DERSequence(vector); + } +}// RecipInfo diff --git a/src/org/jruby/ext/openssl/impl/SMIME.java b/src/org/jruby/ext/openssl/impl/SMIME.java new file mode 100644 index 00000000000..c18ecec004a --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/SMIME.java @@ -0,0 +1,280 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** SMIME methods for PKCS7 + * + * @author Ola Bini + */ +public class SMIME { + public final static int MAX_SMLEN = 1024; + public final static byte[] NEWLINE = new byte[]{'\r','\n'}; + + private Mime mime; + + public SMIME() { + this(Mime.DEFAULT); + } + + public SMIME(Mime mime) { + this.mime = mime; + } + + private static boolean equals(byte[] first, int firstIndex, byte[] second, int secondIndex, int length) { + int len = length; + for(int i=firstIndex, + j=secondIndex, + flen=first.length, + slen=second.length; + i0; + i++, j++, len--) { + + if(first[i] != second[j]) { + return false; + } + } + return len == 0; + } + + /* c: static strip_eol + * + */ + public static boolean stripEol(byte[] linebuf, int[] plen) { + int len = plen[0]; + boolean isEol = false; + + for(int p = len - 1; len > 0; len--, p--) { + byte c = linebuf[p]; + if(c == '\n') { + isEol = true; + } else if(c != '\r') { + break; + } + + } + plen[0] = len; + return isEol; + } + + + /* c: SMIME_text + * + */ + public void text(BIO input, BIO output) { +// char iobuf[4096]; +// int len; +// STACK_OF(MIME_HEADER) *headers; +// MIME_HEADER *hdr; + +// if (!(headers = mime_parse_hdr(in))) { +// PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_PARSE_ERROR); +// return 0; +// } +// if(!(hdr = mime_hdr_find(headers, "content-type")) || !hdr->value) { +// PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_MIME_NO_CONTENT_TYPE); +// sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +// return 0; +// } +// if (strcmp (hdr->value, "text/plain")) { +// PKCS7err(PKCS7_F_SMIME_TEXT,PKCS7_R_INVALID_MIME_TYPE); +// ERR_add_error_data(2, "type: ", hdr->value); +// sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +// return 0; +// } +// sk_MIME_HEADER_pop_free(headers, mime_hdr_free); +// while ((len = BIO_read(in, iobuf, sizeof(iobuf))) > 0) +// BIO_write(out, iobuf, len); +// return 1; + } + + /* c: static mime_bound_check + * + */ + private int boundCheck(byte[] line, int linelen, byte[] bound, int blen) { + if(linelen == -1) { + linelen = line.length; + } + + if(blen == -1) { + blen = bound.length; + } + + // Quickly eliminate if line length too short + if(blen + 2 > linelen) { + return 0; + } + + if(line[0] == '-' && + line[1] == '-' && + equals(line, 2, bound, 0, blen)) { + if(line.length>=(blen+4) && + line[2 + blen] == '-' && + line[2 + blen + 1] == '-') { + return 2; + } else { + return 1; + } + } + return 0; + } + + /* c: B64_read_PKCS7 + * + */ + public PKCS7 readPKCS7Base64(BIO bio) throws IOException, PKCS7Exception { + BIO bio64 = BIO.base64Filter(bio); + return PKCS7.fromASN1(bio64); + } + + /* c: static multi_split + * + */ + private List multiSplit(BIO bio, byte[] bound) throws IOException { + List parts = new ArrayList(); + byte[] linebuf = new byte[MAX_SMLEN]; + int blen = bound.length; + boolean eol = false; + int len = 0; + int part = 0; + int state = 0; + boolean first = true; + BIO bpart = null; + + while((len = bio.gets(linebuf, MAX_SMLEN)) > 0) { + state = boundCheck(linebuf, len, bound, blen); + if(state == 1) { + first = true; + part++; + } else if(state == 2) { + parts.add(bpart); + return parts; + } else if(part != 0) { + // strip CR+LF from linebuf + int[] tmp = new int[] {len}; + boolean nextEol = stripEol(linebuf, tmp); + len = tmp[0]; + + if(first) { + first = false; + if(bpart != null) { + parts.add(bpart); + } + bpart = BIO.mem(); + bpart.setMemEofReturn(0); + } else if(eol) { + bpart.write(NEWLINE, 0, 2); + } + eol = nextEol; + if(len != 0) { + bpart.write(linebuf, 0, len); + } + } + } + + return parts; + } + + /* c: SMIME_read_PKCS7 + * + */ + public PKCS7 readPKCS7(BIO bio, BIO[] bcont) throws IOException, PKCS7Exception { + if(bcont != null && bcont.length > 0) { + bcont[0] = null; + } + + List headers = mime.parseHeaders(bio); + if(headers == null) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_MIME_PARSE_ERROR); + } + + MimeHeader hdr = mime.findHeader(headers, "content-type"); + if(hdr == null || hdr.getValue() == null) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_NO_CONTENT_TYPE); + } + + if("multipart/signed".equals(hdr.getValue())) { + MimeParam prm = mime.findParam(hdr, "boundary"); + if(prm == null || prm.getParamValue() == null) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_NO_MULTIPART_BOUNDARY); + } + + byte[] boundary = null; + try { + boundary = prm.getParamValue().getBytes("ISO8859-1"); + } catch(Exception e) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_NO_MULTIPART_BOUNDARY, e); + } + + List parts = multiSplit(bio, boundary); + if(parts == null || parts.size() != 2) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_NO_MULTIPART_BODY_FAILURE); + } + + BIO p7in = parts.get(1); + + headers = mime.parseHeaders(p7in); + + if(headers == null) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_MIME_SIG_PARSE_ERROR); + } + + hdr = mime.findHeader(headers, "content-type"); + if(hdr == null || hdr.getValue() == null) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_NO_SIG_CONTENT_TYPE); + } + + if(!"application/x-pkcs7-signature".equals(hdr.getValue()) && + !"application/pkcs7-signature".equals(hdr.getValue()) && + !"application/x-pkcs7-mime".equals(hdr.getValue()) && + !"application/pkcs7-mime".equals(hdr.getValue())) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_SIG_INVALID_MIME_TYPE, "type: " + hdr.getValue()); + } + + PKCS7 p7 = readPKCS7Base64(p7in); + + if(bcont != null && bcont.length>0) { + bcont[0] = parts.get(0); + } + + return p7; + } + + if(!"application/x-pkcs7-mime".equals(hdr.getValue()) && + !"application/pkcs7-mime".equals(hdr.getValue())) { + throw new PKCS7Exception(PKCS7.F_SMIME_READ_PKCS7, PKCS7.R_INVALID_MIME_TYPE, "type: " + hdr.getValue()); + } + + return readPKCS7Base64(bio); + } +} diff --git a/src/org/jruby/ext/openssl/impl/SignEnvelope.java b/src/org/jruby/ext/openssl/impl/SignEnvelope.java new file mode 100644 index 00000000000..42dde27f118 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/SignEnvelope.java @@ -0,0 +1,200 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.security.cert.X509CRL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** PKCS7_SIGN_ENVELOPE + * + * @author Ola Bini + */ +public class SignEnvelope { + private int version; + + /** + * Describe encContent here. + */ + private EncContent encData = new EncContent(); + + /** + * Describe crl here. + */ + private Collection crl = new ArrayList(); + + /** + * Describe cert here. + */ + private Collection cert = new ArrayList(); + + /** + * Describe mdAlgs here. + */ + private Set mdAlgs = new HashSet(); + + /** + * Describe signerInfo here. + */ + private Collection signerInfo = new ArrayList(); + + /** + * Describe recipientInfo here. + */ + private Collection recipientInfo = new ArrayList(); + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the EncData value. + * + * @return an EncContent value + */ + public final EncContent getEncData() { + return encData; + } + + /** + * Set the EncData value. + * + * @param newEncContent The new EncContent value. + */ + public final void setEncData(final EncContent newEncData) { + this.encData = newEncData; + } + + /** + * Get the RecipientInfo value. + * + * @return a Collection value + */ + public final Collection getRecipientInfo() { + return recipientInfo; + } + + /** + * Set the RecipientInfo value. + * + * @param newRecipientInfo The new RecipientInfo value. + */ + public final void setRecipientInfo(final Collection newRecipientInfo) { + this.recipientInfo = newRecipientInfo; + } + + /** + * Get the SignerInfoWithPkey value. + * + * @return a Collection value + */ + public final Collection getSignerInfo() { + return signerInfo; + } + + /** + * Set the SignerInfoWithPkey value. + * + * @param newSignerInfo The new SignerInfo value. + */ + public final void setSignerInfo(final Collection newSignerInfo) { + this.signerInfo = newSignerInfo; + } + + /** + * Get the MdAlgs value. + * + * @return a Set value + */ + public final Set getMdAlgs() { + return mdAlgs; + } + + /** + * Set the MdAlgs value. + * + * @param newMdAlgs The new MdAlgs value. + */ + public final void setMdAlgs(final Set newMdAlgs) { + this.mdAlgs = newMdAlgs; + } + + /** + * Get the Cert value. + * + * @return a Collection value + */ + public final Collection getCert() { + return cert; + } + + /** + * Set the Cert value. + * + * @param newCert The new Cert value. + */ + public final void setCert(final Collection newCert) { + this.cert = newCert; + } + + /** + * Get the Crl value. + * + * @return a Collection value + */ + public final Collection getCrl() { + return crl; + } + + /** + * Set the Crl value. + * + * @param newCrl The new Crl value. + */ + public final void setCrl(final Collection newCrl) { + this.crl = newCrl; + } +}// SignEnvelope diff --git a/src/org/jruby/ext/openssl/impl/Signed.java b/src/org/jruby/ext/openssl/impl/Signed.java new file mode 100644 index 00000000000..2adac0d1840 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/Signed.java @@ -0,0 +1,364 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509CRL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Set; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.X509CertificateStructure; +import org.bouncycastle.jce.provider.X509CertificateObject; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** PKCS7_SIGNED + * + * @author Ola Bini + */ +public class Signed { + /** + * Describe version here. + */ + private int version; + + /** + * Describe crl here. + */ + private Collection crl = new ArrayList(); + + /** + * Describe cert here. + */ + private Collection cert = new ArrayList(); + + /** + * Describe mdAlgs here. + */ + private Set mdAlgs = new HashSet(); + + /** + * Describe signerInfo here. + */ + private Collection signerInfo = new ArrayList(); + + PKCS7 contents; + + /** + * Get the Version value. + * + * @return an int value + */ + public final int getVersion() { + return version; + } + + /** + * Set the Version value. + * + * @param newVersion The new Version value. + */ + public final void setVersion(final int newVersion) { + this.version = newVersion; + } + + /** + * Get the SignerInfo value. + * + * @return a Collection value + */ + public final Collection getSignerInfo() { + return signerInfo; + } + + /** + * Set the SignerInfo value. + * + * @param newSignerInfo The new SignerInfo value. + */ + public final void setSignerInfo(final Collection newSignerInfo) { + this.signerInfo = newSignerInfo; + } + + /** + * Get the MdAlgs value. + * + * @return a Set value + */ + public final Set getMdAlgs() { + return mdAlgs; + } + + /** + * Set the MdAlgs value. + * + * @param newMdAlgs The new MdAlgs value. + */ + public final void setMdAlgs(final Set newMdAlgs) { + this.mdAlgs = newMdAlgs; + } + + /** + * Get the Contents value. + * + * @return a PKCS7 value + */ + public final PKCS7 getContents() { + return contents; + } + + /** + * Set the Contents value. + * + * @param newContents The new Contents value. + */ + public final void setContents(final PKCS7 newContents) { + this.contents = newContents; + } + + /** + * Get the Cert value. + * + * @return a Collection value + */ + public final Collection getCert() { + return cert; + } + + /** + * Set the Cert value. + * + * @param newCert The new Cert value. + */ + public final void setCert(final Collection newCert) { + this.cert = newCert; + } + + /** + * Get the Crl value. + * + * @return a Set value + */ + public final Collection getCrl() { + return crl; + } + + /** + * Set the Crl value. + * + * @param newCrl The new Crl value. + */ + public final void setCrl(final Collection newCrl) { + this.crl = newCrl; + } + + @Override + public String toString() { + return "#"; + } + + public ASN1Encodable asASN1() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + vector.add(new DERInteger(version)); + vector.add(digestAlgorithmsToASN1Set()); + vector.add(contents.asASN1()); + if (cert != null && cert.size() > 0) { + if (cert.size() > 1) { + vector.add(new DERTaggedObject(false, 0, certificatesToASN1Set())); + } else { + // Encode the signer certificate directly for OpenSSL compatibility. + // OpenSSL does not support multiple signer signature. + // And OpenSSL requires EXPLICIT tagging. + vector.add(new DERTaggedObject(true, 0, firstCertificatesToASN1())); + } + } + if (crl != null && crl.size() > 0) { + vector.add(new DERTaggedObject(false, 1, crlsToASN1Set())); + } + vector.add(signerInfosToASN1Set()); + return new DERSequence(vector); + } + + private ASN1Set digestAlgorithmsToASN1Set() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + for(AlgorithmIdentifier ai : mdAlgs) { + vector.add(ai.toASN1Object()); + } + return new DERSet(vector); + } + + // This imlementation is stupid and wasteful. Ouch. + private ASN1Set certificatesToASN1Set() { + try { + ASN1EncodableVector vector = new ASN1EncodableVector(); + for(X509AuxCertificate c : cert) { + vector.add(new ASN1InputStream(new ByteArrayInputStream(c.getEncoded())).readObject()); + } + return new DERSet(vector); + } catch(Exception e) { + return null; + } + } + + private DERSequence firstCertificatesToASN1() { + try { + X509AuxCertificate c = cert.iterator().next(); + return (DERSequence) (new ASN1InputStream(new ByteArrayInputStream(c.getEncoded())).readObject()); + } catch (Exception e) {} + return null; + } + + private ASN1Set crlsToASN1Set() { + throw new RuntimeException("TODO: implement CRL part"); + } + + private ASN1Set signerInfosToASN1Set() { + ASN1EncodableVector vector = new ASN1EncodableVector(); + for(SignerInfoWithPkey si : signerInfo) { + vector.add(si.toASN1Object()); + } + return new DERSet(vector); + } + + /** + * SignedData ::= SEQUENCE { + * version Version, + * digestAlgorithms DigestAlgorithmIdentifiers, + * contentInfo ContentInfo, + * certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL, + * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL, + * signerInfos SignerInfos } + * + * Version ::= INTEGER + * + * DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier + * + * SignerInfos ::= SET OF SignerInfo + */ + public static Signed fromASN1(DEREncodable content) throws PKCS7Exception{ + ASN1Sequence sequence = (ASN1Sequence)content; + DERInteger version = (DERInteger)sequence.getObjectAt(0); + ASN1Set digestAlgos = (ASN1Set)sequence.getObjectAt(1); + DEREncodable contentInfo = sequence.getObjectAt(2); + + DEREncodable certificates = null; + DEREncodable crls = null; + + int index = 3; + DEREncodable tmp = sequence.getObjectAt(index); + if((tmp instanceof DERTaggedObject) && ((DERTaggedObject)tmp).getTagNo() == 0) { + certificates = ((DERTaggedObject)tmp).getObject(); + index++; + } + + tmp = sequence.getObjectAt(index); + if((tmp instanceof DERTaggedObject) && ((DERTaggedObject)tmp).getTagNo() == 1) { + crls = ((DERTaggedObject)tmp).getObject(); + index++; + } + + ASN1Set signerInfos = (ASN1Set)sequence.getObjectAt(index); + + Signed signed = new Signed(); + signed.setVersion(version.getValue().intValue()); + signed.setMdAlgs(algorithmIdentifiersFromASN1Set(digestAlgos)); + signed.setContents(PKCS7.fromASN1(contentInfo)); + if(certificates != null) { + signed.setCert(certificatesFromASN1Set(certificates)); + } + if(crls != null) { + throw new RuntimeException("TODO: implement CRL part"); + } + signed.setSignerInfo(signerInfosFromASN1Set(signerInfos)); + + return signed; + } + + private static Collection certificatesFromASN1Set(DEREncodable content) throws PKCS7Exception { + Collection result = new ArrayList(); + if (content instanceof DERSequence) { + try { + for (Enumeration enm = ((DERSequence) content).getObjects(); enm.hasMoreElements();) { + DEREncodable current = (DEREncodable) enm.nextElement(); + result.add(certificateFromASN1(current)); + } + } catch (IllegalArgumentException iae) { + result.add(certificateFromASN1(content)); + } + } else if (content instanceof DERSet) { + // EXPLICIT Set shouldn't apper here but keep this for backward compatibility. + for (Enumeration enm = ((DERSet) content).getObjects(); enm.hasMoreElements();) { + DEREncodable current = (DEREncodable) enm.nextElement(); + result.add(certificateFromASN1(current)); + } + } else { + throw new PKCS7Exception(PKCS7.F_B64_READ_PKCS7, PKCS7.R_CERTIFICATE_VERIFY_ERROR, "unknown certificates format"); + } + return result; + } + + private static X509AuxCertificate certificateFromASN1(DEREncodable current) throws PKCS7Exception { + X509CertificateStructure struct = X509CertificateStructure.getInstance(current); + try { + return new X509AuxCertificate(new X509CertificateObject(struct)); + } catch (CertificateParsingException cpe) { + throw new PKCS7Exception(PKCS7.F_B64_READ_PKCS7, PKCS7.R_CERTIFICATE_VERIFY_ERROR, cpe); + } + } + + private static Set algorithmIdentifiersFromASN1Set(DEREncodable content) { + ASN1Set set = (ASN1Set)content; + Set result = new HashSet(); + for(Enumeration e = set.getObjects(); e.hasMoreElements();) { + result.add(AlgorithmIdentifier.getInstance(e.nextElement())); + } + return result; + } + + private static Collection signerInfosFromASN1Set(DEREncodable content) { + ASN1Set set = (ASN1Set)content; + Collection result = new ArrayList(); + for(Enumeration e = set.getObjects(); e.hasMoreElements();) { + result.add(SignerInfoWithPkey.getInstance(e.nextElement())); + } + return result; + } +}// Signed diff --git a/src/org/jruby/ext/openssl/impl/SignerInfoWithPkey.java b/src/org/jruby/ext/openssl/impl/SignerInfoWithPkey.java new file mode 100644 index 00000000000..38c5f012673 --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/SignerInfoWithPkey.java @@ -0,0 +1,364 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.PrivateKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.RSAPrivateKey; +import java.util.Enumeration; +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.ASN1Set; +import org.bouncycastle.asn1.ASN1TaggedObject; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERSet; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.pkcs.Attribute; +import org.bouncycastle.asn1.pkcs.IssuerAndSerialNumber; +import org.bouncycastle.asn1.pkcs.SignerInfo; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.bouncycastle.asn1.x509.X509Name; +import org.jruby.ext.openssl.x509store.X509AuxCertificate; + +/** + * + * @author Ola Bini + */ +public class SignerInfoWithPkey extends ASN1Encodable { + private DERInteger version; + private IssuerAndSerialNumber issuerAndSerialNumber; + private AlgorithmIdentifier digAlgorithm; + private ASN1Set authenticatedAttributes; + private AlgorithmIdentifier digEncryptionAlgorithm; + private ASN1OctetString encryptedDigest; + private ASN1Set unauthenticatedAttributes; + + public static SignerInfoWithPkey getInstance(Object o) { + if(o instanceof SignerInfo) { + return (SignerInfoWithPkey)o; + } else if (o instanceof ASN1Sequence) { + return new SignerInfoWithPkey((ASN1Sequence)o); + } + + throw new IllegalArgumentException("unknown object in factory: " + o.getClass().getName()); + } + + public SignerInfoWithPkey dup() { + SignerInfoWithPkey copy = new SignerInfoWithPkey(version, + issuerAndSerialNumber, + digAlgorithm, + authenticatedAttributes, + digEncryptionAlgorithm, + encryptedDigest, + unauthenticatedAttributes); + copy.pkey = pkey; + return copy; + } + + SignerInfoWithPkey() { + } + + public SignerInfoWithPkey(DERInteger version, + IssuerAndSerialNumber issuerAndSerialNumber, + AlgorithmIdentifier digAlgorithm, + ASN1Set authenticatedAttributes, + AlgorithmIdentifier digEncryptionAlgorithm, + ASN1OctetString encryptedDigest, + ASN1Set unauthenticatedAttributes) { + this.version = version; + this.issuerAndSerialNumber = issuerAndSerialNumber; + this.digAlgorithm = digAlgorithm; + this.authenticatedAttributes = authenticatedAttributes; + this.digEncryptionAlgorithm = digEncryptionAlgorithm; + this.encryptedDigest = encryptedDigest; + this.unauthenticatedAttributes = unauthenticatedAttributes; + } + + public SignerInfoWithPkey(ASN1Sequence seq) { + Enumeration e = seq.getObjects(); + + version = (DERInteger)e.nextElement(); + issuerAndSerialNumber = IssuerAndSerialNumber.getInstance(e.nextElement()); + digAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement()); + + Object obj = e.nextElement(); + + if(obj instanceof ASN1TaggedObject) { + authenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)obj, false); + + digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(e.nextElement()); + } + else { + authenticatedAttributes = null; + digEncryptionAlgorithm = AlgorithmIdentifier.getInstance(obj); + } + + encryptedDigest = ASN1OctetString.getInstance(e.nextElement()); + + if(e.hasMoreElements()) { + unauthenticatedAttributes = ASN1Set.getInstance((ASN1TaggedObject)e.nextElement(), false); + } + else { + unauthenticatedAttributes = null; + } + } + + public DERInteger getVersion() { + return version; + } + + public IssuerAndSerialNumber getIssuerAndSerialNumber() { + return issuerAndSerialNumber; + } + + public ASN1Set getAuthenticatedAttributes() { + return authenticatedAttributes; + } + + public AlgorithmIdentifier getDigestAlgorithm() { + return digAlgorithm; + } + + public ASN1OctetString getEncryptedDigest() { + return encryptedDigest; + } + + public AlgorithmIdentifier getDigestEncryptionAlgorithm() { + return digEncryptionAlgorithm; + } + + public ASN1Set getUnauthenticatedAttributes() { + return unauthenticatedAttributes; + } + + /* c: PKCS7_SIGNER_INFO_set + * + */ + public void set(X509AuxCertificate x509, PrivateKey pkey, MessageDigest dgst) throws PKCS7Exception { + boolean dsa = + (pkey instanceof DSAPrivateKey) || + (pkey instanceof ECPrivateKey); + + version = new DERInteger(1); + + try { + X509Name issuer = X509Name.getInstance(new ASN1InputStream(new ByteArrayInputStream(x509.getIssuerX500Principal().getEncoded())).readObject()); + BigInteger serial = x509.getSerialNumber(); + issuerAndSerialNumber = new IssuerAndSerialNumber(issuer, serial); + } catch(IOException e) { + throw new PKCS7Exception(-1, -1, e); + } + + this.pkey = pkey; + + if(dsa) { + digAlgorithm = new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_sha1)); + } else { + digAlgorithm = new AlgorithmIdentifier(ASN1Registry.nid2obj(EVP.type(dgst))); + } + + if(pkey instanceof RSAPrivateKey) { + digEncryptionAlgorithm = new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_rsaEncryption)); + } else if(pkey instanceof DSAPrivateKey) { + digEncryptionAlgorithm = new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_dsa)); + } else if(pkey instanceof ECPrivateKey) { + digEncryptionAlgorithm = new AlgorithmIdentifier(ASN1Registry.nid2obj(ASN1Registry.NID_ecdsa_with_SHA1)); + } + } + + /** + * Produce an object suitable for an ASN1OutputStream. + *

+     *  SignerInfo ::= SEQUENCE {
+     *      version Version,
+     *      issuerAndSerialNumber IssuerAndSerialNumber,
+     *      digestAlgorithm DigestAlgorithmIdentifier,
+     *      authenticatedAttributes [0] IMPLICIT Attributes OPTIONAL,
+     *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
+     *      encryptedDigest EncryptedDigest,
+     *      unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL
+     *  }
+     *
+     *  EncryptedDigest ::= OCTET STRING
+     *
+     *  DigestAlgorithmIdentifier ::= AlgorithmIdentifier
+     *
+     *  DigestEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
+     * 
+ */ + public DERObject toASN1Object() { + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(version); + v.add(issuerAndSerialNumber); + v.add(digAlgorithm); + + if (authenticatedAttributes != null) { + v.add(new DERTaggedObject(false, 0, authenticatedAttributes)); + } + + v.add(digEncryptionAlgorithm); + v.add(encryptedDigest); + + if (unauthenticatedAttributes != null) { + v.add(new DERTaggedObject(false, 1, unauthenticatedAttributes)); + } + + return new DERSequence(v); + } + + /** + * Describe pkey here. + */ + private PrivateKey pkey; + + /** + * Get the Pkey value. + * + * @return a PrivateKey value + */ + public final PrivateKey getPkey() { + return pkey; + } + + /** + * Set the Pkey value. + * + * @param newPkey The new Pkey value. + */ + public final void setPkey(final PrivateKey newPkey) { + this.pkey = newPkey; + } + + public void setAuthenticatedAttributes(ASN1Set authAttr) { + this.authenticatedAttributes = authAttr; + } + + public void setUnauthenticatedAttributes(ASN1Set unauthAttr) { + this.unauthenticatedAttributes = unauthAttr; + } + + public void setEncryptedDigest(ASN1OctetString encryptedDigest) { + this.encryptedDigest = encryptedDigest; + } + + /** c: PKCS7_get_signed_attribute + * + */ + public DEREncodable getSignedAttribute(int nid) { + return getAttribute(this.authenticatedAttributes, nid); + } + + /** c: PKCS7_get_attribute + * + */ + public DEREncodable getAttribute(int nid) { + return getAttribute(this.unauthenticatedAttributes, nid); + } + + /** c: static get_attribute + * + */ + public static DEREncodable getAttribute(ASN1Set sk, int nid) { + Attribute xa = null; + DERObjectIdentifier o = ASN1Registry.nid2obj(nid); + + if(null == o || null == sk) { + return null; + } + + for(Enumeration e = sk.getObjects(); e.hasMoreElements();) { + Object val = e.nextElement(); + if(val instanceof Attribute) { + xa = (Attribute)val; + } else { + xa = Attribute.getInstance(val); + } + + if(o.equals(xa.getAttrType())) { + if(xa.getAttrValues().size() > 0) { + return xa.getAttrValues().getObjectAt(0); + } else { + return null; + } + } + } + return null; + } + + /** c: PKCS7_add_signed_attribute + * + */ + public void addSignedAttribute(int atrType, DEREncodable value) { + this.authenticatedAttributes = addAttribute(this.authenticatedAttributes, atrType, value); + } + + /** c: PKCS7_add_attribute + * + */ + public void addAttribute(int atrType, DEREncodable value) { + this.unauthenticatedAttributes = addAttribute(this.unauthenticatedAttributes, atrType, value); + } + + /** c: static add_attribute + * + */ + private ASN1Set addAttribute(ASN1Set base, int atrType, DEREncodable value) { + ASN1EncodableVector vector = new ASN1EncodableVector(); + if(base == null) { + base = new DERSet(); + } + Attribute attr = null; + for(Enumeration e = base.getObjects(); e.hasMoreElements();) { + Object val = e.nextElement(); + if(val instanceof Attribute) { + attr = (Attribute)val; + } else { + attr = Attribute.getInstance(val); + } + if(ASN1Registry.obj2nid(attr.getAttrType()) != atrType) { + vector.add(attr); + } + } + attr = new Attribute(ASN1Registry.nid2obj(atrType), new DERSet(value)); + vector.add(attr); + return new DERSet(vector); + } +}// SignerInfoWithPkey diff --git a/src/org/jruby/ext/openssl/impl/TypeDiscriminating.java b/src/org/jruby/ext/openssl/impl/TypeDiscriminating.java new file mode 100644 index 00000000000..bd75b71049a --- /dev/null +++ b/src/org/jruby/ext/openssl/impl/TypeDiscriminating.java @@ -0,0 +1,34 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2008 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.impl; + +/** + * @author Ola Bini + */ +public abstract class TypeDiscriminating { +}// TypeDiscriminating diff --git a/src/org/jruby/ext/openssl/x509store/CRL.java b/src/org/jruby/ext/openssl/x509store/CRL.java new file mode 100644 index 00000000000..ce2ce25ce57 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/CRL.java @@ -0,0 +1,59 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.security.cert.X509CRL; + +/** + * c: X509_OBJECT + * + * @author Ola Bini + */ +public class CRL extends X509Object { + public java.security.cert.CRL crl; + + public int type() { + return X509Utils.X509_LU_CRL; + } + + public boolean isName(Name nm) { + return nm.isEqual(((X509CRL)crl).getIssuerX500Principal()); + } + + public boolean matches(X509Object o) { + return o instanceof CRL && ((X509CRL)crl).getIssuerX500Principal().equals(((X509CRL)((CRL)o).crl).getIssuerX500Principal()); + } + + public int compareTo(X509Object oth) { + int ret1 = super.compareTo(oth); + if(ret1 == 0) { + ret1 = crl.equals(((CRL)oth).crl) ? 0 : -1; + } + return ret1; + } +}// X509_OBJECT_CRL diff --git a/src/org/jruby/ext/openssl/x509store/Certificate.java b/src/org/jruby/ext/openssl/x509store/Certificate.java new file mode 100644 index 00000000000..8b2075835fb --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Certificate.java @@ -0,0 +1,57 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * c: X509_OBJECT + * + * @author Ola Bini + */ +public class Certificate extends X509Object { + public X509AuxCertificate x509; + + public int type() { + return X509Utils.X509_LU_X509; + } + + public boolean isName(Name nm) { + return nm.isEqual(x509.getSubjectX500Principal()); + } + + public boolean matches(X509Object o) { + return o instanceof Certificate && x509.getSubjectX500Principal().equals(((Certificate)o).x509.getSubjectX500Principal()); + } + + public int compareTo(X509Object oth) { + int ret1 = super.compareTo(oth); + if(ret1 == 0) { + ret1 = x509.equals(((Certificate)oth).x509) ? 0 : -1; + } + return ret1; + } +}// X509_OBJECT_CERT diff --git a/src/org/jruby/ext/openssl/x509store/CertificateFile.java b/src/org/jruby/ext/openssl/x509store/CertificateFile.java new file mode 100644 index 00000000000..934edc7949b --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/CertificateFile.java @@ -0,0 +1,46 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Contains information like x509_file_st and X509_CERT_FILER_CTX in + * x509_vfy.h + * + * @author Ola Bini + */ +public class CertificateFile { + public static class Path { + public Path(String name, int type) { + this.name = name; this.type = type; + } + public String name; + public int type; + } + public int numberOfPaths; // This details how many of the paths-var that is actually used + public Path[] paths; +}// X509_CERT_FILE_CTX diff --git a/src/org/jruby/ext/openssl/x509store/CertificateHashDir.java b/src/org/jruby/ext/openssl/x509store/CertificateHashDir.java new file mode 100644 index 00000000000..eee5cd24599 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/CertificateHashDir.java @@ -0,0 +1,46 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Contains information like x509_hash_dir_st and X509_HASH_DIR_CTX in + * x509_vfy.h + * + * @author Ola Bini + */ +public class CertificateHashDir { + public static class Dir { + public Dir(String name, int type) { + this.name = name; this.type = type; + } + public String name; + public int type; + } + public int numberOfDirs; // This details how many of the dirs-var that is actually used + public Dir[] dirs; +}// X509_HASH_DIR_CTX diff --git a/src/org/jruby/ext/openssl/x509store/Function0.java b/src/org/jruby/ext/openssl/x509store/Function0.java new file mode 100644 index 00000000000..4815f60c394 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function0.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Zero arity function call. + * + * @author Ola Bini + */ +public interface Function0 { + public static class Empty implements Function0 { + public int call() { + return -1; + } + } + public static final Function0.Empty EMPTY = new Empty(); + int call() throws Exception; +}// Function0 diff --git a/src/org/jruby/ext/openssl/x509store/Function1.java b/src/org/jruby/ext/openssl/x509store/Function1.java new file mode 100644 index 00000000000..5b61b7efd7d --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function1.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * One arity function call. + * + * @author Ola Bini + */ +public interface Function1 { + public static class Empty implements Function1 { + public int call(Object arg0) { + return -1; + } + } + public static final Function1.Empty EMPTY = new Empty(); + int call(Object arg0) throws Exception; +}// Function1 diff --git a/src/org/jruby/ext/openssl/x509store/Function2.java b/src/org/jruby/ext/openssl/x509store/Function2.java new file mode 100644 index 00000000000..3818dc13909 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function2.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Two arity function call. + * + * @author Ola Bini + */ +public interface Function2 { + public static class Empty implements Function2 { + public int call(Object arg0,Object arg1) { + return -1; + } + } + public static final Function2.Empty EMPTY = new Empty(); + int call(Object arg0,Object arg1) throws Exception; +}// Function2 diff --git a/src/org/jruby/ext/openssl/x509store/Function3.java b/src/org/jruby/ext/openssl/x509store/Function3.java new file mode 100644 index 00000000000..14d81514cce --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function3.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Three arity function call. + * + * @author Ola Bini + */ +public interface Function3 { + public static class Empty implements Function3 { + public int call(Object arg0,Object arg1,Object arg2) { + return -1; + } + } + public static final Function3.Empty EMPTY = new Empty(); + int call(Object arg0,Object arg1,Object arg2) throws Exception; +}// Function3 diff --git a/src/org/jruby/ext/openssl/x509store/Function4.java b/src/org/jruby/ext/openssl/x509store/Function4.java new file mode 100644 index 00000000000..4955640d5d8 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function4.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Four arity function call. + * + * @author Ola Bini + */ +public interface Function4 { + public static class Empty implements Function4 { + public int call(Object arg0,Object arg1,Object arg2,Object arg3) { + return -1; + } + } + public static final Function4.Empty EMPTY = new Empty(); + int call(Object arg0,Object arg1,Object arg2,Object arg3) throws Exception; +}// Function4 diff --git a/src/org/jruby/ext/openssl/x509store/Function5.java b/src/org/jruby/ext/openssl/x509store/Function5.java new file mode 100644 index 00000000000..d2a0a76639c --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Function5.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * Five arity function call. + * + * @author Ola Bini + */ +public interface Function5 { + public static class Empty implements Function5 { + public int call(Object arg0,Object arg1,Object arg2,Object arg3,Object arg4) { + return -1; + } + } + public static final Function5.Empty EMPTY = new Empty(); + int call(Object arg0,Object arg1,Object arg2,Object arg3,Object arg4) throws Exception; +}// Function5 diff --git a/src/org/jruby/ext/openssl/x509store/Lookup.java b/src/org/jruby/ext/openssl/x509store/Lookup.java new file mode 100644 index 00000000000..c7240f05f38 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Lookup.java @@ -0,0 +1,592 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.io.BufferedInputStream; +import java.io.File; +import java.io.IOException; +import java.io.Reader; +import java.io.InputStream; +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; + +import java.math.BigInteger; + +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.cert.CRL; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import org.jruby.Ruby; +import org.jruby.util.io.ChannelDescriptor; +import org.jruby.util.io.ChannelStream; +import org.jruby.util.io.FileExistsException; +import org.jruby.util.io.InvalidValueException; +import org.jruby.util.io.ModeFlags; + +/** + * X509_LOOKUP + * + * @author Ola Bini + */ +public class Lookup { + public boolean init; + public boolean skip; + public LookupMethod method; + public Object methodData; + public Store store; + + /** + * c: X509_LOOKUP_new + */ + public Lookup(LookupMethod method) throws Exception { + init=false; + skip=false; + this.method=method; + methodData=null; + store=null; + if(method.newItem != null && method.newItem != Function1.EMPTY && method.newItem.call(this) == 0) { + throw new Exception(); + } + } + + /** + * c: X509_LOOKUP_load_file + */ + public int loadFile(CertificateFile.Path file) throws Exception { + return control(X509Utils.X509_L_FILE_LOAD,file.name,file.type,null); + } + + /** + * c: X509_LOOKUP_add_dir + */ + public int addDir(CertificateHashDir.Dir dir) throws Exception { + return control(X509Utils.X509_L_ADD_DIR,dir.name,dir.type,null); + } + + /** + * c: X509_LOOKUP_hash_dir + */ + public static LookupMethod hashDirLookup() { + return x509DirectoryLookup; + } + + /** + * c: X509_LOOKUP_file + */ + public static LookupMethod fileLookup() { + return x509FileLookup; + } + + /** + * c: X509_LOOKUP_ctrl + */ + public int control(int cmd, String argc, long argl, String[] ret) throws Exception { + if(method == null) { + return -1; + } + if(method.control != null && method.control != Function5.EMPTY) { + return method.control.call(this,new Integer(cmd),argc,new Long(argl),ret); + } else { + return 1; + } + } + + /** + * c: X509_LOOKUP_load_cert_file + */ + public int loadCertificateFile(String file, int type) throws Exception { + if (file == null) { + return 1; + } + int count = 0; + int ret = 0; + Reader reader = null; + try { + InputStream in = wrapJRubyNormalizedInputStream(file); + X509AuxCertificate x = null; + if (type == X509Utils.X509_FILETYPE_PEM) { + reader = new BufferedReader(new InputStreamReader(in)); + for (;;) { + x = PEMInputOutput.readX509Aux(reader, null); + if (null == x) { + break; + } + int i = store.addCertificate(x); + if (i == 0) { + return ret; + } + count++; + x = null; + } + ret = count; + } else if (type == X509Utils.X509_FILETYPE_ASN1) { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + x = StoreContext.ensureAux((X509Certificate) cf.generateCertificate(in)); + if (x == null) { + X509Error.addError(13); + return ret; + } + int i = store.addCertificate(x); + if (i == 0) { + return ret; + } + ret = i; + } else { + X509Error.addError(X509Utils.X509_R_BAD_X509_FILETYPE); + } + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception ignored) { + } + } + } + return ret; + } + + /** + * c: X509_LOOKUP_load_crl_file + */ + public int loadCRLFile(String file, int type) throws Exception { + if (file == null) { + return 1; + } + int count = 0; + int ret = 0; + Reader reader = null; + try { + InputStream in = wrapJRubyNormalizedInputStream(file); + CRL x = null; + if (type == X509Utils.X509_FILETYPE_PEM) { + reader = new BufferedReader(new InputStreamReader(in)); + for (;;) { + x = PEMInputOutput.readX509CRL(reader, null); + if (null == x) { + break; + } + int i = store.addCRL(x); + if (i == 0) { + return ret; + } + count++; + x = null; + } + ret = count; + } else if (type == X509Utils.X509_FILETYPE_ASN1) { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + x = cf.generateCRL(in); + if (x == null) { + X509Error.addError(13); + return ret; + } + int i = store.addCRL(x); + if (i == 0) { + return ret; + } + ret = i; + } else { + X509Error.addError(X509Utils.X509_R_BAD_X509_FILETYPE); + } + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception ignored) { + } + } + } + return ret; + } + + /** + * c: X509_LOOKUP_load_cert_crl_file + */ + public int loadCertificateOrCRLFile(String file, int type) throws Exception { + if (type != X509Utils.X509_FILETYPE_PEM) { + return loadCertificateFile(file, type); + } + int count = 0; + Reader reader = null; + try { + InputStream in = wrapJRubyNormalizedInputStream(file); + reader = new BufferedReader(new InputStreamReader(in)); + for (;;) { + Object v = PEMInputOutput.readPEM(reader, null); + if (null == v) { + break; + } + if (v instanceof X509Certificate) { + store.addCertificate(StoreContext.ensureAux((X509Certificate) v)); + count++; + } else if (v instanceof CRL) { + store.addCRL((CRL) v); + count++; + } + } + } finally { + if (reader != null) { + try { + reader.close(); + } catch (Exception ignored) { + } + } + } + return count; + } + + private InputStream wrapJRubyNormalizedInputStream(String file) throws IOException { + Ruby runtime = Ruby.getGlobalRuntime(); + try { + ChannelDescriptor descriptor = ChannelDescriptor.open(runtime.getCurrentDirectory(), file, new ModeFlags(ModeFlags.RDONLY)); + return ChannelStream.open(runtime, descriptor).newInputStream(); + } catch (NoSuchMethodError nsme) { + return new BufferedInputStream(new FileInputStream(file)); + } catch (FileExistsException fee) { + // should not happen because ModeFlag does not contain CREAT. + fee.printStackTrace(System.err); + throw new IllegalStateException(fee.getMessage(), fee); + } catch (InvalidValueException ive) { + // should not happen because ModeFlasg does not contain APPEND. + ive.printStackTrace(System.err); + throw new IllegalStateException(ive.getMessage(), ive); + } + } + + /** + * c: X509_LOOKUP_free + */ + public void free() throws Exception { + if(method != null && method.free != null && method.free != Function1.EMPTY) { + method.free.call(this); + } + } + + /** + * c: X509_LOOKUP_init + */ + public int init() throws Exception { + if(method == null) { + return 0; + } + if(method.init != null && method.init != Function1.EMPTY) { + return method.init.call(this); + } + return 1; + } + + /** + * c: X509_LOOKUP_by_subject + */ + public int bySubject(int type, Name name,X509Object[] ret) throws Exception { + if(method == null || method.getBySubject == null || method.getBySubject == Function4.EMPTY) { + return X509Utils.X509_LU_FAIL; + } + if(skip) { + return 0; + } + return method.getBySubject.call(this,new Integer(type),name,ret); + } + + /** + * c: X509_LOOKUP_by_issuer_serial + */ + public int byIssuerSerialNumber(int type, Name name,BigInteger serial, X509Object[] ret) throws Exception { + if(method == null || method.getByIssuerSerialNumber == null || method.getByIssuerSerialNumber == Function5.EMPTY) { + return X509Utils.X509_LU_FAIL; + } + return method.getByIssuerSerialNumber.call(this,new Integer(type),name,serial,ret); + } + + /** + * c: X509_LOOKUP_by_fingerprint + */ + public int byFingerprint(int type,String bytes, X509Object[] ret) throws Exception { + if(method == null || method.getByFingerprint == null || method.getByFingerprint == Function4.EMPTY) { + return X509Utils.X509_LU_FAIL; + } + return method.getByFingerprint.call(this,new Integer(type),bytes,ret); + } + + /** + * c: X509_LOOKUP_by_alias + */ + public int byAlias(int type, String str, X509Object[] ret) throws Exception { + if(method == null || method.getByAlias == null || method.getByAlias == Function4.EMPTY) { + return X509Utils.X509_LU_FAIL; + } + return method.getByAlias.call(this,new Integer(type),str,ret); + } + + /** + * c: X509_LOOKUP_shutdown + */ + public int shutdown() throws Exception { + if(method == null) { + return 0; + } + if(method.shutdown != null && method.shutdown != Function1.EMPTY) { + return method.shutdown.call(this); + } + return 1; + } + + /** + * c: x509_file_lookup + */ + private final static LookupMethod x509FileLookup = new LookupMethod(); + + /** + * c: x509_dir_lookup + */ + private final static LookupMethod x509DirectoryLookup = new LookupMethod(); + + static { + x509FileLookup.name = "Load file into cache"; + x509FileLookup.control = new ByFile(); + + x509DirectoryLookup.name = "Load certs from files in a directory"; + x509DirectoryLookup.newItem = new NewLookupDir(); + x509DirectoryLookup.free = new FreeLookupDir(); + x509DirectoryLookup.control = new LookupDirControl(); + x509DirectoryLookup.getBySubject = new GetCertificateBySubject(); + } + + /** + * c: by_file_ctrl + */ + private static class ByFile implements LookupMethod.ControlFunction { + public int call(Object _ctx, Object _cmd, Object _argp, Object _argl, Object _ret) throws Exception { + Lookup ctx = (Lookup)_ctx; + int cmd = ((Integer)_cmd).intValue(); + String argp = (String)_argp; + long argl = ((Long)_argl).longValue(); + + int ok = 0; + String file = null; + + switch(cmd) { + case X509Utils.X509_L_FILE_LOAD: + if (argl == X509Utils.X509_FILETYPE_DEFAULT) { + try { + file = System.getenv(X509Utils.getDefaultCertificateFileEnvironment()); + } catch (Error error) { + } + if (file != null) { + ok = ctx.loadCertificateOrCRLFile(file, X509Utils.X509_FILETYPE_PEM) != 0 ? 1 : 0; + } else { + ok = (ctx.loadCertificateOrCRLFile(X509Utils.getDefaultCertificateFile(), X509Utils.X509_FILETYPE_PEM) != 0) ? 1 : 0; + } + if (ok == 0) { + X509Error.addError(X509Utils.X509_R_LOADING_DEFAULTS); + } + } else { + if (argl == X509Utils.X509_FILETYPE_PEM) { + ok = (ctx.loadCertificateOrCRLFile(argp, X509Utils.X509_FILETYPE_PEM) != 0) ? 1 : 0; + } else { + ok = (ctx.loadCertificateFile(argp, (int) argl) != 0) ? 1 : 0; + } + } + break; + } + + return ok; + } + } + + /** + * c: BY_DIR, lookup_dir_st + */ + private static class LookupDir { + List dirs; + List dirsType; + } + + /** + * c: new_dir + */ + private static class NewLookupDir implements LookupMethod.NewItemFunction { + public int call(Object _lu) { + Lookup lu = (Lookup)_lu; + LookupDir a = new LookupDir(); + a.dirs = new ArrayList(); + a.dirsType = new ArrayList(); + lu.methodData = a; + return 1; + } + } + + /** + * c: free_dir + */ + private static class FreeLookupDir implements LookupMethod.FreeFunction { + public int call(Object _lu) { + Lookup lu = (Lookup)_lu; + LookupDir a = (LookupDir)lu.methodData; + a.dirs = null; + a.dirsType = null; + lu.methodData = null; + return -1; + } + } + + /** + * c: dir_ctrl + */ + private static class LookupDirControl implements LookupMethod.ControlFunction { + public int call(Object _ctx, Object _cmd, Object _argp, Object _argl, Object _retp) { + Lookup ctx = (Lookup)_ctx; + int cmd = ((Integer)_cmd).intValue(); + String argp = (String)_argp; + long argl = ((Long)_argl).longValue(); + int ret = 0; + LookupDir ld = (LookupDir)ctx.methodData; + String dir = null; + switch(cmd) { + case X509Utils.X509_L_ADD_DIR: + if(argl == X509Utils.X509_FILETYPE_DEFAULT) { + try { + dir = System.getenv(X509Utils.getDefaultCertificateDirectoryEnvironment()); + } catch (Error error) { + } + if(null != dir) { + ret = addCertificateDirectory(ld,dir,X509Utils.X509_FILETYPE_PEM); + } else { + ret = addCertificateDirectory(ld,X509Utils.getDefaultCertificateDirectory(),X509Utils.X509_FILETYPE_PEM); + } + if(ret == 0) { + X509Error.addError(X509Utils.X509_R_LOADING_CERT_DIR); + } + } else { + ret = addCertificateDirectory(ld,argp,(int)argl); + } + break; + } + return ret; + } + + /** + * c: add_cert_dir + */ + private int addCertificateDirectory(LookupDir ctx,String dir,int type) { + if(dir == null || "".equals(dir)) { + X509Error.addError(X509Utils.X509_R_INVALID_DIRECTORY); + return 0; + } + + String[] dirs = dir.split(System.getProperty("path.separator")); + + for(int i=0;i iter = ctx.dirsType.iterator(); + for(String cdir : ctx.dirs) { + int tp = iter.next(); + int k = 0; + for(;;) { + b.append(String.format("%s/%08x.%s%d", cdir, h, postfix, k)); + k++; + if(!(new File(b.toString()).exists())) { + break; + } + if(type == X509Utils.X509_LU_X509) { + if((x1.loadCertificateFile(b.toString(),tp)) == 0) { + break; + } + } else if(type == X509Utils.X509_LU_CRL) { + if((x1.loadCRLFile(b.toString(),tp)) == 0) { + break; + } + } + } + X509Object tmp = null; + synchronized(X509Utils.CRYPTO_LOCK_X509_STORE) { + for(X509Object o : x1.store.objs) { + if(o.type() == type && o.isName(name)) { + tmp = o; + break; + } + } + } + if(tmp != null) { + ok = 1; + ret[0] = tmp; + break; + } + } + + return ok; + } + } +}// X509_LOOKUP diff --git a/src/org/jruby/ext/openssl/x509store/LookupMethod.java b/src/org/jruby/ext/openssl/x509store/LookupMethod.java new file mode 100644 index 00000000000..8bf7f24a19f --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/LookupMethod.java @@ -0,0 +1,84 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * x509_lookup_method_st and X509_LOOKUP_METHOD in x509_vfy.h + * + * @author Ola Bini + */ +public class LookupMethod { + public String name; + + public static interface NewItemFunction extends Function1 {} + public static interface FreeFunction extends Function1 {} + public static interface InitFunction extends Function1 {} + public static interface ShutdownFunction extends Function1 {} + public static interface ControlFunction extends Function5 {} + public static interface BySubjectFunction extends Function4 {} + public static interface ByIssuerSerialNumberFunction extends Function5 {} + public static interface ByFingerprintFunction extends Function4 {} + public static interface ByAliasFunction extends Function4 {} + + /** + * c: new_item + */ + public NewItemFunction newItem; + /** + * c: free + */ + public FreeFunction free; + /** + * c: init + */ + public InitFunction init; + /** + * c: shutdown + */ + public ShutdownFunction shutdown; + /** + * c: ctrl + */ + public ControlFunction control; + /** + * c: get_by_subject + */ + public BySubjectFunction getBySubject; + /** + * c: get_by_issuer_serial + */ + public ByIssuerSerialNumberFunction getByIssuerSerialNumber; + /** + * c: get_by_fingerprint + */ + public ByFingerprintFunction getByFingerprint; + /** + * c: get_by_alias + */ + public ByAliasFunction getByAlias; +}// X509_LOOKUP_METHOD diff --git a/src/org/jruby/ext/openssl/x509store/Name.java b/src/org/jruby/ext/openssl/x509store/Name.java new file mode 100644 index 00000000000..71a945d6552 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Name.java @@ -0,0 +1,85 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.security.MessageDigest; + +import javax.security.auth.x500.X500Principal; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.x509.X509Name; + +/** + * c: X509_NAME + * + * @author Ola Bini + */ +public class Name { + public X509Name name; + + public Name(X500Principal nm) { + try { + this.name = new X509Name((ASN1Sequence)new ASN1InputStream(nm.getEncoded()).readObject()); + } catch(Exception e) { + this.name = null; + } + } + + public Name(X509Name nm) { + this.name = nm; + } + + /** + * c: X509_NAME_hash + */ + public long hash() { + try { + byte[] bytes = name.getEncoded(); + byte[] md = null; + MessageDigest md5 = MessageDigest.getInstance("MD5"); + md = md5.digest(bytes); + long result = 0; + result |= md[3] & 0xff; result <<= 8; + result |= md[2] & 0xff; result <<= 8; + result |= md[1] & 0xff; result <<= 8; + result |= md[0] & 0xff; + return result & 0xffffffff; + } catch(Exception e) { + return 0; + } + } + + public boolean isEqual(X500Principal oname) { + try { + return new X500Principal(name.getEncoded()).equals(oname); + } catch(Exception e) { + return false; + } + } +}// X509_NAME diff --git a/src/org/jruby/ext/openssl/x509store/PEMInputOutput.java b/src/org/jruby/ext/openssl/x509store/PEMInputOutput.java new file mode 100644 index 00000000000..1e28766572d --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/PEMInputOutput.java @@ -0,0 +1,1329 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * Copyright (C) 2007 William N Dortch + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.io.IOException; +import java.io.Writer; +import java.io.BufferedWriter; +import java.io.BufferedReader; +import java.io.Reader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; + +import java.math.BigInteger; + +import java.security.KeyPair; +import java.security.SecureRandom; +import java.security.cert.X509Certificate; +import java.security.cert.X509CRL; +import java.security.cert.CertificateEncodingException; +import java.security.interfaces.DSAPublicKey; +import java.security.interfaces.DSAPrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.interfaces.RSAPrivateCrtKey; +import java.security.spec.InvalidParameterSpecException; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.crypto.spec.DHParameterSpec; + +import org.jruby.ext.openssl.OpenSSLReal; +import org.jruby.ext.openssl.PKCS10CertificationRequestExt; + +import org.bouncycastle.asn1.ASN1Encodable; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OutputStream; +import org.bouncycastle.asn1.ASN1EncodableVector; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DERInteger; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERUTF8String; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.DERObjectIdentifier; +import org.bouncycastle.asn1.DERObject; +import org.bouncycastle.asn1.x509.DSAParameter; +import org.bouncycastle.asn1.cms.ContentInfo; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.pkcs.RSAPrivateKeyStructure; +import org.bouncycastle.asn1.x509.RSAPublicKeyStructure; +import org.bouncycastle.crypto.PBEParametersGenerator; +import org.bouncycastle.crypto.generators.OpenSSLPBEParametersGenerator; +import org.bouncycastle.crypto.params.KeyParameter; +import org.bouncycastle.util.encoders.Base64; +import org.bouncycastle.util.encoders.Hex; +import org.bouncycastle.cms.CMSSignedData; + +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.cert.CertificateFactory; +import java.security.spec.DSAPrivateKeySpec; +import java.security.spec.DSAPublicKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.KeySpec; +import java.security.spec.RSAPrivateCrtKeySpec; +import java.security.spec.RSAPublicKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.StringTokenizer; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.PBEParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import org.bouncycastle.asn1.pkcs.PKCS12PBEParams; +import org.bouncycastle.asn1.x509.AlgorithmIdentifier; +import org.jruby.ext.openssl.impl.ASN1Registry; + +/** + * Helper class to read and write PEM files correctly. + * + * @author Ola Bini + */ +public class PEMInputOutput { + public static final String BEF = "-----"; + public static final String AFT = "-----"; + public static final String BEF_G = BEF+"BEGIN "; + public static final String BEF_E = BEF+"END "; + public static final String PEM_STRING_X509_OLD="X509 CERTIFICATE"; + public static final String PEM_STRING_X509="CERTIFICATE"; + public static final String PEM_STRING_X509_PAIR="CERTIFICATE PAIR"; + public static final String PEM_STRING_X509_TRUSTED="TRUSTED CERTIFICATE"; + public static final String PEM_STRING_X509_REQ_OLD="NEW CERTIFICATE REQUEST"; + public static final String PEM_STRING_X509_REQ="CERTIFICATE REQUEST"; + public static final String PEM_STRING_X509_CRL="X509 CRL"; + public static final String PEM_STRING_EVP_PKEY="ANY PRIVATE KEY"; + public static final String PEM_STRING_PUBLIC="PUBLIC KEY"; + public static final String PEM_STRING_RSA="RSA PRIVATE KEY"; + public static final String PEM_STRING_RSA_PUBLIC="RSA PUBLIC KEY"; + public static final String PEM_STRING_DSA="DSA PRIVATE KEY"; + public static final String PEM_STRING_DSA_PUBLIC="DSA PUBLIC KEY"; + public static final String PEM_STRING_PKCS7="PKCS7"; + public static final String PEM_STRING_PKCS8="ENCRYPTED PRIVATE KEY"; + public static final String PEM_STRING_PKCS8INF="PRIVATE KEY"; + public static final String PEM_STRING_DHPARAMS="DH PARAMETERS"; + public static final String PEM_STRING_SSL_SESSION="SSL SESSION PARAMETERS"; + public static final String PEM_STRING_DSAPARAMS="DSA PARAMETERS"; + public static final String PEM_STRING_ECDSA_PUBLIC="ECDSA PUBLIC KEY"; + public static final String PEM_STRING_ECPARAMETERS="EC PARAMETERS"; + public static final String PEM_STRING_ECPRIVATEKEY="EC PRIVATE KEY"; + + private static final Pattern DH_PARAM_PATTERN = Pattern.compile( + "(-----BEGIN DH PARAMETERS-----)(.*)(-----END DH PARAMETERS-----)", + Pattern.MULTILINE); + private static final int DH_PARAM_GROUP = 2; // the group above containing encoded params + + private static BufferedReader makeBuffered(Reader in) { + if(in instanceof BufferedReader) { + return (BufferedReader)in; + } + return new BufferedReader(in); + } + + private static BufferedWriter makeBuffered(Writer out) { + if(out instanceof BufferedWriter) { + return (BufferedWriter)out; + } + return new BufferedWriter(out); + } + + /** + * c: PEM_X509_INFO_read_bio + */ + public static Object readPEM(Reader in,char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_PUBLIC) != -1) { + try { + return readPublicKey(_in,BEF_E+PEM_STRING_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating public key: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_DSA) != -1) { + try { + return readKeyPair(_in,f, "DSA", BEF_E+PEM_STRING_DSA); + } catch (Exception e) { + throw new IOException("problem creating DSA private key: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_RSA_PUBLIC) != -1) { + try { + return readPublicKey(_in,BEF_E+PEM_STRING_RSA_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating RSA public key: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_OLD) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509_OLD); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_TRUSTED) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509_TRUSTED); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_CRL) != -1) { + try { + return readCRL(_in,BEF_E+PEM_STRING_X509_CRL); + } catch (Exception e) { + throw new IOException("problem creating X509 CRL: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_REQ) != -1) { + try { + return readCertificateRequest(_in,BEF_E+PEM_STRING_X509_REQ); + } catch (Exception e) { + throw new IOException("problem creating X509 REQ: " + e.toString()); + } + } + } + return null; + } + + public static byte[] readX509PEM(Reader in) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if (line.indexOf(BEF_G + PEM_STRING_X509_OLD) != -1) { + try { + return readBytes(_in, BEF_E + PEM_STRING_X509_OLD); + } catch (Exception e) { + throw new IOException("problem reading PEM X509 Aux certificate: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_X509) != -1) { + try { + return readBytes(_in, BEF_E + PEM_STRING_X509); + } catch (Exception e) { + throw new IOException("problem reading PEM X509 Aux certificate: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_X509_TRUSTED) != -1) { + try { + return readBytes(_in, BEF_E + PEM_STRING_X509_TRUSTED); + } catch (Exception e) { + throw new IOException("problem reading PEM X509 Aux certificate: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_X509_CRL) != -1) { + try { + return readBytes(_in, BEF_E + PEM_STRING_X509_CRL); + } catch (Exception e) { + throw new IOException("problem reading PEM X509 CRL: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_X509_REQ) != -1) { + try { + return readBytes(_in, BEF_E + PEM_STRING_X509_REQ); + } catch (Exception e) { + throw new IOException("problem reading PEM X509 REQ: " + e.toString()); + } + } + } + return null; + } + + /** + * c: PEM_read_PrivateKey + PEM_read_bio_PrivateKey + * CAUTION: KeyPair#getPublic() may be null. + */ + public static KeyPair readPrivateKey(Reader in, char[] password) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if (line.indexOf(BEF_G + PEM_STRING_RSA) != -1) { + try { + return readKeyPair(_in, password, "RSA", BEF_E + PEM_STRING_RSA); + } catch (Exception e) { + throw new IOException("problem creating RSA private key: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_DSA) != -1) { + try { + return readKeyPair(_in, password, "DSA", BEF_E + PEM_STRING_DSA); + } catch (Exception e) { + throw new IOException("problem creating DSA private key: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_ECPRIVATEKEY) != -1) { + throw new IOException("EC private key not supported"); + } else if (line.indexOf(BEF_G + PEM_STRING_PKCS8INF) != -1) { + try { + byte[] bytes = readBytes(_in, BEF_E + PEM_STRING_PKCS8INF); + ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); + ASN1InputStream aIn = new ASN1InputStream(bIn); + PrivateKeyInfo info = new PrivateKeyInfo((ASN1Sequence) aIn.readObject()); + String type = getPrivateKeyTypeFromObjectId(info.getAlgorithmId().getObjectId()); + return readPrivateKeySequence(info.getPrivateKey().getDEREncoded(), type); + } catch (Exception e) { + throw new IOException("problem creating private key: " + e.toString()); + } + } else if (line.indexOf(BEF_G + PEM_STRING_PKCS8) != -1) { + try { + byte[] bytes = readBytes(_in, BEF_E + PEM_STRING_PKCS8); + ByteArrayInputStream bIn = new ByteArrayInputStream(bytes); + ASN1InputStream aIn = new ASN1InputStream(bIn); + org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo eIn = new org.bouncycastle.asn1.pkcs.EncryptedPrivateKeyInfo((ASN1Sequence) aIn.readObject()); + AlgorithmIdentifier algId = eIn.getEncryptionAlgorithm(); + String algorithm = ASN1Registry.o2a(algId.getObjectId()); + algorithm = (algorithm.split("-"))[0]; + PKCS12PBEParams pbeParams = new PKCS12PBEParams((ASN1Sequence) algId.getParameters()); + SecretKeyFactory fact = OpenSSLReal.getSecretKeyFactoryBC(algorithm); // need to use BC for PKCS12PBEParams. + PBEKeySpec pbeSpec = new PBEKeySpec(password); + SecretKey key = fact.generateSecret(pbeSpec); + PBEParameterSpec defParams = new PBEParameterSpec(pbeParams.getIV(), pbeParams.getIterations().intValue()); + Cipher cipher = OpenSSLReal.getCipherBC(algorithm); // need to use BC for PBEParameterSpec. + cipher.init(Cipher.UNWRAP_MODE, key, defParams); + // wrappedKeyAlgorithm is unknown ("") + PrivateKey privKey = (PrivateKey) cipher.unwrap(eIn.getEncryptedData(), "", Cipher.PRIVATE_KEY); + return new KeyPair(null, privKey); + } catch (Exception e) { + throw new IOException("problem creating private key: " + e.toString()); + } + } + } + return null; + } + + /* + * c: PEM_read_bio_DSA_PUBKEY + */ + public static DSAPublicKey readDSAPubKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_DSA_PUBLIC) != -1) { + try { + return (DSAPublicKey)readPublicKey(_in,"DSA",BEF_E+PEM_STRING_DSA_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating DSA public key: " + e.toString()); + } + } + } + return null; + } + + /* + * c: PEM_read_bio_DSAPublicKey + */ + public static DSAPublicKey readDSAPublicKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_PUBLIC) != -1) { + try { + return (DSAPublicKey)readPublicKey(_in,"DSA",BEF_E+PEM_STRING_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating DSA public key: " + e.toString()); + } + } + } + return null; + } + + /* + * c: PEM_read_bio_DSAPrivateKey + */ + public static KeyPair readDSAPrivateKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_DSA) != -1) { + try { + return readKeyPair(_in,f, "DSA", BEF_E+PEM_STRING_DSA); + } catch (Exception e) { + throw new IOException("problem creating DSA private key: " + e.toString()); + } + } + } + return null; + } + + /** + * reads an RSA public key encoded in an SubjectPublicKeyInfo RSA structure. + * c: PEM_read_bio_RSA_PUBKEY + */ + public static RSAPublicKey readRSAPubKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_PUBLIC) != -1) { + try { + return readRSAPublicKey(_in,BEF_E+PEM_STRING_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating RSA public key: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_RSA_PUBLIC) != -1) { + try { + return readRSAPublicKey(_in,BEF_E+PEM_STRING_RSA_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating RSA public key: " + e.toString()); + } + } + } + return null; + } + + /** + * reads an RSA public key encoded in an PKCS#1 RSA structure. + * c: PEM_read_bio_RSAPublicKey + */ + public static RSAPublicKey readRSAPublicKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_PUBLIC) != -1) { + try { + return (RSAPublicKey)readPublicKey(_in,"RSA",BEF_E+PEM_STRING_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating RSA public key: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_RSA_PUBLIC) != -1) { + try { + return (RSAPublicKey)readPublicKey(_in,"RSA",BEF_E+PEM_STRING_RSA_PUBLIC); + } catch (Exception e) { + throw new IOException("problem creating RSA public key: " + e.toString()); + } + } + } + return null; + } + + /** + * c: PEM_read_bio_RSAPrivateKey + */ + public static KeyPair readRSAPrivateKey(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_RSA) != -1) { + try { + return readKeyPair(_in,f, "RSA", BEF_E+PEM_STRING_RSA); + } catch (Exception e) { + throw new IOException("problem creating RSA private key: " + e.toString()); + } + } + } + return null; + } + public static CMSSignedData readPKCS7(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_PKCS7) != -1) { + try { + return readPKCS7(_in,f, BEF_E+PEM_STRING_PKCS7); + } catch (Exception e) { + throw new IOException("problem creating PKCS7: " + e.toString()); + } + } + } + return null; + } + public static X509AuxCertificate readX509Certificate(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_X509_OLD) != -1) { + try { + return new X509AuxCertificate(readCertificate(_in,BEF_E+PEM_STRING_X509_OLD)); + } catch (Exception e) { + throw new IOException("problem creating X509 certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509) != -1) { + try { + return new X509AuxCertificate(readCertificate(_in,BEF_E+PEM_STRING_X509)); + } catch (Exception e) { + throw new IOException("problem creating X509 certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_TRUSTED) != -1) { + try { + return new X509AuxCertificate(readCertificate(_in,BEF_E+PEM_STRING_X509_TRUSTED)); + } catch (Exception e) { + throw new IOException("problem creating X509 certificate: " + e.toString()); + } + } + } + return null; + } + public static X509AuxCertificate readX509Aux(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_X509_OLD) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509_OLD); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } else if(line.indexOf(BEF_G+PEM_STRING_X509_TRUSTED) != -1) { + try { + return readAuxCertificate(_in,BEF_E+PEM_STRING_X509_TRUSTED); + } catch (Exception e) { + throw new IOException("problem creating X509 Aux certificate: " + e.toString()); + } + } + } + return null; + } + public static X509CRL readX509CRL(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_X509_CRL) != -1) { + try { + return readCRL(_in,BEF_E+PEM_STRING_X509_CRL); + } catch (Exception e) { + throw new IOException("problem creating X509 CRL: " + e.toString()); + } + } + } + return null; + } + public static PKCS10CertificationRequestExt readX509Request(Reader in, char[] f) throws IOException { + BufferedReader _in = makeBuffered(in); + String line; + while ((line = _in.readLine()) != null) { + if(line.indexOf(BEF_G+PEM_STRING_X509_REQ) != -1) { + try { + return readCertificateRequest(_in,BEF_E+PEM_STRING_X509_REQ); + } catch (Exception e) { + throw new IOException("problem creating X509 REQ: " + e.toString()); + } + } + } + return null; + } + + public static DHParameterSpec readDHParameters(Reader _in) + throws IOException, InvalidParameterSpecException { + BufferedReader in = makeBuffered(_in); + String line; + StringBuilder buf = new StringBuilder(); + while ((line = in.readLine()) != null) { + if (line.indexOf(BEF_G + PEM_STRING_DHPARAMS) >= 0) { + do { + buf.append(line.trim()); + } while (line.indexOf(BEF_E + PEM_STRING_DHPARAMS) < 0 && + (line = in.readLine()) != null); + break; + } + } + Matcher m = DH_PARAM_PATTERN.matcher(buf.toString()); + if (m.find()) { + try { + byte[] decoded = Base64.decode(m.group(DH_PARAM_GROUP)); + ASN1InputStream aIn = new ASN1InputStream(new ByteArrayInputStream(decoded)); + ASN1Sequence seq = (ASN1Sequence)aIn.readObject(); + BigInteger p = ((DERInteger)seq.getObjectAt(0)).getValue(); + BigInteger g = ((DERInteger)seq.getObjectAt(1)).getValue(); + return new DHParameterSpec(p, g); + } catch (Exception e) {} + } + // probably not exactly the intended use of this exception, but + // close enough for internal throw/catch + throw new InvalidParameterSpecException("invalid " + PEM_STRING_DHPARAMS); + } + + private static byte[] getEncoded(java.security.Key key) { + if (key != null) { + return key.getEncoded(); + } + return new byte[] { '0', 0 }; + } + + private static byte[] getEncoded(ASN1Encodable obj) throws IOException { + if (obj != null) { + return obj.getEncoded(); + } + return new byte[] { '0', 0 }; + } + + private static byte[] getEncoded(CMSSignedData obj) throws IOException { + if (obj != null) { + return obj.getEncoded(); + } + return new byte[] { '0', 0 }; + } + + private static byte[] getEncoded(X509Certificate cert) throws IOException { + if (cert != null) { + try { + return cert.getEncoded(); + } catch (GeneralSecurityException gse) { + throw new IOException("problem with encoding object in write_X509"); + } + } + return new byte[] { '0', 0 }; + } + + private static byte[] getEncoded(X509CRL crl) throws IOException { + if (crl != null) { + try { + return crl.getEncoded(); + } catch (GeneralSecurityException gse) { + throw new IOException("problem with encoding object in write_X509_CRL"); + } + } + return new byte[] { '0', 0 }; + } + + public static void writeDSAPublicKey(Writer _out, DSAPublicKey obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_DSA_PUBLIC + AFT); + out.newLine(); + writeEncoded(out, encoding); + out.write(BEF_E + PEM_STRING_DSA_PUBLIC + AFT); + out.newLine(); + out.flush(); + } + /** writes an RSA public key encoded in an PKCS#1 RSA structure. */ + public static void writeRSAPublicKey(Writer _out, RSAPublicKey obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_RSA_PUBLIC + AFT); + out.newLine(); + writeEncoded(out, encoding); + out.write(BEF_E + PEM_STRING_RSA_PUBLIC + AFT); + out.newLine(); + out.flush(); + } + public static void writePKCS7(Writer _out, ContentInfo obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_PKCS7 + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_PKCS7 + AFT); + out.newLine(); + out.flush(); + } + public static void writePKCS7(Writer _out, CMSSignedData obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_PKCS7 + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_PKCS7 + AFT); + out.newLine(); + out.flush(); + } + public static void writePKCS7(Writer _out, byte[] encoded) throws IOException { + BufferedWriter out = makeBuffered(_out); + out.write(BEF_G + PEM_STRING_PKCS7 + AFT); + out.newLine(); + writeEncoded(out,encoded); + out.write(BEF_E + PEM_STRING_PKCS7 + AFT); + out.newLine(); + out.flush(); + } + public static void writeX509Certificate(Writer _out, X509Certificate obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_X509 + AFT); + out.newLine(); + writeEncoded(out, encoding); + out.write(BEF_E + PEM_STRING_X509 + AFT); + out.newLine(); + out.flush(); + } + public static void writeX509Aux(Writer _out, X509AuxCertificate obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = null; + try { + if(obj.getAux() == null) { + encoding = obj.getEncoded(); + } else { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + byte[] ymp = obj.getEncoded(); + baos.write(ymp,0,ymp.length); + + X509Aux aux = obj.getAux(); + ASN1EncodableVector a1 = new ASN1EncodableVector(); + if(aux.trust.size()>0) { + ASN1EncodableVector a2 = new ASN1EncodableVector(); + for(String trust : aux.trust) { + a2.add(new DERObjectIdentifier(trust)); + } + a1.add(new DERSequence(a2)); + } + if(aux.reject.size()>0) { + ASN1EncodableVector a2 = new ASN1EncodableVector(); + for(String reject : aux.reject) { + a2.add(new DERObjectIdentifier(reject)); + } + a1.add(new DERTaggedObject(0,new DERSequence(a2))); + } + if(aux.alias != null) { + a1.add(new DERUTF8String(aux.alias)); + } + if(aux.keyid != null) { + a1.add(new DEROctetString(aux.keyid)); + } + if(aux.other.size()>0) { + ASN1EncodableVector a2 = new ASN1EncodableVector(); + for(DERObject other : aux.other) { + a2.add(other); + } + a1.add(new DERTaggedObject(1,new DERSequence(a2))); + } + ymp = new DERSequence(a1).getEncoded(); + baos.write(ymp,0,ymp.length); + encoding = baos.toByteArray(); + } + } catch(CertificateEncodingException e) { + throw new IOException("problem with encoding object in write_X509_AUX"); + } + out.write(BEF_G + PEM_STRING_X509_TRUSTED + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_X509_TRUSTED + AFT); + out.newLine(); + out.flush(); + } + public static void writeX509CRL(Writer _out, X509CRL obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_X509_CRL + AFT); + out.newLine(); + writeEncoded(out, encoding); + out.write(BEF_E + PEM_STRING_X509_CRL + AFT); + out.newLine(); + out.flush(); + } + public static void writeX509Request(Writer _out, PKCS10CertificationRequestExt obj) throws IOException { + BufferedWriter out = makeBuffered(_out); + byte[] encoding = getEncoded(obj); + out.write(BEF_G + PEM_STRING_X509_REQ + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_X509_REQ + AFT); + out.newLine(); + out.flush(); + } + + private static SecureRandom random; + static { + try { + random = SecureRandom.getInstance("SHA1PRNG"); + } catch(Exception e) { + random = null; + } + } + + public static void writeDSAPrivateKey(Writer _out, DSAPrivateKey obj, String algo, char[] f) throws IOException { + BufferedWriter out = makeBuffered(_out); + ByteArrayInputStream bIn = new ByteArrayInputStream(getEncoded(obj)); + ASN1InputStream aIn = new ASN1InputStream(bIn); + PrivateKeyInfo info = new PrivateKeyInfo((ASN1Sequence)aIn.readObject()); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream aOut = new ASN1OutputStream(bOut); + + DSAParameter p = DSAParameter.getInstance(info.getAlgorithmId().getParameters()); + ASN1EncodableVector v = new ASN1EncodableVector(); + + v.add(new DERInteger(0)); + v.add(new DERInteger(p.getP())); + v.add(new DERInteger(p.getQ())); + v.add(new DERInteger(p.getG())); + + BigInteger x = obj.getX(); + BigInteger y = p.getG().modPow(x, p.getP()); + + v.add(new DERInteger(y)); + v.add(new DERInteger(x)); + + aOut.writeObject(new DERSequence(v)); + byte[] encoding = bOut.toByteArray(); + + if(algo != null && f != null) { + byte[] salt = new byte[8]; + byte[] encData = null; + random.nextBytes(salt); + OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(f), salt); + SecretKey secretKey = null; + if (algo.equalsIgnoreCase("DESede/CBC/PKCS5Padding")) { + // generate key + int keyLength = 24; + KeyParameter param = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8); + secretKey = new SecretKeySpec(param.getKey(), "DESede"); + } else { + throw new IOException("unknown algorithm in write_DSAPrivateKey: " + algo); + } + + // cipher + try { + Cipher c = Cipher.getInstance("DESede/CBC/PKCS5Padding"); + c.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(salt)); + encData = c.doFinal(encoding); + } catch (Exception e) { + throw new IOException("exception using cipher: " + e.toString()); + } + + // write the data + out.write(BEF_G + PEM_STRING_DSA + AFT); + out.newLine(); + out.write("Proc-Type: 4,ENCRYPTED"); + out.newLine(); + out.write("DEK-Info: DES-EDE3-CBC,"); + writeHexEncoded(out,salt); + out.newLine(); + out.newLine(); + writeEncoded(out,encData); + out.write(BEF_E + PEM_STRING_DSA + AFT); + out.flush(); + } else { + out.write(BEF_G + PEM_STRING_DSA + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_DSA + AFT); + out.newLine(); + out.flush(); + } + } + + public static void writeRSAPrivateKey(Writer _out, RSAPrivateCrtKey obj, String algo, char[] f) throws IOException { + assert(obj != null); + BufferedWriter out = makeBuffered(_out); + RSAPrivateKeyStructure keyStruct = new RSAPrivateKeyStructure( + obj.getModulus(), + obj.getPublicExponent(), + obj.getPrivateExponent(), + obj.getPrimeP(), + obj.getPrimeQ(), + obj.getPrimeExponentP(), + obj.getPrimeExponentQ(), + obj.getCrtCoefficient()); + + // convert to bytearray + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream aOut = new ASN1OutputStream(bOut); + + aOut.writeObject(keyStruct); + aOut.close(); + + byte[] encoding = bOut.toByteArray(); + + if(algo != null && f != null) { + byte[] salt = new byte[8]; + byte[] encData = null; + random.nextBytes(salt); + OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(f), salt); + SecretKey secretKey = null; + + if (algo.startsWith("DES")) { + // generate key + int keyLength = 24; + if (algo.equalsIgnoreCase("DESEDE")) { + algo = "DESede/CBC/PKCS5Padding"; + } + KeyParameter param = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8); + secretKey = new SecretKeySpec(param.getKey(), algo.split("/")[0]); + } else { + throw new IOException("unknown algorithm `" + algo + "' in write_DSAPrivateKey"); + } + + // cipher + try { + Cipher c = Cipher.getInstance(algo); + c.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(salt)); + encData = c.doFinal(encoding); + } catch (Exception e) { + throw new IOException("exception using cipher: " + e.toString()); + } + + // write the data + out.write(BEF_G + PEM_STRING_RSA + AFT); + out.newLine(); + out.write("Proc-Type: 4,ENCRYPTED"); + out.newLine(); + out.write("DEK-Info: DES-EDE3-CBC,"); + writeHexEncoded(out,salt); + out.newLine(); + out.newLine(); + writeEncoded(out,encData); + out.write(BEF_E + PEM_STRING_RSA + AFT); + out.flush(); + } else { + out.write(BEF_G + PEM_STRING_RSA + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_RSA + AFT); + out.newLine(); + out.flush(); + } + } + + public static void writeDHParameters(Writer _out, DHParameterSpec params) throws IOException { + BufferedWriter out = makeBuffered(_out); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + ASN1OutputStream aOut = new ASN1OutputStream(bOut); + + ASN1EncodableVector v = new ASN1EncodableVector(); + + BigInteger value; + if ((value = params.getP()) != null) { + v.add(new DERInteger(value)); + } + if ((value = params.getG()) != null) { + v.add(new DERInteger(value)); + } + + aOut.writeObject(new DERSequence(v)); + byte[] encoding = bOut.toByteArray(); + + out.write(BEF_G + PEM_STRING_DHPARAMS + AFT); + out.newLine(); + writeEncoded(out,encoding); + out.write(BEF_E + PEM_STRING_DHPARAMS + AFT); + out.newLine(); + out.flush(); + } + + private static String getPrivateKeyTypeFromObjectId(DERObjectIdentifier oid) { + if (ASN1Registry.obj2nid(oid) == ASN1Registry.NID_rsaEncryption) { + return "RSA"; + } else { + return "DSA"; + } + } + + private static byte[] readBytes(BufferedReader in, String endMarker) throws IOException { + String line; + StringBuffer buf = new StringBuffer(); + + while ((line = in.readLine()) != null) { + if (line.indexOf(endMarker) != -1) { + break; + } + buf.append(line.trim()); + } + + if (line == null) { + throw new IOException(endMarker + " not found"); + } + + return Base64.decode(buf.toString()); + } + + /** + * create the secret key needed for this object, fetching the password + */ + private static SecretKey getKey(char[] k1, String algorithm, int keyLength, byte[] salt) throws IOException { + char[] password = k1; + if (password == null) { + throw new IOException("Password is null, but a password is required"); + } + OpenSSLPBEParametersGenerator pGen = new OpenSSLPBEParametersGenerator(); + pGen.init(PBEParametersGenerator.PKCS5PasswordToBytes(password), salt); + KeyParameter param = (KeyParameter) pGen.generateDerivedParameters(keyLength * 8); + return new javax.crypto.spec.SecretKeySpec(param.getKey(), algorithm); + } + + private static RSAPublicKey readRSAPublicKey(BufferedReader in, String endMarker) throws IOException { + ByteArrayInputStream bAIS = new ByteArrayInputStream(readBytes(in,endMarker)); + ASN1InputStream ais = new ASN1InputStream(bAIS); + Object asnObject = ais.readObject(); + ASN1Sequence sequence = (ASN1Sequence) asnObject; + RSAPublicKeyStructure rsaPubStructure = new RSAPublicKeyStructure(sequence); + RSAPublicKeySpec keySpec = new RSAPublicKeySpec( + rsaPubStructure.getModulus(), + rsaPubStructure.getPublicExponent()); + + try { + KeyFactory keyFact = KeyFactory.getInstance("RSA"); + return (RSAPublicKey) keyFact.generatePublic(keySpec); + } catch (NoSuchAlgorithmException e) { + // ignore + } catch (InvalidKeySpecException e) { + // ignore + } + + return null; + } + + private static PublicKey readPublicKey(BufferedReader in, String alg, String endMarker) throws IOException { + KeySpec keySpec = new X509EncodedKeySpec(readBytes(in,endMarker)); + try { + KeyFactory keyFact = KeyFactory.getInstance(alg); + PublicKey pubKey = keyFact.generatePublic(keySpec); + return pubKey; + } catch (NoSuchAlgorithmException e) { + // ignore + } catch (InvalidKeySpecException e) { + // ignore + } + return null; + } + + private static PublicKey readPublicKey(BufferedReader in, String endMarker) throws IOException { + KeySpec keySpec = new X509EncodedKeySpec(readBytes(in,endMarker)); + String[] algs = {"RSA","DSA"}; + for(int i=0;i ix && aux.getObjectAt(ix) instanceof DERSequence) { + DERSequence trust = (DERSequence)aux.getObjectAt(ix++); + for(int i=0;i ix && aux.getObjectAt(ix) instanceof DERTaggedObject && ((DERTaggedObject)aux.getObjectAt(ix)).getTagNo() == 0) { + DERSequence reject = (DERSequence)((DERTaggedObject)aux.getObjectAt(ix++)).getObject(); + for(int i=0;iix && aux.getObjectAt(ix) instanceof DERUTF8String) { + ax.alias = ((DERUTF8String)aux.getObjectAt(ix++)).getString(); + } + if(aux.size()>ix && aux.getObjectAt(ix) instanceof DEROctetString) { + ax.keyid = ((DEROctetString)aux.getObjectAt(ix++)).getOctets(); + } + if(aux.size() > ix && aux.getObjectAt(ix) instanceof DERTaggedObject && ((DERTaggedObject)aux.getObjectAt(ix)).getTagNo() == 1) { + DERSequence other = (DERSequence)((DERTaggedObject)aux.getObjectAt(ix++)).getObject(); + for(int i=0;i= bytes.length) { + break; + } + buf[index] = (char)bytes[i + index]; + index++; + } + out.write(buf, 0, index); + out.newLine(); + } + } + + /** + * Reads in a PKCS7 object. This returns a ContentInfo object suitable for use with the CMS + * API. + * + * @return the X509Certificate + * @throws IOException if an I/O error occured + */ + private static CMSSignedData readPKCS7(BufferedReader in, char[] p, String endMarker) throws IOException { + String line; + StringBuffer buf = new StringBuffer(); + ByteArrayOutputStream bOut = new ByteArrayOutputStream(); + + while ((line = in.readLine()) != null) { + if (line.indexOf(endMarker) != -1) { + break; + } + line = line.trim(); + buf.append(line.trim()); + Base64.decode(buf.substring(0, (buf.length() / 4) * 4), bOut); + buf.delete(0, (buf.length() / 4) * 4); + } + if (buf.length() != 0) { + throw new RuntimeException("base64 data appears to be truncated"); + } + if (line == null) { + throw new IOException(endMarker + " not found"); + } + ByteArrayInputStream bIn = new ByteArrayInputStream(bOut.toByteArray()); + try { + ASN1InputStream aIn = new ASN1InputStream(bIn); + return new CMSSignedData(ContentInfo.getInstance(aIn.readObject())); + } catch (Exception e) { + throw new IOException("problem parsing PKCS7 object: " + e.toString()); + } + } +}// PEM diff --git a/src/org/jruby/ext/openssl/x509store/PKey.java b/src/org/jruby/ext/openssl/x509store/PKey.java new file mode 100644 index 00000000000..f3be5b9909e --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/PKey.java @@ -0,0 +1,41 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * c: X509_OBJECT + * + * @author Ola Bini + */ +public class PKey extends X509Object { + public java.security.PrivateKey pkey; + + public int type() { + return X509Utils.X509_LU_PKEY; + } +}// X509_OBJECT_PKEY diff --git a/src/org/jruby/ext/openssl/x509store/PolicyTree.java b/src/org/jruby/ext/openssl/x509store/PolicyTree.java new file mode 100644 index 00000000000..a8223a1cf49 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/PolicyTree.java @@ -0,0 +1,36 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +/** + * c: X509_POLICY_TREE + * + * @author Ola Bini + */ +public class PolicyTree { +}// X509_POLICY_TREE diff --git a/src/org/jruby/ext/openssl/x509store/Purpose.java b/src/org/jruby/ext/openssl/x509store/Purpose.java new file mode 100644 index 00000000000..dee67949343 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Purpose.java @@ -0,0 +1,475 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + + +import java.util.ArrayList; +import java.util.List; + +/** + * c: X509_PURPOSE + * + * @author Ola Bini + */ +public class Purpose { + private static final String XKU_EMAIL_PROTECT = "1.3.6.1.5.5.7.3.4"; // Email protection + private static final String XKU_SSL_CLIENT = "1.3.6.1.5.5.7.3.2"; // SSL Client Authentication + private static final String[] XKU_SSL_SERVER = new String[]{ + "1.3.6.1.5.5.7.3.1", // SSL Server Authentication + "2.16.840.1.113730.4.1", // Netscape Server Gated Crypto + "1.3.6.1.4.1.311.10.3.3" // Microsoft Server Gated Crypto + }; + + public static interface CheckPurposeFunction extends Function3 { + public static final CheckPurposeFunction EMPTY = new CheckPurposeFunction(){ + public int call(Object arg0, Object arg1, Object arg2) { + return -1; + } + }; + } + + public int purpose; + public int trust; /* Default trust ID */ + public int flags; + public CheckPurposeFunction checkPurpose; + public String name; + public String sname; + public Object userData; + + public Purpose() {} + + public Purpose(int p, int t, int f, CheckPurposeFunction cp, String n, String s, Object u) { + this.purpose = p; this.trust = t; + this.flags = f; this.checkPurpose = cp; + this.name = n; this.sname = s; + this.userData = u; + } + + /** + * c: X509_check_purpose + */ + public static int checkPurpose(X509AuxCertificate x, int id, int ca) throws Exception { + if(id == -1) { + return 1; + } + int idx = getByID(id); + if(idx == -1) { + return -1; + } + Purpose pt = getFirst(idx); + return pt.checkPurpose.call(pt,x,new Integer(ca)); + } + + /** + * c: X509_PURPOSE_set + */ + public static int set(int[] p, int purpose) { + if(getByID(purpose) == -1) { + X509Error.addError(X509Utils.X509V3_R_INVALID_PURPOSE); + return 0; + } + p[0] = purpose; + return 1; + } + + private final static List xptable = new ArrayList(); + + /** + * c: X509_PURPOSE_get_count + */ + public static int getCount() { + return xptable.size() + xstandard.length; + } + + /** + * c: X509_PURPOSE_get0 + */ + public static Purpose getFirst(int idx) { + if(idx < 0) { + return null; + } + if(idx < xstandard.length) { + return xstandard[idx]; + } + return xptable.get(idx - xstandard.length); + } + + /** + * c: X509_PURPOSE_get_by_sname + */ + public static int getBySName(String sname) { + for(int i=0;i= X509Utils.X509_PURPOSE_MIN && (purpose <= X509Utils.X509_PURPOSE_MAX)) { + return purpose - X509Utils.X509_PURPOSE_MIN; + } + int i = 0; + for(Purpose p : xptable) { + if(p.purpose == purpose) { + return i + xstandard.length; + } + } + return -1; + } + + /** + * c: X509_PURPOSE_add + */ + public static int add(int id, int trust, int flags, CheckPurposeFunction ck, String name, String sname, Object arg) { + flags &= ~X509Utils.X509_PURPOSE_DYNAMIC; + flags |= X509Utils.X509_PURPOSE_DYNAMIC_NAME; + int idx = getByID(id); + Purpose ptmp; + if(idx == -1) { + ptmp = new Purpose(); + ptmp.flags = X509Utils.X509_PURPOSE_DYNAMIC; + } else { + ptmp = getFirst(idx); + } + ptmp.name = name; + ptmp.sname = sname; + ptmp.flags &= X509Utils.X509_PURPOSE_DYNAMIC; + ptmp.flags |= flags; + ptmp.purpose = id; + ptmp.trust = trust; + ptmp.checkPurpose = ck; + ptmp.userData = arg; + if(idx == -1) { + xptable.add(ptmp); + } + return 1; + } + + /** + * c: X509_PURPOSE_cleanup + */ + public static void cleanup() { + xptable.clear(); + } + + /** + * c: X509_PURPOSE_get_id + */ + public int getID() { + return purpose; + } + + /** + * c: X509_PURPOSE_get0_name + */ + public String getName() { + return name; + } + + /** + * c: X509_PURPOSE_get0_sname + */ + public String getSName() { + return sname; + } + + /** + * c: X509_PURPOSE_get_trust + */ + public int getTrust() { + return trust; + } + + /** + * c: X509_check_ca + */ + public static int checkCA(X509AuxCertificate x) throws Exception { + if(x.getKeyUsage() != null && !x.getKeyUsage()[5]) { // KEY_CERT_SIGN + return 0; + } + if(x.getExtensionValue("2.5.29.19") != null) { // BASIC_CONSTRAINTS + if(x.getBasicConstraints() != -1) { // is CA. + return 1; + } else { + return 0; + } + } else { + if(x.getVersion() == 1 && x.getIssuerX500Principal().equals(x.getSubjectX500Principal())) { // V1_ROOT + return 3; + } + if(x.getKeyUsage() != null) { + return 4; + } + Integer nsCertType = x.getNsCertType(); + if (nsCertType != null && (nsCertType & X509Utils.NS_ANY_CA) != 0) { + return 5; + } + return 0; + } + } + + /** + * c: check_ssl_ca + */ + public static int checkSSLCA(X509AuxCertificate x) throws Exception { + int ca_ret = checkCA(x); + if(ca_ret == 0) { + return 0; + } + Integer nsCertType = x.getNsCertType(); + boolean v2 = nsCertType != null && (nsCertType & X509Utils.NS_SSL_CA) != 0; + if(ca_ret != 5 || v2) { + return ca_ret; + } + return 0; + } + + /** + * c: xku_reject: check if the cert must be rejected(true) or not + */ + public static boolean xkuReject(X509AuxCertificate x, String mustHaveXku) throws Exception { + List xku = x.getExtendedKeyUsage(); + return (xku != null) && !xku.contains(mustHaveXku); + } + public static boolean xkuReject(X509AuxCertificate x, String[] mustHaveOneOfXku) throws Exception { + List xku = x.getExtendedKeyUsage(); + if(xku == null) { + return false; + } + for (String mustHaveXku : mustHaveOneOfXku) { + if(xku.contains(mustHaveXku)) { + return false; + } + } + return true; + } + + /** + * c: ns_reject + */ + public static boolean nsReject(X509AuxCertificate x, int mustHaveCertType) throws Exception { + Integer nsCertType = x.getNsCertType(); + return (nsCertType != null) && (nsCertType & mustHaveCertType) == 0; + } + + /** + * c: purpose_smime + */ + public static int purposeSMIME(X509AuxCertificate x, int ca) throws Exception { + if(xkuReject(x,XKU_EMAIL_PROTECT)) { + return 0; // must allow email protection + } + if(ca != 0) { + int ca_ret = checkCA(x); + if(ca_ret == 0) { + return 0; + } + Integer nsCertType = x.getNsCertType(); + boolean v2 = nsCertType != null && (nsCertType & X509Utils.NS_SMIME_CA) != 0; + if(ca_ret != 5 || v2) { + return ca_ret; + } else { + return 0; + } + } + Integer nsCertType = x.getNsCertType(); + if (nsCertType != null) { + if ((nsCertType & X509Utils.NS_SMIME) != 0) { + return 1; + } + if ((nsCertType & X509Utils.NS_SSL_CLIENT) != 0) { + return 2; + } + return 0; + } + return 1; + } + + /** + * c: check_purpose_ssl_client + */ + public final static CheckPurposeFunction checkPurposeSSLClient = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + X509AuxCertificate x = (X509AuxCertificate)_x; + if(xkuReject(x, XKU_SSL_CLIENT)) { + return 0; + } + int ca = ((Integer)_ca).intValue(); + if(ca != 0) { + return checkSSLCA(x); + } + if(x.getKeyUsage() != null && !x.getKeyUsage()[0]) { + return 0; + } + if(nsReject(x, X509Utils.NS_SSL_CLIENT)) { + // when the cert has nsCertType, it must include NS_SSL_CLIENT + return 0; + } + return 1; + } + }; + + /** + * c: check_purpose_ssl_server + */ + public final static CheckPurposeFunction checkPurposeSSLServer = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + X509AuxCertificate x = (X509AuxCertificate)_x; + int ca = ((Integer)_ca).intValue(); + if(xkuReject(x, XKU_SSL_SERVER)) { + return 0; + } + if(ca != 0) { + return checkSSLCA(x); + } + if(nsReject(x, X509Utils.NS_SSL_SERVER)) { + // when the cert has nsCertType, it must include NS_SSL_SERVER + return 0; + } + if(x.getKeyUsage() != null && (!x.getKeyUsage()[0] || !x.getKeyUsage()[2])) { + return 0; + } + return 1; + } + }; + + /** + * c: check_purpose_ns_ssl_server + */ + public final static CheckPurposeFunction checkPurposeNSSSLServer = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + Purpose xp = (Purpose)_xp; + X509AuxCertificate x = (X509AuxCertificate)_x; + int ca = ((Integer)_ca).intValue(); + int ret = checkPurposeSSLServer.call(xp,x,_ca); + if(ret == 0 || ca != 0) { + return ret; + } + if(x.getKeyUsage() != null && !x.getKeyUsage()[2]) { + return 0; + } + return 1; + } + }; + + /** + * c: check_purpose_smime_sign + */ + public final static CheckPurposeFunction checkPurposeSMIMESign = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + X509AuxCertificate x = (X509AuxCertificate)_x; + int ca = ((Integer)_ca).intValue(); + int ret = purposeSMIME(x,ca); + if(ret == 0 || ca != 0) { + return ret; + } + if(x.getKeyUsage() != null && (!x.getKeyUsage()[0] || !x.getKeyUsage()[1])) { + return 0; + } + return ret; + } + }; + + /** + * c: check_purpose_smime_encrypt + */ + public final static CheckPurposeFunction checkPurposeSMIMEEncrypt = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + X509AuxCertificate x = (X509AuxCertificate)_x; + int ca = ((Integer)_ca).intValue(); + int ret = purposeSMIME(x,ca); + if(ret == 0 || ca != 0) { + return ret; + } + if(x.getKeyUsage() != null && !x.getKeyUsage()[2]) { + return 0; + } + return ret; + } + }; + + /** + * c: check_purpose_crl_sign + */ + public final static CheckPurposeFunction checkPurposeCRLSign = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + X509AuxCertificate x = (X509AuxCertificate)_x; + int ca = ((Integer)_ca).intValue(); + + if(ca != 0) { + int ca_ret = checkCA(x); + if(ca_ret != 2) { + return ca_ret; + } + return 0; + } + if(x.getKeyUsage() != null && !x.getKeyUsage()[6]) { + return 0; + } + return 1; + } + }; + + /** + * c: no_check + */ + public final static CheckPurposeFunction noCheck = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) { + return 1; + } + }; + + /** + * c: ocsp_helper + */ + public final static CheckPurposeFunction oscpHelper = new CheckPurposeFunction() { + public int call(Object _xp, Object _x, Object _ca) throws Exception { + if(((Integer)_ca).intValue() != 0) { + return checkCA((X509AuxCertificate)_x); + } + return 1; + } + }; + + public final static Purpose[] xstandard = new Purpose[] { + new Purpose(X509Utils.X509_PURPOSE_SSL_CLIENT, X509Utils.X509_TRUST_SSL_CLIENT, 0, checkPurposeSSLClient, "SSL client", "sslclient", null), + new Purpose(X509Utils.X509_PURPOSE_SSL_SERVER, X509Utils.X509_TRUST_SSL_SERVER, 0, checkPurposeSSLServer, "SSL server", "sslserver", null), + new Purpose(X509Utils.X509_PURPOSE_NS_SSL_SERVER, X509Utils.X509_TRUST_SSL_SERVER, 0, checkPurposeNSSSLServer, "Netscape SSL server", "nssslserver", null), + new Purpose(X509Utils.X509_PURPOSE_SMIME_SIGN, X509Utils.X509_TRUST_EMAIL, 0, checkPurposeSMIMESign, "S/MIME signing", "smimesign", null), + new Purpose(X509Utils.X509_PURPOSE_SMIME_ENCRYPT, X509Utils.X509_TRUST_EMAIL, 0, checkPurposeSMIMEEncrypt, "S/MIME encryption", "smimeencrypt", null), + new Purpose(X509Utils.X509_PURPOSE_CRL_SIGN, X509Utils.X509_TRUST_COMPAT, 0, checkPurposeCRLSign, "CRL signing", "crlsign", null), + new Purpose(X509Utils.X509_PURPOSE_ANY, X509Utils.X509_TRUST_DEFAULT, 0, noCheck, "Any Purpose", "any", null), + new Purpose(X509Utils.X509_PURPOSE_OCSP_HELPER, X509Utils.X509_TRUST_COMPAT, 0, oscpHelper, "OCSP helper", "ocsphelper", null), + }; +}// X509_PURPOSE diff --git a/src/org/jruby/ext/openssl/x509store/Store.java b/src/org/jruby/ext/openssl/x509store/Store.java new file mode 100644 index 00000000000..6ebb3c6b760 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Store.java @@ -0,0 +1,377 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.io.FileNotFoundException; +import java.security.cert.X509Certificate; + +import java.util.ArrayList; +import java.util.List; + +import javax.net.ssl.X509TrustManager; + +/** + * c: X509_STORE + * + * @author Ola Bini + */ +public class Store implements X509TrustManager { + public int cache; + public List objs; + public List certificateMethods; + public VerifyParameter param; + + public static interface VerifyFunction extends Function1 { + public static final VerifyFunction EMPTY = new VerifyFunction(){ + public int call(Object arg0) { + return -1; + } + }; + } + public static interface VerifyCallbackFunction extends Function2 { + public static final VerifyCallbackFunction EMPTY = new VerifyCallbackFunction(){ + public int call(Object arg0, Object arg1) { + return -1; + } + }; + } + public static interface GetIssuerFunction extends Function3 { + public static final GetIssuerFunction EMPTY = new GetIssuerFunction(){ + public int call(Object arg0, Object arg1, Object arg2) { + return -1; + } + }; + } + public static interface CheckIssuedFunction extends Function3 { + public static final CheckIssuedFunction EMPTY = new CheckIssuedFunction(){ + public int call(Object arg0, Object arg1, Object arg2) { + return -1; + } + }; + } + public static interface CheckRevocationFunction extends Function1 { + public static final CheckRevocationFunction EMPTY = new CheckRevocationFunction(){ + public int call(Object arg0) { + return -1; + } + }; + } + public static interface GetCRLFunction extends Function3 { + public static final GetCRLFunction EMPTY = new GetCRLFunction(){ + public int call(Object arg0, Object arg1, Object arg2) { + return -1; + } + }; + } + public static interface CheckCRLFunction extends Function2 { + public static final CheckCRLFunction EMPTY = new CheckCRLFunction(){ + public int call(Object arg0, Object arg1) { + return -1; + } + }; + } + public static interface CertificateCRLFunction extends Function3 { + public static final CertificateCRLFunction EMPTY = new CertificateCRLFunction(){ + public int call(Object arg0, Object arg1, Object arg2) { + return -1; + } + }; + } + public static interface CleanupFunction extends Function1 { + public static final CleanupFunction EMPTY = new CleanupFunction(){ + public int call(Object arg0) { + return -1; + } + }; + } + + public VerifyFunction verify; + public VerifyCallbackFunction verifyCallback; + public GetIssuerFunction getIssuer; + public CheckIssuedFunction checkIssued; + public CheckRevocationFunction checkRevocation; + public GetCRLFunction getCRL; + public CheckCRLFunction checkCRL; + public CertificateCRLFunction certificateCRL; + public CleanupFunction cleanup; + + public List extraData; + public int references; + + /** + * c: X509_STORE_new + */ + public Store() { + objs = new ArrayList(); + cache = 1; + certificateMethods = new ArrayList(); + + verify = VerifyFunction.EMPTY; + verifyCallback = VerifyCallbackFunction.EMPTY; + + param = new VerifyParameter(); + + getIssuer = GetIssuerFunction.EMPTY; + checkIssued = CheckIssuedFunction.EMPTY; + checkRevocation = CheckRevocationFunction.EMPTY; + getCRL = GetCRLFunction.EMPTY; + checkCRL = CheckCRLFunction.EMPTY; + certificateCRL = CertificateCRLFunction.EMPTY; + cleanup = CleanupFunction.EMPTY; + + references = 1; + extraData = new ArrayList(); + this.extraData.add(null);this.extraData.add(null);this.extraData.add(null); + this.extraData.add(null);this.extraData.add(null);this.extraData.add(null); + this.extraData.add(null);this.extraData.add(null);this.extraData.add(null); + } + + /** + * c: X509_STORE_set_verify_func + */ + public void setVerifyFunction(VerifyFunction func) { + verify = func; + } + + /** + * c: X509_STORE_set_verify_cb_func + */ + public void setVerifyCallbackFunction(VerifyCallbackFunction func) { + verifyCallback = func; + } + + /** + * c: X509_STORE_free + */ + public void free() throws Exception { + for(Lookup lu : certificateMethods) { + lu.shutdown(); + lu.free(); + } + if(param != null) { + param.free(); + } + } + + /** + * c: X509_set_ex_data + */ + public int setExtraData(int idx,Object data) { + extraData.set(idx,data); + return 1; + } + + /** + * c: X509_get_ex_data + */ + public Object getExtraData(int idx) { + return extraData.get(idx); + } + + /** + * c: X509_STORE_set_depth + */ + public int setDepth(int depth) { + param.setDepth(depth); + return 1; + } + + /** + * c: X509_STORE_set_flags + */ + public int setFlags(long flags) { + return param.setFlags(flags); + } + + /** + * c: X509_STORE_set_purpose + */ + public int setPurpose(int purpose) { + return param.setPurpose(purpose); + } + + /** + * c: X509_STORE_set_trust + */ + public int setTrust(int trust) { + return param.setTrust(trust); + } + + /** + * c: X509_STORE_set1_param + */ + public int setParam(VerifyParameter pm) { + return param.set(param); + } + + /** + * c: X509_STORE_add_lookup + */ + public Lookup addLookup(LookupMethod m) throws Exception { + Lookup lu; + + for(Lookup l : certificateMethods) { + if(l.equals(m)) { + return l; + } + } + lu = new Lookup(m); + lu.store = this; + certificateMethods.add(lu); + return lu; + } + + /** + * c: X509_STORE_add_cert + */ + public int addCertificate(X509Certificate x) { + int ret = 1; + if(x == null) { + return 0; + } + + Certificate obj = new Certificate(); + obj.x509 = StoreContext.ensureAux(x); + + synchronized(X509Utils.CRYPTO_LOCK_X509_STORE) { + if(X509Object.retrieveMatch(objs,obj) != null) { + X509Error.addError(X509Utils.X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret=0; + } else { + objs.add(obj); + } + } + return ret; + } + + /** + * c: X509_STORE_add_crl + */ + public int addCRL(java.security.cert.CRL x) { + int ret = 1; + if(null == x) { + return 0; + } + CRL obj = new CRL(); + obj.crl = x; + + synchronized(X509Utils.CRYPTO_LOCK_X509_STORE) { + if(X509Object.retrieveMatch(objs,obj) != null) { + X509Error.addError(X509Utils.X509_R_CERT_ALREADY_IN_HASH_TABLE); + ret=0; + } else { + objs.add(obj); + } + } + return ret; + } + + /** + * c: X509_STORE_load_locations + */ + public int loadLocations(String file, String path) throws Exception { + Lookup lookup; + + if(file != null) { + lookup = addLookup(Lookup.fileLookup()); + if(lookup == null) { + return 0; + } + if(lookup.loadFile(new CertificateFile.Path(file,X509Utils.X509_FILETYPE_PEM)) != 1) { + return 0; + } + } + + if(path != null) { + lookup = addLookup(Lookup.hashDirLookup()); + if(lookup == null) { + return 0; + } + if(lookup.addDir(new CertificateHashDir.Dir(path,X509Utils.X509_FILETYPE_PEM)) != 1) { + return 0; + } + } + if((path == null) && (file == null)) { + return 0; + } + + return 1; + } + + /** + * c: X509_STORE_set_default_paths + * not used for now: invoking this method causes refering System.getenv("SSL_CERT_DIR") etc. + * We need to get the dir via evaluating "ENV['SSL_CERT_DIR']" instead of it. + */ + public int setDefaultPaths() throws Exception { + Lookup lookup; + + lookup = addLookup(Lookup.fileLookup()); + if(lookup == null) { + return 0; + } + try { + lookup.loadFile(new CertificateFile.Path(null,X509Utils.X509_FILETYPE_DEFAULT)); + } + catch(FileNotFoundException e) { + // set_default_paths ignores FileNotFound + } + + lookup = addLookup(Lookup.hashDirLookup()); + if(lookup == null) { + return 0; + } + try { + lookup.addDir(new CertificateHashDir.Dir(null,X509Utils.X509_FILETYPE_DEFAULT)); + } + catch(FileNotFoundException e) { + // set_default_paths ignores FileNotFound + } + + X509Error.clearErrors(); + + return 1; + } + + + public void checkClientTrusted(X509Certificate[] chain, String authType) { + } + + public void checkServerTrusted(X509Certificate[] chain, String authType) { + } + + public X509Certificate[] getAcceptedIssuers() { + List l = new ArrayList(); + for(X509Object o : objs) { + if(o instanceof Certificate) { + l.add(((Certificate)o).x509); + } + } + return l.toArray(new X509Certificate[l.size()]); + } +}// X509_STORE diff --git a/src/org/jruby/ext/openssl/x509store/StoreContext.java b/src/org/jruby/ext/openssl/x509store/StoreContext.java new file mode 100644 index 00000000000..caae9a2b140 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/StoreContext.java @@ -0,0 +1,1400 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.security.PublicKey; +import java.security.cert.X509CRL; +import java.security.cert.X509Certificate; +import java.security.cert.X509Extension; + +import java.util.Calendar; +import java.util.Collection; +import java.util.Date; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.HashSet; + +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERInteger; + +/** + * c: X509_STORE_CTX + * + * @author Ola Bini + */ +public class StoreContext { + public Store ctx; + public int currentMethod; + + public X509AuxCertificate certificate; + public List untrusted; + public List crls; + + public VerifyParameter param; + + public List otherContext; + + public static interface CheckPolicyFunction extends Function1 { + public static final CheckPolicyFunction EMPTY = new CheckPolicyFunction(){ + public int call(Object arg0) { + return -1; + } + }; + } + + public Store.VerifyFunction verify; + public Store.VerifyCallbackFunction verifyCallback; + public Store.GetIssuerFunction getIssuer; + public Store.CheckIssuedFunction checkIssued; + public Store.CheckRevocationFunction checkRevocation; + public Store.GetCRLFunction getCRL; + public Store.CheckCRLFunction checkCRL; + public Store.CertificateCRLFunction certificateCRL; + public CheckPolicyFunction checkPolicy; + public Store.CleanupFunction cleanup; + + public boolean isValid; + public int lastUntrusted; + + public List chain; //List + public PolicyTree tree; + + public int explicitPolicy; + + public int errorDepth; + public int error; + public X509AuxCertificate currentCertificate; + public X509AuxCertificate currentIssuer; + public java.security.cert.CRL currentCRL; + + public List extraData; + + /** + * c: X509_STORE_CTX_set_depth + */ + public void setDepth(int depth) { + param.setDepth(depth); + } + + /** + * c: X509_STORE_CTX_set_app_data + */ + public void setApplicationData(Object data) { + setExtraData(0,data); + } + + /** + * c: X509_STORE_CTX_get_app_data + */ + public Object getApplicationData() { + return getExtraData(0); + } + + /** + * c: X509_STORE_CTX_get1_issuer + */ + public int getFirstIssuer(X509AuxCertificate[] issuer, X509AuxCertificate x) throws Exception { + Name xn = new Name(x.getIssuerX500Principal()); + X509Object[] s_obj = new X509Object[1]; + int ok = ctx == null ? 0 : getBySubject(X509Utils.X509_LU_X509,xn,s_obj); + if(ok != X509Utils.X509_LU_X509) { + if(ok == X509Utils.X509_LU_RETRY) { + X509Error.addError(X509Utils.X509_R_SHOULD_RETRY); + return -1; + } else if (ok != X509Utils.X509_LU_FAIL) { + return -1; + } + return 0; + } + X509Object obj = s_obj[0]; + if(this.checkIssued.call(this,x,((Certificate)obj).x509) != 0) { + issuer[0] = ((Certificate)obj).x509; + return 1; + } + + int idx = X509Object.indexBySubject(ctx.objs,X509Utils.X509_LU_X509, xn); + if(idx == -1) { + return 0; + } + + /* Look through all matching certificates for a suitable issuer */ + for(int i = idx; i < ctx.objs.size(); i++) { + X509Object pobj = ctx.objs.get(i); + if(pobj.type() != X509Utils.X509_LU_X509) { + return 0; + } + if(!xn.isEqual((((Certificate)pobj).x509).getSubjectX500Principal())) { + return 0; + } + if(this.checkIssued.call(this,x,((Certificate)pobj).x509) != 0) { + issuer[0] = ((Certificate)pobj).x509; + return 1; + } + } + return 0; + } + + public static List ensureAux(Collection inp) { + if (inp == null) { + return null; + } + List out = new ArrayList(); + for(X509Certificate o : inp) { + out.add(ensureAux(o)); + } + return out; + } + + public static List ensureAux(X509Certificate[] inp) { + if (inp == null) { + return null; + } + List o = new ArrayList(); + for(X509Certificate c : inp) { + o.add(ensureAux(c)); + } + return o; + } + + public static X509AuxCertificate ensureAux(X509Certificate i) { + if (i == null) { + return null; + } + if(i instanceof X509AuxCertificate) { + return (X509AuxCertificate)i; + } else { + return new X509AuxCertificate(i); + } + } + + /** + * c: X509_STORE_CTX_init + */ + public int init(Store store, X509AuxCertificate x509, List chain) { + int ret = 1; + this.ctx=store; + this.currentMethod=0; + this.certificate=x509; + this.untrusted=chain; + this.crls = null; + this.lastUntrusted=0; + this.otherContext = null; + this.isValid=false; + this.chain = null; + this.error=0; + this.explicitPolicy=0; + this.errorDepth=0; + this.currentCertificate=null; + this.currentIssuer=null; + this.tree = null; + + this.param = new VerifyParameter(); + + if(store != null) { + ret = param.inherit(store.param); + } else { + param.flags |= X509Utils.X509_VP_FLAG_DEFAULT | X509Utils.X509_VP_FLAG_ONCE; + } + if(store != null) { + verifyCallback = store.verifyCallback; + cleanup = store.cleanup; + } else { + cleanup = Store.CleanupFunction.EMPTY; + } + + if(ret != 0) { + ret = param.inherit(VerifyParameter.lookup("default")); + } + + if(ret == 0) { + X509Error.addError(X509Utils.ERR_R_MALLOC_FAILURE); + return 0; + } + + if(store != null && store.checkIssued != null && store.checkIssued != Store.CheckIssuedFunction.EMPTY) { + this.checkIssued = store.checkIssued; + } else { + this.checkIssued = defaultCheckIssued; + } + + if(store != null && store.getIssuer != null && store.getIssuer != Store.GetIssuerFunction.EMPTY) { + this.getIssuer = store.getIssuer; + } else { + this.getIssuer = new Store.GetIssuerFunction() { + public int call(Object arg1, Object arg2, Object arg3) throws Exception { + return ((StoreContext)arg2).getFirstIssuer((X509AuxCertificate[])arg1,(X509AuxCertificate)arg3); + } + }; + } + + if(store != null && store.verifyCallback != null && store.verifyCallback != Store.VerifyCallbackFunction.EMPTY) { + this.verifyCallback = store.verifyCallback; + } else { + this.verifyCallback = NullCallback; + } + + if(store != null && store.verify != null && store.verify != Store.VerifyFunction.EMPTY) { + this.verify = store.verify; + } else { + this.verify = internalVerify; + } + + if(store != null && store.checkRevocation != null && store.checkRevocation != Store.CheckRevocationFunction.EMPTY) { + this.checkRevocation = store.checkRevocation; + } else { + this.checkRevocation = defaultCheckRevocation; + } + + if(store != null && store.getCRL != null && store.getCRL != Store.GetCRLFunction.EMPTY) { + this.getCRL = store.getCRL; + } else { + this.getCRL = defaultGetCRL; + } + + if(store != null && store.checkCRL != null && store.checkCRL != Store.CheckCRLFunction.EMPTY) { + this.checkCRL = store.checkCRL; + } else { + this.checkCRL = defaultCheckCRL; + } + + if(store != null && store.certificateCRL != null && store.certificateCRL != Store.CertificateCRLFunction.EMPTY) { + this.certificateCRL = store.certificateCRL; + } else { + this.certificateCRL = defaultCertificateCRL; + } + + this.checkPolicy = defaultCheckPolicy; + + this.extraData = new ArrayList(); + this.extraData.add(null);this.extraData.add(null);this.extraData.add(null); + this.extraData.add(null);this.extraData.add(null);this.extraData.add(null); + return 1; + } + + /** + * c: X509_STORE_CTX_trusted_stack + */ + public void trustedStack(List sk) { + otherContext = sk; + getIssuer = getIssuerStack; + } + + /** + * c: X509_STORE_CTX_cleanup + */ + public void cleanup() throws Exception { + if(cleanup != null && cleanup != Store.CleanupFunction.EMPTY) { + cleanup.call(this); + } + param = null; + tree = null; + chain = null; + extraData = null; + } + + /** + * c: find_issuer + */ + public X509AuxCertificate findIssuer(List sk, X509AuxCertificate x) throws Exception { + for(X509AuxCertificate issuer : sk) { + if(checkIssued.call(this,x,issuer) != 0) { + return issuer; + } + } + return null; + } + + /** + * c: X509_STORE_CTX_set_ex_data + */ + public int setExtraData(int idx,Object data) { + extraData.set(idx,data); + return 1; + } + + /** + * c: X509_STORE_CTX_get_ex_data + */ + public Object getExtraData(int idx) { + return extraData.get(idx); + } + + /** + * c: X509_STORE_CTX_get_error + */ + public int getError() { + return error; + } + + /** + * c: X509_STORE_CTX_set_error + */ + public void setError(int s) { + this.error = s; + } + + /** + * c: X509_STORE_CTX_get_error_depth + */ + public int getErrorDepth() { + return errorDepth; + } + + /** + * c: X509_STORE_CTX_get_current_cert + */ + public X509AuxCertificate getCurrentCertificate() { + return currentCertificate; + } + + /** + * c: X509_STORE_CTX_get_chain + */ + public List getChain() { + return chain; + } + + /** + * c: X509_STORE_CTX_get1_chain + */ + public List getFirstChain() { + if(null == chain) { + return null; + } + return new ArrayList(chain); + } + + /** + * c: X509_STORE_CTX_set_cert + */ + public void setCertificate(X509AuxCertificate x) { + this.certificate = x; + } + + public void setCertificate(X509Certificate x) { + this.certificate = ensureAux(x); + } + + /** + * c: X509_STORE_CTX_set_chain + */ + public void setChain(List sk) { + this.untrusted = ensureAux(sk); + } + + public void setChain(X509Certificate[] sk) { + this.untrusted = ensureAux(sk); + } + + /** + * c: X509_STORE_CTX_set0_crls + */ + public void setCRLs(List sk) { + this.crls = sk; + } + + /** + * c: X509_STORE_CTX_set_purpose + */ + public int setPurpose(int purpose) { + return purposeInherit(0,purpose,0); + } + + /** + * c: X509_STORE_CTX_set_trust + */ + public int setTrust(int trust) { + return purposeInherit(0,0,trust); + } + + private void resetSettingsToWithoutStore() { + ctx = null; + this.param = new VerifyParameter(); + this.param.flags |= X509Utils.X509_VP_FLAG_DEFAULT | X509Utils.X509_VP_FLAG_ONCE; + this.param.inherit(VerifyParameter.lookup("default")); + this.cleanup = Store.CleanupFunction.EMPTY; + this.checkIssued = defaultCheckIssued; + this.getIssuer = new Store.GetIssuerFunction() { + public int call(Object arg1, Object arg2, Object arg3) throws Exception { + return ((StoreContext)arg2).getFirstIssuer((X509AuxCertificate[])arg1,(X509AuxCertificate)arg3); + } + }; + this.verifyCallback = NullCallback; + this.verify = internalVerify; + this.checkRevocation = defaultCheckRevocation; + this.getCRL = defaultGetCRL; + this.checkCRL = defaultCheckCRL; + this.certificateCRL = defaultCertificateCRL; + } + + /** + * c: SSL_CTX_load_verify_locations + */ + public int loadVerifyLocations(String CAfile, String CApath) { + boolean reset = false; + try { + if(ctx == null) { + reset = true; + ctx = new Store(); + this.param.inherit(ctx.param); + param.inherit(VerifyParameter.lookup("default")); + this.cleanup = ctx.cleanup; + if(ctx.checkIssued != null && ctx.checkIssued != Store.CheckIssuedFunction.EMPTY) { + this.checkIssued = ctx.checkIssued; + } + if(ctx.getIssuer != null && ctx.getIssuer != Store.GetIssuerFunction.EMPTY) { + this.getIssuer = ctx.getIssuer; + } + + if(ctx.verifyCallback != null && ctx.verifyCallback != Store.VerifyCallbackFunction.EMPTY) { + this.verifyCallback = ctx.verifyCallback; + } + + if(ctx.verify != null && ctx.verify != Store.VerifyFunction.EMPTY) { + this.verify = ctx.verify; + } + + if(ctx.checkRevocation != null && ctx.checkRevocation != Store.CheckRevocationFunction.EMPTY) { + this.checkRevocation = ctx.checkRevocation; + } + + if(ctx.getCRL != null && ctx.getCRL != Store.GetCRLFunction.EMPTY) { + this.getCRL = ctx.getCRL; + } + + if(ctx.checkCRL != null && ctx.checkCRL != Store.CheckCRLFunction.EMPTY) { + this.checkCRL = ctx.checkCRL; + } + + if(ctx.certificateCRL != null && ctx.certificateCRL != Store.CertificateCRLFunction.EMPTY) { + this.certificateCRL = ctx.certificateCRL; + } + } + + int ret = ctx.loadLocations(CAfile, CApath); + if(ret == 0 && reset) resetSettingsToWithoutStore(); + + return ret; + } catch(Exception e) { + if(reset) { + resetSettingsToWithoutStore(); + } + return 0; + } + } + + /** + * c: X509_STORE_CTX_purpose_inherit + */ + public int purposeInherit(int defaultPurpose,int purpose, int trust) { + int idx; + if(purpose == 0) { + purpose = defaultPurpose; + } + if(purpose != 0) { + idx = Purpose.getByID(purpose); + if(idx == -1) { + X509Error.addError(X509Utils.X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + Purpose ptmp = Purpose.getFirst(idx); + if(ptmp.trust == X509Utils.X509_TRUST_DEFAULT) { + idx = Purpose.getByID(defaultPurpose); + if(idx == -1) { + X509Error.addError(X509Utils.X509_R_UNKNOWN_PURPOSE_ID); + return 0; + } + ptmp = Purpose.getFirst(idx); + } + if(trust == 0) { + trust = ptmp.trust; + } + } + if(trust != 0) { + idx = Trust.getByID(trust); + if(idx == -1) { + X509Error.addError(X509Utils.X509_R_UNKNOWN_TRUST_ID); + return 0; + } + } + + if(purpose != 0 && param.purpose == 0) { + param.purpose = purpose; + } + if(trust != 0 && param.trust == 0) { + param.trust = trust; + } + return 1; + } + + /** + * c: X509_STORE_CTX_set_flags + */ + public void setFlags(long flags) { + param.setFlags(flags); + } + + /** + * c: X509_STORE_CTX_set_time + */ + public void setTime(long flags,Date t) { + param.setTime(t); + } + + /** + * c: X509_STORE_CTX_set_verify_cb + */ + public void setVerifyCallback(Store.VerifyCallbackFunction verifyCallback) { + this.verifyCallback = verifyCallback; + } + + /** + * c: X509_STORE_CTX_get0_policy_tree + */ + PolicyTree getPolicyTree() { + return tree; + } + + /** + * c: X509_STORE_CTX_get_explicit_policy + */ + public int getExplicitPolicy() { + return explicitPolicy; + } + + /** + * c: X509_STORE_CTX_get0_param + */ + public VerifyParameter getParam() { + return param; + } + + /** + * c: X509_STORE_CTX_set0_param + */ + public void setParam(VerifyParameter param) { + this.param = param; + } + + /** + * c: X509_STORE_CTX_set_default + */ + public int setDefault(String name) { + VerifyParameter p = VerifyParameter.lookup(name); + if(p == null) { + return 0; + } + return param.inherit(p); + } + + /** + * c: X509_STORE_get_by_subject (it gets X509_STORE_CTX as the first parameter) + */ + public int getBySubject(int type,Name name,X509Object[] ret) throws Exception { + Store c = ctx; + + X509Object tmp = X509Object.retrieveBySubject(c.objs,type,name); + if(tmp == null) { + for(int i=currentMethod; i0) { + tmp = stmp[0]; + break; + } + } + currentMethod = 0; + if(tmp == null) { + return 0; + } + } + ret[0] = tmp; + return 1; + } + + /** + * c: X509_verify_cert + */ + public int verifyCertificate() throws Exception { + X509AuxCertificate x,xtmp=null,chain_ss = null; + //X509_NAME xn; + int bad_chain = 0; + int depth,i,ok=0; + int num; + Store.VerifyCallbackFunction cb; + List sktmp = null; + if(certificate == null) { + X509Error.addError(X509Utils.X509_R_NO_CERT_SET_FOR_US_TO_VERIFY); + return -1; + } + cb=verifyCallback; + + /* first we make sure the chain we are going to build is + * present and that the first entry is in place */ + + if(null == chain) { + chain = new ArrayList(); + chain.add(certificate); + lastUntrusted = 1; + } + + /* We use a temporary STACK so we can chop and hack at it */ + + if(untrusted != null) { + sktmp = new ArrayList(untrusted); + } + num = chain.size(); + x = chain.get(num-1); + depth = param.depth; + for(;;) { + if(depth < num) { + break; + } + + if(checkIssued.call(this,x,x) != 0) { + break; + } + + if(untrusted != null) { + xtmp = findIssuer(sktmp,x); + if(xtmp != null) { + chain.add(xtmp); + sktmp.remove(xtmp); + lastUntrusted++; + x = xtmp; + num++; + continue; + } + } + break; + } + + /* at this point, chain should contain a list of untrusted + * certificates. We now need to add at least one trusted one, + * if possible, otherwise we complain. */ + + /* Examine last certificate in chain and see if it + * is self signed. + */ + + i = chain.size(); + x = chain.get(i-1); + + if(checkIssued.call(this,x,x) != 0) { + /* we have a self signed certificate */ + if(chain.size() == 1) { + /* We have a single self signed certificate: see if + * we can find it in the store. We must have an exact + * match to avoid possible impersonation. + */ + X509AuxCertificate[] p_xtmp = new X509AuxCertificate[]{xtmp}; + ok = getIssuer.call(p_xtmp,this,x); + xtmp = p_xtmp[0]; + if(ok <= 0 || !x.equals(xtmp)) { + error = X509Utils.V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT; + currentCertificate = x; + errorDepth = i-1; + bad_chain = 1; + ok = cb.call(new Integer(0),this); + if(ok == 0) { + return ok; + } + } else { + /* We have a match: replace certificate with store version + * so we get any trust settings. + */ + x = xtmp; + chain.set(i-1,x); + lastUntrusted = 0; + } + } else { + /* extract and save self signed certificate for later use */ + chain_ss = chain.remove(chain.size()-1); + lastUntrusted--; + num--; + x = chain.get(num-1); + } + } + /* We now lookup certs from the certificate store */ + for(;;) { + /* If we have enough, we break */ + if(depth= num) { + error = X509Utils.V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY; + } else { + error = X509Utils.V_ERR_UNABLE_TO_GET_ISSUER_CERT; + } + currentCertificate = x; + } else { + chain.add(chain_ss); + num++; + lastUntrusted = num; + currentCertificate = chain_ss; + error = X509Utils.V_ERR_SELF_SIGNED_CERT_IN_CHAIN; + chain_ss = null; + } + errorDepth = num-1; + bad_chain = 1; + ok = cb.call(new Integer(0),this); + if(ok == 0) { + return ok; + } + } + + /* We have the chain complete: now we need to check its purpose */ + ok = checkChainExtensions(); + if(ok == 0) { + return ok; + } + + /* TODO: Check name constraints (from 1.0.0) */ + + /* The chain extensions are OK: check trust */ + if(param.trust > 0) { + ok = checkTrust(); + } + if(ok == 0) { + return ok; + } + + /* Check revocation status: we do this after copying parameters + * because they may be needed for CRL signature verification. + */ + ok = checkRevocation.call(this); + if(ok == 0) { + return ok; + } + + /* At this point, we have a chain and need to verify it */ + if(verify != null && verify != Store.VerifyFunction.EMPTY) { + ok = verify.call(this); + } else { + ok = internalVerify.call(this); + } + if(ok == 0) { + return ok; + } + + /* TODO: RFC 3779 path validation, now that CRL check has been done (from 1.0.0) */ + + /* If we get this far evaluate policies */ + if(bad_chain == 0 && (param.flags & X509Utils.V_FLAG_POLICY_CHECK) != 0) { + ok = checkPolicy.call(this); + } + return ok; + } + + + private final static Set CRITICAL_EXTENSIONS = new HashSet(); + static { + CRITICAL_EXTENSIONS.add("2.16.840.1.113730.1.1"); // netscape cert type, NID 71 + CRITICAL_EXTENSIONS.add("2.5.29.15"); // key usage, NID 83 + CRITICAL_EXTENSIONS.add("2.5.29.17"); // subject alt name, NID 85 + CRITICAL_EXTENSIONS.add("2.5.29.19"); // basic constraints, NID 87 + CRITICAL_EXTENSIONS.add("2.5.29.37"); // ext key usage, NID 126 + CRITICAL_EXTENSIONS.add("1.3.6.1.5.5.7.1.14"); // proxy cert info, NID 661 + } + + private static boolean supportsCriticalExtension(String oid) { + return CRITICAL_EXTENSIONS.contains(oid); + } + + private static boolean unhandledCritical(X509Extension xx) { + if(xx.getCriticalExtensionOIDs() == null || xx.getCriticalExtensionOIDs().size() == 0) { + return false; + } + for(String ss : xx.getCriticalExtensionOIDs()) { + if(!supportsCriticalExtension(ss)) { + return true; + } + } + return false; + } + + /** + * c: check_chain_extensions + */ + public int checkChainExtensions() throws Exception { + int ok=0, must_be_ca; + X509AuxCertificate x; + Store.VerifyCallbackFunction cb; + int proxy_path_length = 0; + int allow_proxy_certs = (param.flags & X509Utils.V_FLAG_ALLOW_PROXY_CERTS) != 0 ? 1 : 0; + cb = verifyCallback; + must_be_ca = -1; + + try { + if (System.getenv("OPENSSL_ALLOW_PROXY_CERTS") != null && !"false".equalsIgnoreCase(System.getenv("OPENSSL_ALLOW_PROXY_CERTS"))) { + allow_proxy_certs = 1; + } + } catch (Error e) { + // just ignore if we can't use System.getenv + } + + for(int i = 0; i 0) { + ret = Purpose.checkPurpose(x,param.purpose, must_be_ca > 0 ? 1 : 0); + if(ret == 0 || ((param.flags & X509Utils.V_FLAG_X509_STRICT) != 0 && ret != 1)) { + error = X509Utils.V_ERR_INVALID_PURPOSE; + errorDepth = i; + currentCertificate = x; + ok = cb.call(new Integer(0),this); + if(ok == 0) { + return ok; + } + } + } + + if(i > 1 && x.getBasicConstraints() != -1 && x.getBasicConstraints() != Integer.MAX_VALUE && (i > (x.getBasicConstraints() + proxy_path_length + 1))) { + error = X509Utils.V_ERR_PATH_LENGTH_EXCEEDED; + errorDepth = i; + currentCertificate = x; + ok = cb.call(new Integer(0),this); + if(ok == 0) { + return ok; + } + } + + if(x.getExtensionValue("1.3.6.1.5.5.7.1.14") != null) { + DERSequence pci = (DERSequence)new ASN1InputStream(x.getExtensionValue("1.3.6.1.5.5.7.1.14")).readObject(); + if(pci.size() > 0 && pci.getObjectAt(0) instanceof DERInteger) { + int pcpathlen = ((DERInteger)pci.getObjectAt(0)).getValue().intValue(); + if(i > pcpathlen) { + error = X509Utils.V_ERR_PROXY_PATH_LENGTH_EXCEEDED; + errorDepth = i; + currentCertificate = x; + ok = cb.call(new Integer(0),this); + if(ok == 0) { + return ok; + } + } + } + proxy_path_length++; + must_be_ca = 0; + } else { + must_be_ca = 1; + } + } + return 1; + } + + /** + * c: X509_check_trust + */ + public int checkTrust() throws Exception { + int i,ok; + X509AuxCertificate x; + Store.VerifyCallbackFunction cb; + cb = verifyCallback; + i = chain.size()-1; + x = chain.get(i); + ok = Trust.checkTrust(x,param.trust,0); + if(ok == X509Utils.X509_TRUST_TRUSTED) { + return 1; + } + errorDepth = 1; + currentCertificate = x; + if(ok == X509Utils.X509_TRUST_REJECTED) { + error = X509Utils.V_ERR_CERT_REJECTED; + } else { + error = X509Utils.V_ERR_CERT_UNTRUSTED; + } + return cb.call(new Integer(0),this); + } + + /** + * c: check_cert_time + */ + public int checkCertificateTime(X509AuxCertificate x) throws Exception { + Date ptime = null; + + if((param.flags & X509Utils.V_FLAG_USE_CHECK_TIME) != 0) { + ptime = this.param.checkTime; + } else { + ptime = Calendar.getInstance().getTime(); + } + if(!x.getNotBefore().before(ptime)) { + error = X509Utils.V_ERR_CERT_NOT_YET_VALID; + currentCertificate = x; + if(verifyCallback.call(new Integer(0),this) == 0) { + return 0; + } + } + if(!x.getNotAfter().after(ptime)) { + error = X509Utils.V_ERR_CERT_HAS_EXPIRED; + currentCertificate = x; + if(verifyCallback.call(new Integer(0),this) == 0) { + return 0; + } + } + return 1; + } + + /** + * c: check_cert + */ + public int checkCertificate() throws Exception { + X509CRL[] crl = new X509CRL[1]; + X509AuxCertificate x; + int ok,cnum; + cnum = errorDepth; + x = chain.get(cnum); + currentCertificate = x; + ok = getCRL.call(this,crl,x); + if(ok == 0) { + error = X509Utils.V_ERR_UNABLE_TO_GET_CRL; + ok = verifyCallback.call(new Integer(0), this); + currentCRL = null; + return ok; + } + currentCRL = crl[0]; + ok = checkCRL.call(this, crl[0]); + if(ok == 0) { + currentCRL = null; + return ok; + } + ok = certificateCRL.call(this,crl[0],x); + currentCRL = null; + return ok; + } + + /** + * c: check_crl_time + */ + public int checkCRLTime(X509CRL crl, int notify) throws Exception { + currentCRL = crl; + Date ptime = null; + + if((param.flags & X509Utils.V_FLAG_USE_CHECK_TIME) != 0) { + ptime = this.param.checkTime; + } else { + ptime = Calendar.getInstance().getTime(); + } + + if(!crl.getThisUpdate().before(ptime)) { + error=X509Utils.V_ERR_CRL_NOT_YET_VALID; + if(notify == 0 || verifyCallback.call(new Integer(0),this) == 0) { + return 0; + } + } + if(crl.getNextUpdate() != null && !crl.getNextUpdate().after(ptime)) { + error=X509Utils.V_ERR_CRL_HAS_EXPIRED; + if(notify == 0 || verifyCallback.call(new Integer(0),this) == 0) { + return 0; + } + } + + currentCRL = null; + return 1; + } + + /** + * c: get_crl_sk + */ + public int getCRLStack(X509CRL[] pcrl, Name nm, List crls) throws Exception { + X509CRL best_crl = null; + if(null != crls) { + for(X509CRL crl : crls) { + if(!nm.isEqual(crl.getIssuerX500Principal())) { + continue; + } + if(checkCRLTime(crl,0) != 0) { + pcrl[0] = crl; + return 1; + } + best_crl = crl; + } + } + if(best_crl != null) { + pcrl[0] = best_crl; + } + return 0; + } + + /** + * c: get_issuer_sk + */ + public final static Store.GetIssuerFunction getIssuerStack = new Store.GetIssuerFunction() { + public int call(Object a1, Object a2, Object a3) throws Exception { + X509AuxCertificate[] issuer = (X509AuxCertificate[])a1; + StoreContext ctx = (StoreContext)a2; + X509AuxCertificate x = (X509AuxCertificate)a3; + issuer[0] = ctx.findIssuer(ctx.otherContext,x); + if(issuer[0] != null) { + return 1; + } else { + return 0; + } + } + }; + + /** + * c: check_issued + */ + public final static Store.CheckIssuedFunction defaultCheckIssued = new Store.CheckIssuedFunction() { + public int call(Object a1, Object a2, Object a3) throws Exception { + StoreContext ctx = (StoreContext)a1; + X509AuxCertificate x = (X509AuxCertificate)a2; + X509AuxCertificate issuer = (X509AuxCertificate)a3; + int ret = X509Utils.checkIfIssuedBy(issuer,x); + if(ret == X509Utils.V_OK) { + return 1; + } + if((ctx.param.flags & X509Utils.V_FLAG_CB_ISSUER_CHECK) == 0) { + return 0; + } + ctx.error = ret; + ctx.currentCertificate = x; + ctx.currentIssuer = issuer; + return ctx.verifyCallback.call(new Integer(0),ctx); + } + }; + + /** + * c: null_callback + */ + public final static Store.VerifyCallbackFunction NullCallback = new Store.VerifyCallbackFunction() { + public int call(Object a1, Object a2) { + return ((Integer)a1).intValue(); + } + }; + + /** + * c: internal_verify + */ + public final static Store.VerifyFunction internalVerify = new Store.VerifyFunction() { + public int call(Object a1) throws Exception { + StoreContext ctx = (StoreContext)a1; + Store.VerifyCallbackFunction cb = ctx.verifyCallback; + int n = ctx.chain.size(); + ctx.errorDepth = n-1; + n--; + X509AuxCertificate xi = ctx.chain.get(n); + X509AuxCertificate xs = null; + int ok = 0; + if(ctx.checkIssued.call(ctx,xi,xi) != 0) { + xs = xi; + } else { + if(n<=0) { + ctx.error = X509Utils.V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + ctx.currentCertificate = xi; + ok = cb.call(new Integer(0),ctx); + return ok; + } else { + n--; + ctx.errorDepth = n; + xs = ctx.chain.get(n); + } + } + while(n>=0) { + ctx.errorDepth = n; + if(!xs.isValid()) { + try { + xs.verify(xi.getPublicKey()); + } catch(Exception e) { + /* + System.err.println("n: " + n); + System.err.println("verifying: " + xs); + System.err.println("verifying with issuer?: " + xi); + System.err.println("verifying with issuer.key?: " + xi.getPublicKey()); + System.err.println("exception: " + e); + */ + ctx.error = X509Utils.V_ERR_CERT_SIGNATURE_FAILURE; + ctx.currentCertificate = xs; + ok = cb.call(new Integer(0),ctx); + if(ok == 0) { + return ok; + } + } + } + xs.setValid(true); + ok = ctx.checkCertificateTime(xs); + if(ok == 0) { + return ok; + } + ctx.currentIssuer = xi; + ctx.currentCertificate = xs; + ok = cb.call(new Integer(1),ctx); + if(ok == 0) { + return ok; + } + n--; + if(n>=0) { + xi = xs; + xs = ctx.chain.get(n); + } + } + ok = 1; + return ok; + } + }; + + /** + * c: check_revocation + */ + public final static Store.CheckRevocationFunction defaultCheckRevocation = new Store.CheckRevocationFunction() { + public int call(Object a1) throws Exception { + StoreContext ctx = (StoreContext)a1; + int last,ok=0; + if((ctx.param.flags & X509Utils.V_FLAG_CRL_CHECK) == 0) { + return 1; + } + if((ctx.param.flags & X509Utils.V_FLAG_CRL_CHECK_ALL) != 0) { + last = ctx.chain.size() -1; + } else { + last = 0; + } + for(int i=0;i<=last;i++) { + ctx.errorDepth = i; + ok = ctx.checkCertificate(); + if(ok == 0) { + return 0; + } + } + return 1; + } + }; + + /** + * c: get_crl + */ + public final static Store.GetCRLFunction defaultGetCRL = new Store.GetCRLFunction() { + public int call(Object a1, Object a2, Object a3) throws Exception { + StoreContext ctx = (StoreContext)a1; + X509CRL[] pcrl = (X509CRL[])a2; + X509AuxCertificate x = (X509AuxCertificate)a3; + Name nm = new Name(x.getIssuerX500Principal()); + X509CRL[] crl = new X509CRL[1]; + int ok = ctx.getCRLStack(crl,nm,ctx.crls); + if(ok != 0) { + pcrl[0] = crl[0]; + return 1; + } + X509Object[] xobj = new X509Object[1]; + ok = ctx.getBySubject(X509Utils.X509_LU_CRL,nm,xobj); + if(ok == 0) { + if(crl[0] != null) { + pcrl[0] = crl[0]; + return 1; + } + return 0; + } + pcrl[0] = (X509CRL)(((CRL)xobj[0]).crl); + return 1; + } + }; + + /** + * c: check_crl + */ + public final static Store.CheckCRLFunction defaultCheckCRL = new Store.CheckCRLFunction() { + public int call(Object a1, Object a2) throws Exception { + StoreContext ctx = (StoreContext)a1; + final X509CRL crl = (X509CRL)a2; + X509AuxCertificate issuer = null; + int ok = 0,chnum,cnum; + cnum = ctx.errorDepth; + chnum = ctx.chain.size()-1; + if(cnum < chnum) { + issuer = ctx.chain.get(cnum+1); + } else { + issuer = ctx.chain.get(chnum); + if(ctx.checkIssued.call(ctx,issuer,issuer) == 0) { + ctx.error = X509Utils.V_ERR_UNABLE_TO_GET_CRL_ISSUER; + ok = ctx.verifyCallback.call(new Integer(0),ctx); + if(ok == 0) { + return ok; + } + } + } + + if (issuer != null) { + if (issuer.getKeyUsage() != null && !issuer.getKeyUsage()[6]) { + ctx.error = X509Utils.V_ERR_KEYUSAGE_NO_CRL_SIGN; + ok = ctx.verifyCallback.call(new Integer(0), ctx); + if (ok == 0) { + return ok; + } + } + final PublicKey ikey = issuer.getPublicKey(); + if (ikey == null) { + ctx.error = X509Utils.V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY; + ok = ctx.verifyCallback.call(new Integer(0), ctx); + if (ok == 0) { + return ok; + } + } else { + try { + crl.verify(ikey); + } catch (Exception ignored) { + ctx.error = X509Utils.V_ERR_CRL_SIGNATURE_FAILURE; + ok = ctx.verifyCallback.call(new Integer(0), ctx); + if (ok == 0) { + return ok; + } + } + } + } + + ok = ctx.checkCRLTime(crl,1); + if(ok == 0) { + return ok; + } + return 1; + } + }; + + /** + * c: cert_crl + */ + public final static Store.CertificateCRLFunction defaultCertificateCRL = new Store.CertificateCRLFunction() { + public int call(Object a1, Object a2, Object a3) throws Exception { + StoreContext ctx = (StoreContext)a1; + X509CRL crl = (X509CRL)a2; + X509AuxCertificate x = (X509AuxCertificate)a3; + int ok; + if(crl.getRevokedCertificate(x.getSerialNumber()) != null) { + ctx.error = X509Utils.V_ERR_CERT_REVOKED; + ok = ctx.verifyCallback.call(new Integer(0), ctx); + if(ok == 0) { + return 0; + } + } + if((ctx.param.flags & X509Utils.V_FLAG_IGNORE_CRITICAL) != 0) { + return 1; + } + + if(crl.getCriticalExtensionOIDs() != null && crl.getCriticalExtensionOIDs().size()>0) { + ctx.error = X509Utils.V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION; + ok = ctx.verifyCallback.call(new Integer(0), ctx); + if(ok == 0) { + return 0; + } + } + return 1; + } + }; + + /** + * c: check_policy + */ + public final static CheckPolicyFunction defaultCheckPolicy = new CheckPolicyFunction() { + public int call(Object a1) throws Exception { + return 1; + } + }; +}// X509_STORE_CTX diff --git a/src/org/jruby/ext/openssl/x509store/Trust.java b/src/org/jruby/ext/openssl/x509store/Trust.java new file mode 100644 index 00000000000..a414379b569 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/Trust.java @@ -0,0 +1,279 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.util.ArrayList; +import java.util.List; + +/** + * c: X509_TRUST + * + * @author Ola Bini + */ +public class Trust { + public static interface Checker extends Function3 {} + public int trust; + public int flags; + public Checker checkTrust; + public String name; + public String arg1; + public Object arg2; + + public Trust() {} + + public Trust(int t, int f, Checker ct, String n, String a1, Object a2) { + this.trust = t; + this.flags = f; this.checkTrust = ct; + this.name = n; this.arg1 = a1; + this.arg2 = a2; + } + + /** + * c: X509_TRUST_set_default + */ + public static Checker setDefault(Checker trust) { + Checker old_trust = defaultTrust; + defaultTrust = trust; + return old_trust; + } + + private final static List trtable = new ArrayList(); + + /** + * c: X509_check_trust + */ + public static int checkTrust(X509AuxCertificate x, int id, int flags) throws Exception { + if(id == -1) { + return 1; + } + int idx = getByID(id); + if(idx == -1) { + return defaultTrust.call(new Integer(id),x,new Integer(flags)); + } + Trust pt = getFirst(idx); + return pt.checkTrust.call(pt,x,new Integer(flags)); + } + + /** + * c: X509_TRUST_get_count + */ + public static int getCount() { + return trtable.size() + trstandard.length; + } + + /** + * c: X509_TRUST_get0 + */ + public static Trust getFirst(int idx) { + if(idx < 0) { + return null; + } + if(idx < trstandard.length) { + return trstandard[idx]; + } + return trtable.get(idx - trstandard.length); + } + + /** + * c: X509_TRUST_get_by_id + */ + public static int getByID(int id) { + if(id >= X509Utils.X509_TRUST_MIN && id <= X509Utils.X509_TRUST_MAX) { + return id - X509Utils.X509_TRUST_MIN; + } + int i = 0; + for(Trust t : trtable) { + if(t.trust == id) { + return i + trstandard.length; + } + } + return -1; + } + + /** + * c: X509_TRUST_set + */ + public static int set(int[] t, int trust) { + if(getByID(trust) == -1) { + X509Error.addError(X509Utils.X509_R_INVALID_TRUST); + return 0; + } + t[0] = trust; + return 1; + } + + /** + * c: X509_TRUST_add + */ + public static int add(int id, int flags, Checker ck, String name, String arg1, Object arg2) { + int idx; + Trust trtmp; + flags &= ~X509Utils.X509_TRUST_DYNAMIC; + flags |= X509Utils.X509_TRUST_DYNAMIC_NAME; + idx = getByID(id); + if(idx == -1) { + trtmp = new Trust(); + trtmp.flags = X509Utils.X509_TRUST_DYNAMIC; + } else { + trtmp = getFirst(idx); + } + trtmp.name = name; + trtmp.flags &= X509Utils.X509_TRUST_DYNAMIC; + trtmp.flags |= flags; + trtmp.trust = id; + trtmp.checkTrust = ck; + trtmp.arg1 = arg1; + trtmp.arg2 = arg2; + if(idx == -1) { + trtable.add(trtmp); + } + return 1; + } + + /** + * c: X509_TRUST_cleanup + */ + public static void cleanup() { + trtable.clear(); + } + + /** + * c: X509_TRUST_get_flags + */ + public int getFlags() { + return flags; + } + + /** + * c: X509_TRUST_get0_name + */ + public String getName() { + return name; + } + + /** + * c: X509_TRUST_get_trust + */ + public int getTrust() { + return trust; + } + + /** + * c: trust_compat + */ + public final static Checker trustCompatibe = new Checker() { + public int call(Object _trust, Object _x, Object _flags) throws Exception { + //X509_TRUST trust = (X509_TRUST)_trust; + X509AuxCertificate x = (X509AuxCertificate)_x; + //int flags = ((Integer)_flags).intValue(); + + Purpose.checkPurpose(x,-1,0); + if(x.getIssuerX500Principal().equals(x.getSubjectX500Principal())) { // self signed + return X509Utils.X509_TRUST_TRUSTED; + } else { + return X509Utils.X509_TRUST_UNTRUSTED; + } + } + }; + + /** + * c: trust_1oidany + */ + public final static Checker trust1OIDAny = new Checker() { + public int call(Object _trust, Object _x, Object _flags) throws Exception { + Trust trust = (Trust)_trust; + X509AuxCertificate x = (X509AuxCertificate)_x; + int flags = ((Integer)_flags).intValue(); + + X509Aux ax = x.getAux(); + if(ax != null && (ax.trust.size() > 0 || ax.reject.size() > 0)) { + return objTrust.call(trust.arg1,x,new Integer(flags)); + } + return trustCompatibe.call(trust,x,new Integer(flags)); + } + }; + + /** + * c: trust_1oid + */ + public final static Checker trust1OID = new Checker() { + public int call(Object _trust, Object _x, Object _flags) throws Exception { + Trust trust = (Trust)_trust; + X509AuxCertificate x = (X509AuxCertificate)_x; + int flags = ((Integer)_flags).intValue(); + + if(x.getAux() != null) { + return objTrust.call(trust.arg1,x,new Integer(flags)); + } + return X509Utils.X509_TRUST_UNTRUSTED; + } + }; + + /** + * c: obj_trust + */ + public final static Checker objTrust = new Checker() { + public int call(Object _id, Object _x, Object _flags) { + String id = (String)_id; + X509AuxCertificate x = (X509AuxCertificate)_x; + //int flags = ((Integer)_flags).intValue(); + + X509Aux ax = x.getAux(); + if(null == ax) { + return X509Utils.X509_TRUST_UNTRUSTED; + } + for(String rej : ax.reject) { + if(rej.equals(id)) { + return X509Utils.X509_TRUST_REJECTED; + } + } + for(String t : ax.trust) { + if(t.equals(id)) { + return X509Utils.X509_TRUST_TRUSTED; + } + } + return X509Utils.X509_TRUST_UNTRUSTED; + } + }; + + /** + * c: default_trust + */ + public static Checker defaultTrust = objTrust; + + public final static Trust[] trstandard = new Trust[] { + new Trust(X509Utils.X509_TRUST_COMPAT, 0, trustCompatibe, "compatible", null, null), + new Trust(X509Utils.X509_TRUST_SSL_CLIENT, 0, trust1OIDAny, "SSL Client", "1.3.6.1.5.5.7.3.2", null), + new Trust(X509Utils.X509_TRUST_SSL_SERVER, 0, trust1OIDAny, "SSL Server", "1.3.6.1.5.5.7.3.1", null), + new Trust(X509Utils.X509_TRUST_EMAIL, 0, trust1OIDAny, "S/MIME email", "1.3.6.1.5.5.7.3.4", null), + new Trust(X509Utils.X509_TRUST_OBJECT_SIGN, 0, trust1OIDAny, "Object Signer", "1.3.6.1.5.5.7.3.3", null), + new Trust(X509Utils.X509_TRUST_OCSP_SIGN, 0, trust1OID, "OCSP responder", "1.3.6.1.5.5.7.3.9", null), + new Trust(X509Utils.X509_TRUST_OCSP_REQUEST, 0, trust1OID, "OCSP request", "1.3.6.1.5.5.7.48.1", null) + + }; +}// X509_TRUST diff --git a/src/org/jruby/ext/openssl/x509store/VerifyParameter.java b/src/org/jruby/ext/openssl/x509store/VerifyParameter.java new file mode 100644 index 00000000000..83a57a3f4f5 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/VerifyParameter.java @@ -0,0 +1,324 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.util.Date; + +import java.util.ArrayList; +import java.util.List; +import java.util.Iterator; + +import org.bouncycastle.asn1.DERObject; + +/** + * c: X509_VERIFY_PARAM + * + * @author Ola Bini + */ +public class VerifyParameter { + public String name; + public Date checkTime; + public long inheritFlags; + public long flags; + public int purpose; + public int trust; + public int depth; + public List policies; + + /** + * c: X509_VERIFY_PARAM_new + */ + public VerifyParameter() { + zero(); + } + + public VerifyParameter(String n, long t, long i_f, long f, int p, int trs, int d, List pol) { + this.name = n; + this.checkTime = new Date(t); + this.inheritFlags = i_f; + this.flags = f; + this.purpose = p; + this.trust = trs; + this.depth = d; + this.policies = pol; + } + + private void zero() { + name = null; + purpose = 0; + trust = 0; + inheritFlags = X509Utils.X509_VP_FLAG_DEFAULT; + flags = 0; + depth = -1; + policies = null; + } + + /** + * c: X509_VERIFY_PARAM_free + */ + public void free() { + zero(); + } + + /** + * c: X509_VERIFY_PARAM_inherit + */ + public int inherit(VerifyParameter src) { + long inh_flags; + boolean to_d, to_o; + + if(src == null) { + return 1; + } + + + inh_flags = src.inheritFlags | this.inheritFlags; + if((inh_flags & X509Utils.X509_VP_FLAG_ONCE) != 0) { + this.inheritFlags = 0; + } + if((inh_flags & X509Utils.X509_VP_FLAG_LOCKED) != 0) { + return 1; + } + to_d = ((inh_flags & X509Utils.X509_VP_FLAG_DEFAULT) != 0); + to_o = ((inh_flags & X509Utils.X509_VP_FLAG_OVERWRITE) != 0); + + if(to_o || ((src.purpose != 0 && (to_d || this.purpose == 0)))) { + this.purpose = src.purpose; + } + if(to_o || ((src.trust != 0 && (to_d || this.trust == 0)))) { + this.trust = src.trust; + } + if(to_o || ((src.depth != -1 && (to_d || this.depth == -1)))) { + this.depth = src.depth; + } + + if(to_o || !((this.flags & X509Utils.V_FLAG_USE_CHECK_TIME) != 0)) { + this.checkTime = src.checkTime; + this.flags &= ~X509Utils.V_FLAG_USE_CHECK_TIME; + } + + if((inh_flags & X509Utils.X509_VP_FLAG_RESET_FLAGS) != 0) { + this.flags = 0; + } + + this.flags |= src.flags; + + if(to_o || ((src.policies != null && (to_d || this.policies == null)))) { + setPolicies(src.policies); + } + return 1; + } + + /** + * c: X509_VERIFY_PARAM_set1 + */ + public int set(VerifyParameter from) { + inheritFlags |= X509Utils.X509_VP_FLAG_DEFAULT; + return inherit(from); + } + + /** + * c: X509_VERIFY_PARAM_set1_name + */ + public int setName(String name) { + this.name = name; + return 1; + } + + /** + * c: X509_VERIFY_PARAM_set_flags + */ + public int setFlags(long flags) { + this.flags |= flags; + if((flags & X509Utils.V_FLAG_POLICY_MASK) == X509Utils.V_FLAG_POLICY_MASK) { + this.flags |= X509Utils.V_FLAG_POLICY_CHECK; + } + return 1; + } + + /** + * c: X509_VERIFY_PARAM_clear_flags + */ + public int clearFlags(long flags) { + this.flags &= ~flags; + return 1; + } + + /** + * c: X509_VERIFY_PARAM_get_flags + */ + public long getFlags() { + return flags; + } + + /** + * c: X509_VERIFY_PARAM_set_purpose + */ + public int setPurpose(int purpose) { + int[] arg = new int[]{this.purpose}; + int v = Purpose.set(arg,purpose); + this.purpose = arg[0]; + return v; + } + + /** + * c: X509_VERIFY_PARAM_set_trust + */ + public int setTrust(int trust) { + int[] arg = new int[]{this.trust}; + int v = Trust.set(arg,trust); + this.trust = arg[0]; + return v; + } + + /** + * c: X509_VERIFY_PARAM_set_depth + */ + public void setDepth(int depth) { + this.depth = depth; + } + + /** + * c: X509_VERIFY_PARAM_set_time + */ + public void setTime(Date t) { + this.checkTime = t; + this.flags |= X509Utils.V_FLAG_USE_CHECK_TIME; + } + + /** + * c: X509_VERIFY_PARAM_add0_policy + */ + public int addPolicy(DERObject policy) { + if(policies == null) { + policies = new ArrayList(); + } + policies.add(policy); + return 1; + } + + /** + * c: X509_VERIFY_PARAM_set1_policies + */ + public int setPolicies(List policies) { + if(policies == null) { + this.policies = null; + return 1; + } + this.policies = new ArrayList(); + this.policies.addAll(policies); + this.flags |= X509Utils.V_FLAG_POLICY_CHECK; + return 1; + } + + /** + * c: X509_VERIFY_PARAM_get_depth + */ + public int getDepth() { + return depth; + } + + /** + * c: X509_VERIFY_PARAM_add0_table + */ + public int addTable() { + for(Iterator iter = parameterTable.iterator();iter.hasNext();) { + VerifyParameter v = iter.next(); + if(this.name.equals(v.name)) { + iter.remove(); + } + } + parameterTable.add(this); + return 1; + } + + public static VerifyParameter lookup(String name) { + for(VerifyParameter v : parameterTable) { + if(name.equals(v.name)) { + return v; + } + } + for(VerifyParameter v : defaultTable) { + if(name.equals(v.name)) { + return v; + } + } + return null; + } + + /** + * c: X509_VERIFY_PARAM_table_cleanup + */ + public static void tableCleanup() { + parameterTable.clear(); + } + + private final static VerifyParameter[] defaultTable = new VerifyParameter[] { + new VerifyParameter( + "default", /* X509 default parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + 0, /* purpose */ + 0, /* trust */ + 100, /* depth */ + null /* policies */ + ), + new VerifyParameter( + "pkcs7", /* SSL/TLS client parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509Utils.X509_PURPOSE_SMIME_SIGN, /* purpose */ + X509Utils.X509_TRUST_EMAIL, /* trust */ + -1, /* depth */ + null /* policies */ + ), + new VerifyParameter( + "ssl_client", /* SSL/TLS client parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509Utils.X509_PURPOSE_SSL_CLIENT, /* purpose */ + X509Utils.X509_TRUST_SSL_CLIENT, /* trust */ + -1, /* depth */ + null /* policies */ + ), + new VerifyParameter( + "ssl_server", /* SSL/TLS server parameters */ + 0, /* Check time */ + 0, /* internal flags */ + 0, /* flags */ + X509Utils.X509_PURPOSE_SSL_SERVER, /* purpose */ + X509Utils.X509_TRUST_SSL_SERVER, /* trust */ + -1, /* depth */ + null /* policies */ + )}; + + private final static List parameterTable = new ArrayList(); +}// X509_VERIFY_PARAM diff --git a/src/org/jruby/ext/openssl/x509store/X509Aux.java b/src/org/jruby/ext/openssl/x509store/X509Aux.java new file mode 100644 index 00000000000..f7d56ed955e --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/X509Aux.java @@ -0,0 +1,43 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.util.List; +import java.util.ArrayList; +import org.bouncycastle.asn1.DERObject; + +/** + * @author Ola Bini + */ +public class X509Aux { + public List trust = new ArrayList(); // String of OID's /* trusted uses */ + public List reject = new ArrayList(); // String of OID's /* rejected uses */ + public String alias; /* "friendly name" */ + public byte[] keyid; /* key id of private key */ + public List other = new ArrayList(); /* String of OID's of sigAlgs, other unspecified info */ +}// X509_AUX diff --git a/src/org/jruby/ext/openssl/x509store/X509AuxCertificate.java b/src/org/jruby/ext/openssl/x509store/X509AuxCertificate.java new file mode 100644 index 00000000000..555d24719c6 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/X509AuxCertificate.java @@ -0,0 +1,170 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.io.IOException; +import java.math.BigInteger; + +import java.security.Principal; +import java.security.PublicKey; +import java.security.NoSuchAlgorithmException; +import java.security.InvalidKeyException; +import java.security.NoSuchProviderException; +import java.security.SignatureException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.CertificateParsingException; +import java.security.cert.X509Certificate; + +import java.util.Date; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.DERBitString; +import org.bouncycastle.asn1.DEROctetString; + +/** + * Since regular X509Certificate doesn't represent the Aux part of a + * certification, this class uses composition and extension to contain + * both pieces of information. + * + * @author Ola Bini + */ +public class X509AuxCertificate extends X509Certificate { + private static final long serialVersionUID = -909543379295427515L; + private final X509Certificate wrap; + private final X509Aux aux; + + private boolean valid = false; + private int ex_flags = 0; + + public X509AuxCertificate(X509Certificate wrap) { + this(wrap,null); + } + + public X509AuxCertificate(X509Certificate wrap, X509Aux aux) { + super(); + this.wrap = wrap; + this.aux = aux; + } + + public X509Aux getAux() { + return this.aux; + } + + public boolean isValid() { + return valid; + } + + public void setValid(boolean v) { + this.valid = v; + } + + public int getExFlags() { + return ex_flags; + } + + public void setExFlags(int ex_flags) { + this.ex_flags = ex_flags; + } + + public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { wrap.checkValidity(); } + public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { wrap.checkValidity(date); } + public int getBasicConstraints() { return wrap.getBasicConstraints(); } + public List getExtendedKeyUsage() throws CertificateParsingException { return wrap.getExtendedKeyUsage(); } + public Collection> getIssuerAlternativeNames() throws CertificateParsingException { return wrap.getIssuerAlternativeNames(); } + public Principal getIssuerDN() { return wrap.getIssuerDN(); } + public boolean[] getIssuerUniqueID() { return wrap.getIssuerUniqueID(); } + public X500Principal getIssuerX500Principal() { return wrap.getIssuerX500Principal(); } + public boolean[] getKeyUsage() { return wrap.getKeyUsage(); } + public Date getNotAfter() { return wrap.getNotAfter(); } + public Date getNotBefore() { return wrap.getNotBefore(); } + public BigInteger getSerialNumber() { return wrap.getSerialNumber(); } + public String getSigAlgName() { return wrap.getSigAlgName(); } + public String getSigAlgOID() { return wrap.getSigAlgOID(); } + public byte[] getSigAlgParams() { return wrap.getSigAlgParams(); } + public byte[] getSignature() { return wrap.getSignature(); } + public Collection> getSubjectAlternativeNames() throws CertificateParsingException { return wrap.getSubjectAlternativeNames(); } + public Principal getSubjectDN() { return wrap.getSubjectDN(); } + public boolean[] getSubjectUniqueID() { return wrap.getSubjectUniqueID(); } + public X500Principal getSubjectX500Principal() { return wrap.getSubjectX500Principal(); } + public byte[] getTBSCertificate() throws CertificateEncodingException { return wrap.getTBSCertificate(); } + public int getVersion() { return wrap.getVersion(); } + + public boolean equals(Object other) { + boolean ret = this == other; + if(!ret && (other instanceof X509AuxCertificate)) { + X509AuxCertificate o = (X509AuxCertificate)other; + ret = this.wrap.equals(o.wrap) && ((this.aux == null) ? o.aux == null : this.aux.equals(o.aux)); + } + return ret; + } + public byte[] getEncoded() throws CertificateEncodingException { return wrap.getEncoded(); } + public PublicKey getPublicKey(){ return wrap.getPublicKey(); } + public int hashCode() { + int ret = wrap.hashCode(); + ret += 3 * (aux == null ? 1 : aux.hashCode()); + return ret; + } + public String toString(){ return wrap.toString(); } + public void verify(PublicKey key) throws CertificateException,NoSuchAlgorithmException,InvalidKeyException,NoSuchProviderException,SignatureException { wrap.verify(key); } + public void verify(PublicKey key, String sigProvider) throws CertificateException,NoSuchAlgorithmException,InvalidKeyException,NoSuchProviderException,SignatureException { wrap.verify(key,sigProvider); } + public Set getCriticalExtensionOIDs(){ return wrap.getCriticalExtensionOIDs(); } + public byte[] getExtensionValue(String oid){ return wrap.getExtensionValue(oid); } + public Set getNonCriticalExtensionOIDs(){ return wrap.getNonCriticalExtensionOIDs(); } + public boolean hasUnsupportedCriticalExtension(){ return wrap.hasUnsupportedCriticalExtension(); } + + private static final String NS_CERT_TYPE_OID = "2.16.840.1.113730.1.1"; + public Integer getNsCertType() throws CertificateException { + byte[] bytes = getExtensionValue(NS_CERT_TYPE_OID); + if (bytes == null) { + return null; + } + try { + Object o = new ASN1InputStream(bytes).readObject(); + if (o instanceof DERBitString) { + return ((DERBitString) o).intValue(); + } else if (o instanceof DEROctetString) { + // just reads initial object for nsCertType definition and ignores trailing objects. + ASN1InputStream in = new ASN1InputStream(((DEROctetString) o).getOctets()); + o = in.readObject(); + return ((DERBitString) o).intValue(); + } else { + throw new CertificateException("unknown type from ASN1InputStream.readObject: " + o); + } + } catch (IOException ioe) { + throw new CertificateEncodingException(ioe.getMessage(), ioe); + } + } + +}// X509AuxCertificate diff --git a/src/org/jruby/ext/openssl/x509store/X509Error.java b/src/org/jruby/ext/openssl/x509store/X509Error.java new file mode 100644 index 00000000000..6c5df638711 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/X509Error.java @@ -0,0 +1,70 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.util.ArrayList; +import java.util.List; + +/** + * Used to handle OpenSSL errors in a sane way. These are not safe for + * multi runtimes at the moments. + * + * @author Ola Bini + */ +public class X509Error { + private static ThreadLocal> errors = new ThreadLocal>(); + + public static class ErrorException extends Exception { + private static final long serialVersionUID = -3214495184277468063L; + + private int reason; + public ErrorException(int reason) { + super(); + this.reason = reason; + } + public int getReason() { + return reason; + } + } + + public static synchronized void addError(int reason) { + List errs = errors.get(); + if(errs == null) { + errs = new ArrayList(); + errors.set(errs); + } + errs.add(new ErrorException(reason)); + } + + public static synchronized void clearErrors() { + List errs = errors.get(); + if(errs != null) { + errs.clear(); + } + } +}// Err diff --git a/src/org/jruby/ext/openssl/x509store/X509Object.java b/src/org/jruby/ext/openssl/x509store/X509Object.java new file mode 100644 index 00000000000..b7f35dbc1e4 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/X509Object.java @@ -0,0 +1,88 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + +import java.util.List; + +/** + * c: X509_OBJECT + * + * @author Ola Bini + */ +public abstract class X509Object implements Comparable { + /** + * c: X509_OBJECT_idx_by_subject + */ + public static int indexBySubject(List h, int type, Name name) { + int ix = 0; + for(X509Object oo : h) { + if(type == oo.type() && oo.isName(name)) { + return ix; + } + } + return -1; + } + + /** + * c: X509_OBJECT_retrieve_by_subject + */ + public static X509Object retrieveBySubject(List h,int type,Name name) { + for(X509Object o : h) { + if(type == o.type() && o.isName(name)) { + return o; + } + } + return null; + } + + /** + * c: X509_OBJECT_retrieve_match + */ + public static X509Object retrieveMatch(List h, X509Object x) { + for(X509Object o : h) { + if(o.matches(x)) { + return o; + } + } + return null; + } + + public boolean isName(Name nm) { + return false; + } + + public boolean matches(X509Object o) { + return false; + } + + public abstract int type(); + + public int compareTo(X509Object other) { + return type() - other.type(); + } +}// X509_OBJECT diff --git a/src/org/jruby/ext/openssl/x509store/X509Utils.java b/src/org/jruby/ext/openssl/x509store/X509Utils.java new file mode 100644 index 00000000000..e8d23d1c188 --- /dev/null +++ b/src/org/jruby/ext/openssl/x509store/X509Utils.java @@ -0,0 +1,533 @@ +/***** BEGIN LICENSE BLOCK ***** + * Version: CPL 1.0/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Common Public + * License Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.eclipse.org/legal/cpl-v10.html + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * Copyright (C) 2006 Ola Bini + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the CPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the CPL, the GPL or the LGPL. + ***** END LICENSE BLOCK *****/ +package org.jruby.ext.openssl.x509store; + + +import java.util.Arrays; +import org.bouncycastle.asn1.ASN1InputStream; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.DEREncodable; +import org.bouncycastle.asn1.DEROctetString; +import org.bouncycastle.asn1.DERSequence; +import org.bouncycastle.asn1.DERTaggedObject; +import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier; +import org.bouncycastle.asn1.x509.GeneralName; +import org.bouncycastle.asn1.x509.SubjectKeyIdentifier; +import org.bouncycastle.asn1.x509.X509Name; + +/** + * Contains most of the functionality that beings with X509 in + * crypty/x509/x509_def.c, crypty/x509/x509_txt.c and others. + * + * @author Ola Bini + */ +public abstract class X509Utils { + private X509Utils() {} + + /** + * c: X509_get_default_private_dir + */ + public static String getDefaultPrivateDir() { + return X509_PRIVATE_DIR; + } + + /** + * c: X509_get_default_cert_area + */ + public static String getDefaultCertificateArea() { + return X509_CERT_AREA; + } + + /** + * c: X509_get_default_cert_dir + */ + public static String getDefaultCertificateDirectory() { + return X509_CERT_DIR; + } + + /** + * c: X509_get_default_cert_file + */ + public static String getDefaultCertificateFile() { + return X509_CERT_FILE; + } + + /** + * c: X509_get_default_cert_dir_env + */ + public static String getDefaultCertificateDirectoryEnvironment() { + return X509_CERT_DIR_EVP; + } + + /** + * c: X509_get_default_cert_file_env + */ + public static String getDefaultCertificateFileEnvironment() { + return X509_CERT_FILE_EVP; + } + + /** + * c: X509_verify_cert_error_string + */ + public static String verifyCertificateErrorString(int n) { + switch(n){ + case V_OK: + return("ok"); + case V_ERR_UNABLE_TO_GET_ISSUER_CERT: + return("unable to get issuer certificate"); + case V_ERR_UNABLE_TO_GET_CRL: + return("unable to get certificate CRL"); + case V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE: + return("unable to decrypt certificate's signature"); + case V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE: + return("unable to decrypt CRL's signature"); + case V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + return("unable to decode issuer public key"); + case V_ERR_CERT_SIGNATURE_FAILURE: + return("certificate signature failure"); + case V_ERR_CRL_SIGNATURE_FAILURE: + return("CRL signature failure"); + case V_ERR_CERT_NOT_YET_VALID: + return("certificate is not yet valid"); + case V_ERR_CRL_NOT_YET_VALID: + return("CRL is not yet valid"); + case V_ERR_CERT_HAS_EXPIRED: + return("certificate has expired"); + case V_ERR_CRL_HAS_EXPIRED: + return("CRL has expired"); + case V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + return("format error in certificate's notBefore field"); + case V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + return("format error in certificate's notAfter field"); + case V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD: + return("format error in CRL's lastUpdate field"); + case V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD: + return("format error in CRL's nextUpdate field"); + case V_ERR_OUT_OF_MEM: + return("out of memory"); + case V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + return("self signed certificate"); + case V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + return("self signed certificate in certificate chain"); + case V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + return("unable to get local issuer certificate"); + case V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + return("unable to verify the first certificate"); + case V_ERR_CERT_CHAIN_TOO_LONG: + return("certificate chain too long"); + case V_ERR_CERT_REVOKED: + return("certificate revoked"); + case V_ERR_INVALID_CA: + return ("invalid CA certificate"); + case V_ERR_INVALID_NON_CA: + return ("invalid non-CA certificate (has CA markings)"); + case V_ERR_PATH_LENGTH_EXCEEDED: + return ("path length constraint exceeded"); + case V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + return("proxy path length constraint exceeded"); + case V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED: + return("proxy cerificates not allowed, please set the appropriate flag"); + case V_ERR_INVALID_PURPOSE: + return ("unsupported certificate purpose"); + case V_ERR_CERT_UNTRUSTED: + return ("certificate not trusted"); + case V_ERR_CERT_REJECTED: + return ("certificate rejected"); + case V_ERR_APPLICATION_VERIFICATION: + return("application verification failure"); + case V_ERR_SUBJECT_ISSUER_MISMATCH: + return("subject issuer mismatch"); + case V_ERR_AKID_SKID_MISMATCH: + return("authority and subject key identifier mismatch"); + case V_ERR_AKID_ISSUER_SERIAL_MISMATCH: + return("authority and issuer serial number mismatch"); + case V_ERR_KEYUSAGE_NO_CERTSIGN: + return("key usage does not include certificate signing"); + case V_ERR_UNABLE_TO_GET_CRL_ISSUER: + return("unable to get CRL issuer certificate"); + case V_ERR_UNHANDLED_CRITICAL_EXTENSION: + return("unhandled critical extension"); + case V_ERR_KEYUSAGE_NO_CRL_SIGN: + return("key usage does not include CRL signing"); + case V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE: + return("key usage does not include digital signature"); + case V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION: + return("unhandled critical CRL extension"); + case V_ERR_INVALID_EXTENSION: + return("invalid or inconsistent certificate extension"); + case V_ERR_INVALID_POLICY_EXTENSION: + return("invalid or inconsistent certificate policy extension"); + case V_ERR_NO_EXPLICIT_POLICY: + return("no explicit policy"); + default: + return "error number " + n; + } + } + + private static Object get(Object str) throws Exception { + return get(((DEROctetString)str).getOctets()); + } + + private static Object get(byte[] str) throws Exception { + return new ASN1InputStream(str).readObject(); + } + + /** + * c: X509_check_issued + */ + public static int checkIfIssuedBy(X509AuxCertificate issuer, X509AuxCertificate subject) throws Exception { + if(!issuer.getSubjectX500Principal().equals(subject.getIssuerX500Principal())) { + return V_ERR_SUBJECT_ISSUER_MISMATCH; + } + + if(subject.getExtensionValue("2.5.29.35") != null) { //authorityKeyID + // I hate ASN1 and DER + Object key = get(subject.getExtensionValue("2.5.29.35")); + if(!(key instanceof ASN1Sequence)) { + key = get(key); + } + + ASN1Sequence seq = (ASN1Sequence)key; + AuthorityKeyIdentifier sakid = null; + if(seq.size() == 1 && (seq.getObjectAt(0) instanceof ASN1OctetString)) { + sakid = new AuthorityKeyIdentifier(new DERSequence(new DERTaggedObject(0, seq.getObjectAt(0)))); + } else { + sakid = new AuthorityKeyIdentifier(seq); + } + + if(sakid.getKeyIdentifier() != null) { + if(issuer.getExtensionValue("2.5.29.14") != null) { + DEROctetString der = (DEROctetString)get(issuer.getExtensionValue("2.5.29.14")); + if(der.getOctets().length > 20) { + der = (DEROctetString)get(der.getOctets()); + } + SubjectKeyIdentifier iskid = new SubjectKeyIdentifier(der); + if(iskid.getKeyIdentifier() != null) { + if(!Arrays.equals(sakid.getKeyIdentifier(),iskid.getKeyIdentifier())) { + return V_ERR_AKID_SKID_MISMATCH; + } + } + } + } + if(sakid.getAuthorityCertSerialNumber() != null && !sakid.getAuthorityCertSerialNumber().equals(issuer.getSerialNumber())) { + return V_ERR_AKID_ISSUER_SERIAL_MISMATCH; + } + if(sakid.getAuthorityCertIssuer() != null) { + GeneralName[] gens = sakid.getAuthorityCertIssuer().getNames(); + X509Name nm = null; + for(int i=0;i