Hace unos días, los rumores aparecieron repentinamente en Internet: una filtración de datos de 12 g en cierto este, y al final, no lo negué en un comunicado, y apenas fue admitido. Ya hay muchas personas que han dicho qué impacto tiene este asunto en la gente común y cómo hacerlo, por lo que no me uniré a la diversión. Hablemos de un algoritmo práctico de cifrado que personalmente creo que es relativamente seguro en la actualidad: Blowfish.
Antes de ingresar al código, permítanme hablar sobre las características del algoritmo de cifrado de pez soplete:
1. Cifrado simétrico, es decir, la clave cifrada y la clave descifrada son la misma;
2. Los resultados después de cada cifrado son diferentes (esto es algo que aprecio más);
3. Reversible, diferente de los algoritmos abstractos como MD5 introducido en mi artículo anterior, es reversible;
4. Velocidad rápida, el proceso de cifrado y descifrado está básicamente compuesto de operaciones de instrucciones ADD y XOR;
5. Gratis, cualquiera puede usarlo gratis sin pagar tarifas de derechos de autor;
6. Blowfish solo puede cifrar y descifrar 8 bytes de datos a la vez;
El algoritmo Blowfish es un algoritmo simétrico de cifrado de paquetes. El núcleo del algoritmo se encuentra en la generación de subkeyos, que expande la tecla de longitud variable en una matriz de subcuciones con una longitud total de 4168 byte. Se usa una gran cantidad de subkeyys en el algoritmo, y los subkeyas dependen de la clave del usuario. En el proceso de adición/descifrado real, se utiliza la matriz de subclave actualizada, a saber, la matriz P y el cuadro S. El algoritmo Blowfish tiene una función de cifrado de núcleo: bf_en (). La entrada de esta función es la información de texto sin formato de 64 bits. Después del cálculo, se emite en forma de información de texto cifrado de 64 bits. Para cifrar información utilizando el algoritmo de pez soplete, se requieren dos procesos: preprocesamiento clave y cifrado de información. Del mismo modo, el descifrado también requiere dos procesos, preprocesamiento clave y descifrado de información.
La clave de origen del algoritmo de pescado de soplado - Pbox y Sbox se fijan. Si queremos cifrar un mensaje, necesitamos elegir una clave y usar esta clave para transformar PBox y Sbox para obtener la tecla_pbox y Key_Sbox para usar para el siguiente paso de cifrado de información. Lo mismo es cierto para el descifrado. Dado que Blowfish es un algoritmo de cifrado simétrico, la parte de descifrado genera el Key_Box y Key_SBox requerido para el descifrado en función de la clave después de obtener la clave. Cifrar y descifrar la misma información, y las diferentes claves seleccionadas conducirán a diferentes texto cifrado. Por lo tanto, la clave para el algoritmo de pez soplado radica en la elección de la clave y la confidencialidad.
Dado que el algoritmo Blowfish usa claves de longitud variable, esto no solo aporta una gran comodidad a los usuarios, sino que también tiene peligros ocultos. Dado que el núcleo de cifrado/descifrado de algoritmo radica en la selección y confidencialidad de las claves, en las aplicaciones reales, algunas claves débiles a menudo se usan para cifrar los recursos de información, lo que resulta en grandes riesgos de seguridad.
El siguiente es la parte más importante, la implementación del algoritmo de cifrado de pez soplado:
paquete cn.bridgeli.Encrypt; public enum BlowfishManager {bridgeli_cn ("Bridgeli_cn!@#$ ABC123_"); Private BlowfishManager (String Secret) {this.blowfish = new Blowfish (secreto); } pez soplete privado; Public Blowfish getBlowfish () {return Blowfish; } / ** * Decrypt * @param sciphertext * @return * / public string DecryptString (String Sciphertext) {return this.getBlowfish (). DecryptString (scipHerText); } / ** * encrypt * @param splAINTEXT * @return * / public string encryptString (string straintext) {return this.getBlowfish (). CiCryPTString (SplAintext); } public static void main (string [] args) {String CiCryptString = BlowfishManager.bridgeli_cn.EncryptString (10 + ""); System.out.println (cifrado); Cadena DecryptString = BlowfishManager.bridgeli_cn.DecryptString (CiCryptString); System.out.println (DecryptString); }}Esta es una interfaz externa, que es muy simple de usar y es fácil de usar. La siguiente es la implementación específica del algoritmo:
paquete cn.bridgeli.Errypt; import java.security.messageGest; import java.util.random; import org.slf4j.logger; import og.slf4j.loggerFactory; public class Blowfish {Logger final estático privado Log = logGactory.getLogger (wopefish.class); La clase estática privada BlowfishCBC extiende Blowfishecb {public void setcbciv (long lnewcbciv) {m_lcbciv = lnewcbciv; } public void setcbciv (byte newCbciv []) {m_lcbciv = wearfish.bytearraytolong (newCbciv, 0); } @Override public void Cleanup () {m_lcbciv = 0l; super.cleanup (); } Private Long CiCryptBlockCBC (Long LPlainBlock) {LPlainBlock ^= M_LCBCIV; llainblock = super.EncryptBlock (LPlainBlock); return m_lcbciv = lPlainBlock; } Private Long DecryptBlockCBC (long lcipherblock) {long ltemp = lcipherblock; lcipherblock = super.decryptblock (lcipherblock); lcipherblock ^= m_lcbciv; m_lcbciv = ltemp; devolver lcipherblock; } public void encrypt (byte buffer []) {int nlen = buffer.length; for (int ni = 0; ni <nlen; ni += 8) {long ltemp = wearffish.bytearraytolong (buffer, ni); ltemp = cifryptblockcbc (ltemp); Blowfish.longtobytearray (Ltemp, buffer, Ni); }} public void Decrypt (byte buffer []) {int nlen = buffer.length; for (int ni = 0; ni <nlen; ni += 8) {long ltemp = wearffish.bytearraytolong (buffer, ni); ltEMP = DecryptBlockCBC (LTEMP); Blowfish.longtobytearray (Ltemp, buffer, Ni); }} long m_lcbciv; public Blowfishcbc (byte bfkey []) {super (bfkey); setCbCiv (0l); } public Blowfishcbc (byte bfkey [], long linitcbciv) {super (bfkey); setCBCIV (LinitCBCiv); } public BlowfishCbc (byte bfkey [], byte initcbciv []) {super (bfkey); setCBCiv (initCBCiv); }} clase estática privada Blowfishecb {public void limpiueP () {for (int ni = 0; ni <18; ni ++) {m_pbox [ni] = 0; } for (int ni = 0; ni <256; ni ++) {m_sbox1 [ni] = m_sbox2 [ni] = m_sbox3 [ni] = m_sbox4 [ni] = 0; }} protegido largo cifrado (largo LPlainBlock) {int nhi = blowfish.longhi32 (llainblock); int nlo = blowfish.longlo32 (llainblock); int sbox1 [] = m_sbox1; int sbox2 [] = m_sbox2; int sbox3 [] = m_sbox3; int sbox4 [] = m_sbox4; int pbox [] = m_pbox; nhi ^= pbox [0]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [1]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [2]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [3]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [4]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [5]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [6]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [7]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [8]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [9]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [10]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [11]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [12]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [13]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [14]; nlo ^ = (sbox1 [nhi >>> 24] + sbox2 [nhi >>> 16 & 0xff] ^ sbox3 [nhi >>> 8 & 0xff]) + sbox4 [nhi & 0xff] ^ pbox [15]; nhi ^ = (sbox1 [nlo >>> 24] + sbox2 [nlo >>> 16 & 0xff] ^ sbox3 [nlo >>> 8 y 0xff]) + sbox4 [nlo & 0xff] ^ pbox [16]; return blowfish.makelong (nhi, nlo ^ pbox [17]); } Protegido largo DecryptBlock (long lcipherblock) {int nhi = blowfish.longhi32 (lcipherblock); int nlo = blowfish.longlo32 (lcipherblock); nhi ^= m_pbox [17]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [16]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [15]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [14]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [13]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [12]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [11]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [11]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [10]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [9]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [8]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [7]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [7]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [6]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [5]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [4]; nhi ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [4]; nhi ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [3]; nlo ^ = (m_sbox1 [nhi >>> 24] + m_sbox2 [nhi >>> 16 & 0xff] ^ m_sbox3 [nhi >>> 8 & 0xff]) + m_sbox4 [nhi & 0xff] ^ m_pbox [2]; nlo ^ = (m_sbox1 [nlo >>> 24] + m_sbox2 [nlo >>> 16 & 0xff] ^ m_sbox3 [nlo >>> 8 & 0xff]) + m_sbox4 [nlo & 0xff] ^ m_pbox [1]; return blowfish.makelong (nhi, nlo ^ m_pbox [0]); } int m_pbox []; int m_sbox1 []; int m_sbox2 []; int m_sbox3 []; int m_sbox4 []; estática final int pBox_init [] = {0x243f6a88, 0x85a308d3, 0x13198a2e, 0x3707344, 0xa4093822, 0x299f31d0, 0x82efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b}; static final int sbox_init_1 [] = {0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb391616cff7cf7b391 0x801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0xd95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b541, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a8b01e8b01e8b01e8b01e8b01e8b01e8b01e8b01e8B01E8B01E8B01E8B01E8 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xCe5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xeF845D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5D5DE 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0xf6d6ff3, 0x83f444239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9b5e1f9b5e1f9b5e1f9b5e1f9e 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xBa3bf050, 0x7EfB2A98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333N cada cadax. 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x75372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x4c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x6660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x55579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfbb1fa 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f55573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f01010, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1df2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3c1ad, 0x2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7c43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a89a89a8 0xd6411bd3, 0xae1e7e49, 0x250e2d, 0x2071b35e, 0x2226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x55563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x2e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9153291529 0xd60f573f, 0xbc9b6e4, 0x2b60a476, 0x81e67400, 0x8ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x8ba4799, 0x6e85076a}; estática final int sbox_init_2 [] = {0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x9f73f73f73fd67 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x21ecc5e, 0x9686b3f, 0x3ebbaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xAa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c, 0xf01c1f04, 0x200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2Dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0xfd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x1833eB331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3aC3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x13333e4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x435556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e. 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71313131313131313131313131313131313131313131313I 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x18cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeeCea50f, 0xdb2f953b, 0x2aef7Dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x334fe1e, 0xaxaa. 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655ABB50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a. 0x11ED935F, 0x166681281, 0xe358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb3333eeB30eB, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45ee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b47676676, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x95bbf00, 0xad1949d1944d1944d19444d19449d194449d194449d19d1944449d19449444949d194444494949494944944494944944944444448AT1944444448Ad19444444448Ad1944944444448Ad19444444448N 0x1462b174, 0x23820e00, 0x58428d2a, 0xc55f5ea, 0x1Dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde359, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d997335, 0xa969a7aaa, 0xc50c06c2, 0x5a04abfc, 0x800bcad 0x9e447a2e, 0xc3453484, 0xfdd56705, 0xe1e9eC9, 0xdb73dbd3, 0x1055588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3f8f8f8d2, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7}; estática final int sbox_init_3 [] = {0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd408241, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x972444546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4dd3, 0x6a 0xbfbc09ec, 0x3bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0xa2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd33375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x5555533a3a, 0x20838d87, 0xfeba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5eF47e1c, 0x9029317c, 0xfdf8e802, 0x4272f70, 0x90b15c, 0x5282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x7f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0xe12b4c2, 0x2e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0xa476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x91be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x68442, 0xc66a2b3b, 0x12754ccc, 0x782Ef11c, 0x6a124237, 0xb79251e7, 0x6a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c9, 0x44421659, 0xa121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbeBfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7AEB2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd555591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x9f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0xba4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0xde6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x6058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xCE591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15b415 0xd39eb8fc, 0xed545578, 0x8fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0}; static final int sbox_init_4 [] = {0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa333742, 0xd382740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946eb9, 0xc6a376d2, 0x6549c89c865454545454545454545454545454545454545454545454545454545454 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xBe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce, 0x96ee222222222222222222222- 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba9586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x22b8b51, 0x96d5ac3a, 0x17da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe 0xe019a5e6, 0x47b0Acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe8c. 0x15056dd4, 0x88f46dba, 0x3a16125, 0x564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x3563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xAbcc5167, 0xccad925f, 0x4de81751, 0x383830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x9072166, 0xb39a460a, 0x64445c0dd, 0x586cdecf, 0x1c20c8ee, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bbbbbbbbbbbbbbbb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x115af84, 0xe1b00428, 0x959833333333959595959595959598 0x6b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x11a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xe083333339e 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf011c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecbb, 0xd5sada38, 0x339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf9722c, 0x15e6fc2a, 0xf91f91f91f91, 0xf91, 0xf91f91f91, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x16988db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a74441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359595595595555555555555555555555555555555555555555555555555555555MAS 0x9b992f2e, 0xe60b6f47, 0xfe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2999999, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x2fb8a8c, 0x1c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252525252525252525252525252525252525252525252525252525252525252525 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6}; public Blowfishecb (byte bfkey []) {m_pbox = new int [18]; for (int ni = 0; ni <18; ni ++) {m_pbox [ni] = pbox_init [ni]; } m_sbox1 = new int [256]; m_sbox2 = new int [256]; m_sbox3 = new int [256]; m_sbox4 = new int [256]; for (int ni = 0; ni <256; ni ++) {m_sbox1 [ni] = sbox_init_1 [ni]; m_sbox2 [ni] = sbox_init_2 [ni]; m_sbox3 [ni] = sbox_init_3 [ni]; m_sbox4 [ni] = sbox_init_4 [ni]; } int nlen = bfkey.length; if (nlen == 0) {return; } int nkeypos = 0; int nbuild = 0; for (int ni = 0; ni <18; ni ++) {for (int nj = 0; nj <4; nj ++) {nbuild = nbuild << 8 | bfkey [nkeypos] & 0xff; if (++ nkeypos == nlen) {nkeypos = 0; }} m_pbox [ni] ^= nbuild; } Long lZero = 0l; for (int ni = 0; ni <18; ni += 2) {lZero = cifryptblock (lZero); m_pbox [ni] = (int) (lZero >>> 32); m_pbox [ni + 1] = (int) (lZero & 0xfffffffl); } para (int ni = 0; ni <256; ni += 2) {lZero = CiCryptBlock (lZero); m_sbox1 [ni] = (int) (lZero >>> 32); m_sbox1 [ni + 1] = (int) (lZero & 0xfffffffffl); } para (int ni = 0; ni <256; ni += 2) {lZero = CiCryptBlock (lZero); m_sbox2 [ni] = (int) (lZero >>> 32); m_sbox2 [ni + 1] = (int) (lZero & 0xfffffffffl); } para (int ni = 0; ni <256; ni += 2) {lZero = CiCryptBlock (lZero); m_sbox3 [ni] = (int) (lZero >>> 32); m_sbox3 [ni + 1] = (int) (lZero & 0xfffffffffl); } para (int ni = 0; ni <256; ni += 2) {lZero = CiCryptBlock (lZero); m_sbox4 [ni] = (int) (lZero >>> 32); m_sbox4 [ni + 1] = (int) (lZero & 0xfffffffl); }}} public Blowfish (contraseña de cadena) {MessageDigest Digest = null; intente {digest = messageDigest.getInstance ("sha1"); digest.update (contraseña.getBytes ()); } catch (excepción e) {log.error (e.getMessage (), e); } m_bfish = new BlowfishCBC (digest.digest (), 0l); digest.reset (); } public String CiCryPTString (String SplAintext) {Long lcbciv; sincronizado (m_rndgen) {lcbciv = m_rndgen.nextLong (); } return encstr (splactext, lcbciv); } private String encstr (string splAintext, long lNewcbciv) {int nstrlen = sprateRyext.length (); byte buf [] = nuevo byte [(nstrlen << 1 y -8) + 8]; int npos = 0; for (int ni = 0; ni <nstrlen; ni ++) {char cactchar = sprateNext.charat (ni); buf [Npos ++] = (byte) (cactchar >> 8 y 0xff); BUF [NPOS ++] = (BYTE) (CACTCHAR & 0XFF); } byte bpadval = (byte) (buf.length - (nstrlen << 1)); while (npos <buf.length) {buf [npos ++] = bpadval; } m_bfish.setcbciv (lnewcbciv); m_bfish.encrypt (BUF); byte newcbciv [] = new Byte [8]; Longtobytearray (lnewcbciv, newcbciv, 0); return bytestobinhex (newCbciv, 0, 8) + bytestobinhex (buf, 0, buf.length); } public String DecryptString (string sciphertext) {int nlen = sciphertext.length () >> 1 & -8; if (nlen <8) {return null; } byte cbciv [] = new Byte [8]; int nnumofbytes = binhextobytes (sciphertext, cbciv, 0, 0, 8); if (nnumofbytes <8) {return null; } m_bfish.setcbciv (CBCIV); if ((nlen -= 8) == 0) {return ""; } byte buf [] = new Byte [nlen]; nnumOfBytes = binhextobytes (sciphertext, buf, 16, 0, nlen); if (nnumofbytes <nlen) {return null; } m_bfish.decrypt (buf); int npadbyte = buf [buf.length - 1] & 0xff; if (npadbyte> 8 || npadbyte <0) {npadbyte = 0; } nnumofbytes -= npadbyte; if (nnumofbytes <0) {return ""; } else {return byteArrayToUncstring (buf, 0, nnumofbytes); }} public void destruye () {m_bfish.cleanup (); } private static long bytearraytolong (byte buffer [], int nstartIndex) {buffer de return (long) [nstartindex] << 56 | (Buffer [nstartindex + 1] y 255l) << 48 | (Buffer [nstartindex + 2] y 255l) << 40 | (Buffer [nstartindex + 3] y 255l) << 32 | (Buffer [nstartindex + 4] y 255l) << 24 | (Buffer [nstartindex + 5] y 255l) << 16 | (Buffer [nstartindex + 3] y 255l) << 32 | (Buffer [nstartindex + 4] y 255l) << 24 | (Buffer [nstartindex + 5] y 255l) << 16 | (Buffer [nstartindex + 6] y 255l) << 8 | búfer [nstartindex + 7] y 255L; } Void estático privado LongTobyTearray (Long Lvalue, byte buffer [], int nstartIndex) {buffer [nstartindex] = (byte) (int) (lvalue >>> 56); buffer [nstartindex + 1] = (byte) (int) (lvalue >>> 48 y 255L); buffer [nstartindex + 2] = (byte) (int) (lvalue >>> 40 y 255L); Buffer [nstartIndex + 3] = (byte) (int) (lvalue >>> 32 y 255L); buffer [nstartIndex + 4] = (byte) (int) (lvalue >>> 24 y 255L); buffer [nstartindex + 5] = (byte) (int) (lvalue >>> 16 y 255L); buffer [nstartindex + 6] = (byte) (int) (lvalue >>> 8 y 255L); buffer [nstartIndex + 7] = (byte) (int) lvalue; } private static long makelong (int nlo, int nhi) {return (long) nhi << 32 | nlo & 0xfffffffffl; } private static int longlo32 (long lval) {return (int) lval; } private static int longhi32 (long lval) {return (int) (lval >>> 32); } cadena estática privada bytestobinhex (byte data [], int nstartpos, int nnumOfBytes) {stringBuffer sbuf = new StringBuffer (); sbuf.setLength (nnumOfBytes << 1); int npos = 0; for (int ni = 0; ni <nnumofbytes; ni ++) {sbuf.setcharat (Npos ++, Hextab [Data [Ni+nStartPos] >> 4 & 0xf]); sbuf.setcharat (Npos ++, Hextab [Data [Ni+NStartPos] & 0xf]); } return sbuf.ToString (); } private static int binhextobytes (string sbinhex, byte data [], int nsrcpos, int ndstpos, int nnumofbytes) {int nstrlen = sbinhex.length (); int navailbytes = nstrlen - nsrcpos >> 1; if (navailbytes <nnumofbytes) {nnumOfBytes = NavailBytes; } int NoutputCapacity = data.length - ndstpos; if (nnumOfBytes> NoutputCapacity) {nnumOfBytes = noutputCapacity; } int nResult = 0; para (int ni = 0; ni <nnumofbytes; ni ++) {byte bactbyte = 0; boolean blconvertok = true; para (int nj = 0; nj <2; nj ++) {bactbyte << = 4; char cactchar = sbinhex.charat (NSRCPOS ++); if (cactchar> = 'a' && cactchar <= 'f') {bactbyte | = (byte) (cactchar - 97) + 10; continuar; } if (cactchar> = '0' && cactchar <= '9') {bactbyte | = (byte) (cactchar - 48); } else {blConvertok = false; }} if (cactchar> = '0' && cactchar <= '9') {bactbyte | = (byte) (cactchar - 48); } else {blConvertok = false; }} if (blconvertok) {data [ndstpos ++] = bactbyte; nResult ++; }} return nresult; } cadena estática privada byteArrayTounctring (Byte Data [], int nStartPos, int nnumOfBytes) {nnumOfBytes & = -2; int navailCapacity = data.length - nStartPos; if (NavailCapacity <nnumOfBytes) {nnumOfBytes = NavailCapacity; } StringBuffer sbuf = new StringBuffer (); sbuf.setLength (nnumofbytes >> 1); int nsbufpos = 0; para (; nnumofbytes> 0; nnumofbytes -= 2) {sbuf.setcharat (nsbufpos ++, (char) (data [nstartpos] << 8 | data [nstartpos+1] & 0xff)); nStartpos += 2; } return sbuf.ToString (); } Blow pecescbc privado m_bfish; privado estático aleatorio m_rndgen = new Random (); estático final char hextab [] = {'0', '1' ',' 2 ',' 3 ',' 4 ',' 5 ',' 6 ',' 7 ',' 8 ',' 9 ',' a ',' b ',' c ',' d ',' e ',' f '};};};};};};Resumir
Lo anterior es todo el contenido de este artículo sobre la implementación del código completo del algoritmo de cifrado Blowfish en el lenguaje Java. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo.