# File lib/mcollective/security/aes_security.rb, line 68
      def decodemsg(msg)
        body = deserialize(msg.payload)

        should_process_msg?(msg, body[:requestid])
        # if we get a message that has a pubkey attached and we're set to learn
        # then add it to the client_cert_dir this should only happen on servers
        # since clients will get replies using their own pubkeys
        if Util.str_to_bool(@config.pluginconf.fetch("aes.learn_pubkeys", false)) && body.include?(:sslpubkey)
          certname = certname_from_callerid(body[:callerid])
          certfile = "#{client_cert_dir}/#{certname}.pem"
          if !File.exist?(certfile)
            if !Util.str_to_bool(@config.pluginconf.fetch("aes.insecure_learning", false))
              if !@config.pluginconf.fetch("aes.ca_cert", nil)
                raise "Cannot verify certificate for '#{certname}'. No CA certificate specified."
              end

              if !validate_certificate(body[:sslpubkey], certname)
                raise "Unable to validate certificate '#{certname}' against CA"
              end

              Log.debug("Verified certificate '#{certname}' against CA")
            else
              Log.warn("Insecure key learning is not a secure method of key distribution. Do NOT use this mode in sensitive environments.")
            end

            Log.debug("Caching client cert in #{certfile}")
            File.open(certfile, "w") {|f| f.print body[:sslpubkey]}
          else
            Log.debug("Not caching client cert. File #{certfile} already exists.")
          end
        end

        cryptdata = {:key => body[:sslkey], :data => body[:body]}

        if @initiated_by == :client
          body[:body] = deserialize(decrypt(cryptdata, nil))
        else
          certname = certname_from_callerid(body[:callerid])
          certfile = "#{client_cert_dir}/#{certname}.pem"
          # if aes.ca_cert is set every certificate is validated before we try and use it
          if @config.pluginconf.fetch("aes.ca_cert", nil) && !validate_certificate(File.read(certfile), certname)
            raise "Unable to validate certificate '#{certname}' against CA"
          end
          body[:body] = deserialize(decrypt(cryptdata, body[:callerid]))

          # If we got a hash it's possible that this is a message with secure
          # TTL and message time, attempt to decode that and transform into a
          # traditional message.
          #
          # If it's not a hash it might be a old style message like old discovery
          # ones that would just be a string so we allow that unaudited but only
          # if enforce_ttl is disabled.  This is primarly to allow a mixed old and
          # new plugin infrastructure to work
          if body[:body].is_a?(Hash)
            update_secure_property(body, :aes_ttl, :ttl, "TTL")
            update_secure_property(body, :aes_msgtime, :msgtime, "Message Time")

            body[:body] = body[:body][:aes_msg] if body[:body].include?(:aes_msg)
          else
            unless @config.pluginconf["aes.enforce_ttl"] == "0"
              raise "Message %s is in an unknown or older security protocol, ignoring" % [request_description(body)]
            end
          end
        end

        return body
      rescue MsgDoesNotMatchRequestID
        raise

      rescue OpenSSL::PKey::RSAError
        raise MsgDoesNotMatchRequestID, "Could not decrypt message using our key, possibly directed at another client"

      rescue Exception => e
        Log.warn("Could not decrypt message from client: #{e.class}: #{e}")
        raise SecurityValidationFailed, "Could not decrypt message"
      end