Stubbing a method on controller instances on rspec type controller is easy, just:

allow(controller).to receive_messages(current_user: create(:user))

And on rspec type request is a common this bad practice

allow_any_instance_of(MyController).to receive(:current_user).and_return(create(:user))

A smart way to avoid this is use of allow_any_instance_of. Let's code this solution!

See more
πŸ—“ 2020-09-14
193 πŸ‘€

As you may already know, a signed tag is a SignedInfo
The public certificate always in X509Certificate
And the content of the SignatureValuetag is a digital signature itself.

require 'openssl'
require 'base64'
require 'nokogiri'

xml = '...'

signed_info = xml.scan(/\<SignedInfo\>[\s\S]*?\<\/SignedInfo\>/)[0].gsub(/>\s+</,"><")
signed_info.gsub!("<SignedInfo>",%{<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">})
signed_info = Nokogiri::XML(signed_info.gsub(/>\s+</,"><")).canonicalize(Nokogiri::XML::XML_C14N_1_1) 

signature_value = xml.scan(/(?<=\<SignatureValue\>)[\s\S]*?(?=\<\/SignatureValue\>)/)[0]

x509_certificate = xml.scan(/(?<=\<X509Certificate\>)[\s\S]*?(?=\<\/X509Certificate\>)/)[0]
x509_certificate = %{-----BEGIN CERTIFICATE-----\n#{x509_certificate}\n-----END CERTIFICATE-----}

certificate = OpenSSL::X509::Certificate.new x509_certificate

digest_method_algorithm = signed_info.scan(/(\<DigestMethod[\s\S]*?\#)([\s\S]*?)(\"|\')/)[0][1]

certificate.public_key.verify OpenSSL::Digest.new(digest_method_algorithm), Base64.decode64(signature_value), signed_info
import re
import lxml.etree as ET
from io import BytesIO
import base64
from OpenSSL import crypto

xml = '...'
signed_info = re.search(r"\<SignedInfo>[\s\S]*?\<\/SignedInfo\>", xml).group()
signed_info = signed_info.replace("<SignedInfo>",'<SignedInfo xmlns="http://www.w3.org/2000/09/xmldsig#">')

tree = ET.ElementTree(ET.fromstring(signed_info))
output = BytesIO()
tree.write_c14n(output)

signed_info = output.getvalue()

signature_value = re.search(r"(?<=\<SignatureValue\>)[\s\S]*?(?=\<\/SignatureValue\>)", xml).group()

x509_certificate = re.search(r"(?<=\<X509Certificate\>)[\s\S]*?(?=\<\/X509Certificate\>)", xml).group()

certificate = crypto.load_certificate(crypto.FILETYPE_PEM, "-----BEGIN CERTIFICATE-----\n" + x509_certificate + "\n-----END CERTIFICATE-----")
digest_method_algorithm = re.search(r"(\<DigestMethod[\s\S]*?\#)([\s\S]*?)(\"|\')", xml).group(2)

pk = certificate.get_pubkey()
x509 = crypto.X509()
x509.set_pubkey(pk)

print(crypto.verify(x509, base64.b64decode(signature_value), signed_info, digest_method_algorithm) == None)
import java.io.ByteArrayInputStream;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Base64;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer;

public class SignatureCheck {
  public static void main(String[] args) throws Exception {   
    String xml = "...";
    Matcher matcher = Pattern.compile("\\<SignedInfo\\>[\\s\\S]*?\\<\\/SignedInfo\\>").matcher(xml);
    matcher.find();
    String signed_info = matcher.group(0);
    signed_info = signed_info.replace("<SignedInfo>", "<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">");
    com.sun.org.apache.xml.internal.security.Init.init();
    Canonicalizer c = Canonicalizer.getInstance(Canonicalizer.ALGO_ID_C14N11_OMIT_COMMENTS);
    byte[] signed_info_b = c.canonicalize(signed_info.getBytes());
    signed_info = new String(signed_info_b);
    matcher = Pattern.compile("(?<=\\<SignatureValue\\>)[\\s\\S]*?(?=\\<\\/SignatureValue\\>)").matcher(xml);
    matcher.find();
    String signature_value = matcher.group(0);
    matcher = Pattern.compile("(?<=\\<X509Certificate\\>)[\\s\\S]*?(?=\\<\\/X509Certificate\\>)").matcher(xml);
    matcher.find();
    String x509_certificate = matcher.group(0);
    x509_certificate = "-----BEGIN CERTIFICATE-----\n" + x509_certificate + "\n-----END CERTIFICATE-----";
    CertificateFactory cf = CertificateFactory.getInstance("X509");
    X509Certificate certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(x509_certificate.getBytes()));
    matcher = Pattern.compile("(\\<DigestMethod[\\s\\S]*?\\#)([\\s\\S]*?)(\\\"|\\')").matcher(signed_info);
    matcher.find();
    String digest_method_algorithm =  matcher.group(2);
    Signature sig = Signature.getInstance(digest_method_algorithm.toUpperCase()+"withRSA");   sig.initVerify(certificate.getPublicKey());
    sig.update(signed_info.getBytes());
    System.out.println(sig.verify(Base64.getDecoder().decode(signature_value.getBytes())));
  }
}
See more
πŸ—“ 2019-01-09
253 πŸ‘€

Visit https://myaccount.google.com/lesssecureapps and set on

require 'net/smtp'
smtp = Net::SMTP.new('smtp.gmail.com', 587)
smtp.enable_starttls
smtp.start('gmail.com', "your_email@gmail.com", 'your_pass', :plain) do |smtp|
  smtp.send_message "hello world", 'your_email@gmail.com', ['your_dest@gmail.com']
end
import smtplib
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login("your_email@gmail.com", "your_pass")
msg = "Hello!" 
s.sendmail("your_email@gmail.com", "email_dest", msg)
String to = "your_email@gmail.com";
String from = "your_email@gmail.com";
final String username = "name sender";
final String password = "yout_pass";
String host = "smtp.gmail.com";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(username, password);
  }
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject("Subject goes here");
message.setText("Hello world");
Transport.send(message);
System.out.println("Done!");
See more
πŸ—“ 2017-10-16
629 πŸ‘€

Visit https://myaccount.google.com/lesssecureapps and set on

require 'net/smtp'
smtp = Net::SMTP.new('smtp.gmail.com', 587)
smtp.enable_starttls
smtp.start('gmail.com', "your_email@gmail.com", 'your_pass', :plain) do |smtp|
  smtp.send_message "hello world", 'your_email@gmail.com', ['your_dest@gmail.com']
end
import smtplib
s = smtplib.SMTP('smtp.gmail.com', 587)
s.starttls()
s.login("your_email@gmail.com", "your_pass")
msg = "Hello!" 
s.sendmail("your_email@gmail.com", "email_dest", msg)
String to = "your_email@gmail.com";
String from = "your_email@gmail.com";
final String username = "name sender";
final String password = "yout_pass";
String host = "smtp.gmail.com";
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.host", host);
props.put("mail.smtp.port", "587");
Session session = Session.getInstance(props, new javax.mail.Authenticator() {
  protected PasswordAuthentication getPasswordAuthentication() {
    return new PasswordAuthentication(username, password);
  }
});
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(from));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(to));
message.setSubject("Subject goes here");
message.setText("Hello world");
Transport.send(message);
System.out.println("Done!");
See more
πŸ—“ 2017-10-16
πŸ‘€

Why use third-party libraries can you use native resources of language easily?

require 'net/https'
require 'uri'

public_cert, private_key, password = ENV['CERT'], ENV['PK'], ENV['PKPASS']

@header = {}
@data = %{}

uri = URI.parse "https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx"
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.key = OpenSSL::PKey::RSA.new File.read(private_key), password
http.cert = OpenSSL::X509::Certificate.new File.read(public_cert)
response = http.post(uri.path, @data, @header)
puts response.body
import http.client, json, ssl, os

public_cert, private_key, password = os.environ['CERT'], os.environ['PK'], os.environ['PKPASS']

context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.load_cert_chain(public_cert, keyfile=private_key, password=password)

conn = http.client.HTTPSConnection('www1.nfe.fazenda.gov.br', port=443, context=context)

header = {}
body = "..."

json_data = json.dumps(body)
conn.request('POST', '/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx', body, header)
response = conn.getresponse()
print(response.read().decode())
String path_pk = "/path/to/pk.pfx";
String pass = "******";
String url_ws = "https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx";
String soap_message = "";
String soap_action = "http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe/nfeDistDFeInteresse";

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream fis = new FileInputStream(new File(path_pk));
ks.load(fis, pass.toCharArray());
fis.close();

URL url = new URL(url_ws);
TrustManager[] trustAllCerts = new TrustManager[] {
  new X509TrustManager() {
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
    @Override
    public X509Certificate[] getAcceptedIssuers() {return null;}
  }
};

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, pass.toCharArray());

SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());

HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();

uc.setDoOutput(true);
uc.setRequestMethod("POST");
uc.setRequestProperty("Content-Type", "application/soap+xml;charset=UTF-8");
uc.setRequestProperty("SOAPAction", soap_action);
OutputStream wr = uc.getOutputStream();
wr.write(soap_message.getBytes());
wr.flush();
wr.close();

BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
  response.append(inputLine);
}
in.close();
System.out.println(response.toString());
See more
πŸ—“ 2017-10-10
πŸ‘€

Do you have a xml a xml and want validate?
This is all that you need

require 'nokogiri'

xml_path = "/path/to/xml.xml"
xsd_path = "/path/to/xsd.xsd"

xsddoc = Nokogiri::XML(File.read(xsd_path), xsd_path)

xsd = Nokogiri::XML::Schema.from_document(xsddoc)

doc = Nokogiri::XML.parse File.read(xml_path)

if xsd.valid?(doc)
  return "ok"
else
  for x_error in xsd.validate(doc)
    puts x_error.message
  end
end
from lxml import etree

xml_path = "/path/to/xml.xml"
xsd_path = "/path/to/xsd.xsd"

xmlschema_doc = etree.parse(xsd_path)

xmlschema = etree.XMLSchema(xmlschema_doc)

doc = etree.parse(xml_path)

# if you use a xml string use:
# doc = etree.parse(StringIO(xml))

if xmlschema.validate(doc):
  print("ok")
else:
  for i in xmlschema.error_log: 
    print(i.message)
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class Validate {
  public static void main(String[] args) throws IOException, SAXException {
    String xml_path = "/path/to/xml.xml";
    String xsd_path = "/path/to/xsd.xsd";

    List<String> errors = vai(xml_path, xsd_path);
    if (errors.size() > 0) {
      for (String string : errors) {
        System.out.println(string);
      }
    } else {
      System.out.println("ok");
    }
  }

  public static List<String> vai(String xml_path, String xsd_path) throws IOException, SAXException {
    String schemaLang = "http://www.w3.org/2001/XMLSchema";
    SchemaFactory factory = SchemaFactory.newInstance(schemaLang);

    Schema schema = factory.newSchema(new StreamSource(xsd_path));

    Validator validator = schema.newValidator();

    List<String> errors = new LinkedList<String>();

    validator.setErrorHandler(new ErrorHandler() {
      @Override
      public void warning(SAXParseException e) throws SAXException {
        errors.add(e.getMessage());
      }

      @Override
      public void fatalError(SAXParseException e) throws SAXException {
        errors.add(e.getMessage());
      }

      @Override
      public void error(SAXParseException e) throws SAXException {
        errors.add(e.getMessage());
      }
    });
    
    // if you use a xml string use:
    // validator.validate(new StreamSource(new StringReader(xml)));
    validator.validate(new StreamSource(xml_path));

    return errors;
  }
}
See more
πŸ—“ 2016-12-12
820 πŸ‘€

Start, stop, status your service

$ systemctl start writer
$ systemctl stop writer
$ systemctl status writer

To call a service when system up just

$ systemctl enable writer
See more
πŸ—“ 2016-10-26
850 πŸ‘€

Criando o cliente

client = Savon.client(
  encoding: "UTF-8",
  wsdl: "https://nfe-homologacao.svrs.rs.gov.br/ws/NfeAutorizacao/NFeAutorizacao.asmx?WSDL",
  ssl_verify_mode: :none,
  ssl_cert_file: "/diretorio/para/seu/certificado.pem",
  ssl_cert_key_file: "/diretorio/para/sua/chave_privada.pem",
  ssl_cert_key_password: "senha_da_chave_privada"
)

Se tudo estiver ok, vocΓͺ poderΓ‘ ver os mΓ©todos do web service assim:

operations = client.operations
# que retorna
# [:nfe_autorizacao_lote, :nfe_autorizacao_lote_zip]
See more
πŸ—“ 2016-10-21
898 πŸ‘€

Para calcular o DigestValue

  • acrescentar o namespace xmlns com o valor http://www.portalfiscal.inf.br/nfe na tag infNFe
  • canonizar a tag infNFe
  • calcular o Digest usando SHA1 e converter o resultado pra Base64

Para assinar a nota

  • acrescentar o namespace xmlns com o valor http://www.w3.org/2000/09/xmldsig# na tag SignedInfo
  • canonizar a tag SignedInfo
  • Assinar a tag SignedInfo, converter o resultado pra Base64

Faltou alguma coisa?

See more
πŸ—“ 2016-08-21
1785 πŸ‘€

Creating your custom validator

class Book < ApplicationRecord
  belongs_to :author
  validates :isbn, length: {included: [10, 13]}
end

Executing the book tests again

$ rspec spec/models/book_spec.rb
........

Finished in 0.23966 seconds (files took 9.44 seconds to load)
8 examples, 0 failures
See more
πŸ—“ 2017-12-19
1005 πŸ‘€

Push your gem to https://rubygems.orgwith this command

$ gem push gtest-0.1.0.gem
  Pushing gem to https://rubygems.org...
  Successfully registered gem: gtest (0.1.0)
See more
πŸ—“ 2016-05-05
1028 πŸ‘€

Example 1

Call alert

ba("This is a message!")
See more
πŸ—“ 2016-04-08
1603 πŸ‘€

Open the JS console and try

"abc".include("a")

Happens this

"abc".include is not a function

Let's code a solution!

See more
πŸ—“ 2016-04-08
1085 πŸ‘€