EJEMPLO CALCULO DE TIMBRE ELECTRÓNICO CON RUBY

Mensaje a Firmar

<DD><RE>97975000-5</RE><TD>33</TD><F>27</F><FE>2003-09-08</FE>
<RR>8414240-9</RR><RSR>JORGE GONZALEZ LTDA</RSR><MNT>502946</M
NT><IT1>Cajon AFECTO</IT1><CAF version="1.0"><DA><RE>97975000-
5</RE><RS>RUT DE PRUEBA</RS><TD>33</TD><RNG><D>1</D><H>200</H>
</RNG><FA>2003-09-04</FA><RSAPK><M>0a4O6Kbx8Qj3K4iWSP4w7KneZYe
J+g/prihYtIEolKt3cykSxl1zO8vSXu397QhTmsX7SBEudTUx++2zDXBhZw==<
/M><E>Aw==</E></RSAPK><IDK>100</IDK></DA><FRMA algoritmo="SHA1
withRSA">g1AQX0sy8NJugX52k2hTJEZAE9Cuul6pqYBdFxj1N17umW7zG/hAa
vCALKByHzdYAfZ3LhGTXCai5zNxOo4lDQ==</FRMA></CAF><TSTED>2003-09
-08T12:28:31</TSTED></DD>

Clave RSA Privada obtenida del CAF

-----BEGIN RSA PRIVATE KEY-----
MIIBOwIBAAJBANGuDuim8fEI9yuIlkj+MOyp3mWHifoP6a4oWLSBKJSrd3MpEsZd
czvL0l7t/e0IU5rF+0gRLnU1Mfvtsw1wYWcCAQMCQQCLyV9FxKFLW09yWw7bVCCd
xpRDr7FRX/EexZB4VhsNxm/vtJfDZyYle0Lfy42LlcsXxPm1w6Q6NnjuW+AeBy67
AiEA7iMi5q5xjswqq+49RP55o//jqdZL/pC9rdnUKxsNRMMCIQDhaHdIctErN2hC
IP9knS3+9zra4R+5jSXOvI+3xVhWjQIhAJ7CF0R0S7SIHHKe04NUURf/7RvkMqm1
08k74sdnXi3XAiEAlkWk2vc2HM+a1sCqQxNz/098ketqe7NuidMKeoOQObMCIQCk
FAMS9IcPcMjk7zI2r/4EEW63PSXyN7MFAX7TYe25mw==
-----END RSA PRIVATE KEY-----

El resultado obtenido de la firma RSA-SHA1, utilizado la llave privada sobre el mensaje es:

pqjXHHQLJmyFPMRvxScN7tYHvIsty0pqL2LLYaG43jMmnfiZfllLA0wb32lP+HBJ
/tf8nziSeorvjlx410ZImw==

CODIGO EN RUBY

require 'openssl'
require 'base64'

# Mensaje XML como string (ajustado en una sola línea para firma exacta)
mensaje = <<~XML.gsub("\n", '')
  <DD><RE>97975000-5</RE><TD>33</TD><F>27</F><FE>2003-09-08</FE><RR>8414240-9</RR><RSR>JORGE GONZALEZ LTDA</RSR><MNT>502946</MNT><IT1>Cajon AFECTO</IT1><CAF version="1.0"><DA><RE>97975000-5</RE><RS>RUT DE PRUEBA</RS><TD>33</TD><RNG><D>1</D><H>200</H></RNG><FA>2003-09-04</FA><RSAPK><M>0a4O6Kbx8Qj3K4iWSP4w7KneZYeJ+g/prihYtIEolKt3cykSxl1zO8vSXu397QhTmsX7SBEudTUx++2zDXBhZw==</M><E>Aw==</E></RSAPK><IDK>100</IDK></DA><FRMA algoritmo="SHA1withRSA">g1AQX0sy8NJugX52k2hTJEZAE9Cuul6pqYBdFxj1N17umW7zG/hAavCALKByHzdYAfZ3LhGTXCai5zNxOo4lDQ==</FRMA></CAF><TSTED>2003-09-08T12:28:31</TSTED></DD>
XML

# Clave privada como string
clave_privada_pem = <<~PEM
  -----BEGIN RSA PRIVATE KEY-----
  MIIBOwIBAAJBANGuDuim8fEI9yuIlkj+MOyp3mWHifoP6a4oWLSBKJSrd3MpEsZd
  czvL0l7t/e0IU5rF+0gRLnU1Mfvtsw1wYWcCAQMCQQCLyV9FxKFLW09yWw7bVCCd
  xpRDr7FRX/EexZB4VhsNxm/vtJfDZyYle0Lfy42LlcsXxPm1w6Q6NnjuW+AeBy67
  AiEA7iMi5q5xjswqq+49RP55o//jqdZL/pC9rdnUKxsNRMMCIQDhaHdIctErN2hC
  IP9knS3+9zra4R+5jSXOvI+3xVhWjQIhAJ7CF0R0S7SIHHKe04NUURf/7RvkMqm1
  08k74sdnXi3XAiEAlkWk2vc2HM+a1sCqQxNz/098ketqe7NuidMKeoOQObMCIQCk
  FAMS9IcPcMjk7zI2r/4EEW63PSXyN7MFAX7TYe25mw==
  -----END RSA PRIVATE KEY-----
PEM

# Cargar clave privada
clave_privada = OpenSSL::PKey::RSA.new(clave_privada_pem)

# Crear la firma con SHA1 y RSA
firma_binaria = clave_privada.sign(OpenSSL::Digest::SHA1.new, mensaje)

# Codificar la firma en Base64
firma_base64 = Base64.encode64(firma_binaria).gsub("\n", '')

puts "Firma generada:\n#{firma_base64}"

Comentarios

Entradas populares de este blog

Creación de un DTE de boleta electrónica usando AppDTE Api:

Guía de Consulta de DTE

¡Nuevo Entorno de Pruebas Disponible para AppDTE API!