Algoritmo de cifrado RSA
Revisemos el algoritmo de cifrado de RSA. Utilizamos un lenguaje relativamente estandarizado para describir este algoritmo en función de la definición de algoritmo de cifrado de clave pública y algoritmo de firma.
El sistema de cifrado de clave pública RSA incluye los siguientes 3 algoritmos: Keygen (algoritmo de generación de claves), CiCrypt (CiCrypt) y Decrypt (algoritmo de descifrado).
El algoritmo de generación de claves utiliza una constante de seguridad como entrada para emitir una clave pública PK y una clave privada SK. La constante de seguridad se usa para determinar qué tan seguro es el algoritmo de cifrado, que generalmente está relacionado con el tamaño del número primo P utilizado por el algoritmo de cifrado. Cuanto mayor sea el número primo P, mayor es el sistema, asegurando una mayor seguridad. En RSA, el algoritmo de generación clave es el siguiente: el algoritmo primero genera aleatoriamente dos números primos grandes diferentes P y Q, y calcula N = PQ. Luego, el algoritmo calcula la función Euler. A continuación, el algoritmo selecciona aleatoriamente un entero menor que E y calcula el elemento inverso de módulo d de e. Finalmente, la clave pública es PK = (N, E) y la clave privada es SK = (N, D).
El algoritmo de cifrado utiliza la clave pública PK y el mensaje M se encriptará como entrada y emite el texto cifrado CT. En RSA, el algoritmo de cifrado es el siguiente: el algoritmo genera directamente el texto cifrado, ya que el algoritmo de descifrado utiliza la clave privada SK y CIPHERTEXT CT como entradas, y emite el mensaje M. En RSA, el algoritmo de descifrado es el siguiente: el algoritmo emite el texto de la plantilla directamente. Dado que E y D son inversamente opuestos entre sí, tenemos:
Por lo tanto, a partir de la descripción del algoritmo, también podemos ver que la clave pública se usa para cifrar los datos, y la clave privada se usa para descifrar los datos. Por supuesto, esto también se puede entender de manera intuitiva: una clave pública es una clave pública, y solo cuando se divulga, ¿pueden todos usarlo para cifrar datos? Una clave privada es una clave privada, y quien tenga esta clave puede descifrar el texto cifrado. De lo contrario, si todos pueden ver la clave privada y descifrarla, será un desastre.
Echemos un vistazo a la implementación simple en Java:
paquete com.stone.security; import java.security.keypair; import java.security.keypairgenerator; import java.security.privatekey; import java.security.publickey; importar java.util.arrays; import javax.crypto.cipher; / *** Algoritmo RSA Cifrado de cifrado público Cifrado asimétrico*/ clase pública RSA {public static static final string key_algorithm = "rsa"; Cadena final Public Static final cipher_algorithm_ecb1 = "rsa/ecb/pkcs1padding"; Cadena final Public Static final cipher_algorithm_ecb2 = "rsa/ecb/oaepwithsha-1andmgf1padding"; // No puede usar la cadena final estática pública cipher_algorithm_ecb3 = "oaepwithsha-256andmgf1padding"; // No puede usar estática PublicKey PublicKey; Key PRIVADA ESTÁTICA PRIVADO KEY; Cifrado estático; Keypair estático Keypair; public static void main (string [] args) lanza la excepción {método1 ("skoda u*(sfsad7f ()*^%% $"); método2 ("skoda u*(sfsad7f ()*^%% $"); método3 ("skoda u*(sfsad7f ()*^%% $");} /***clave pública clave CECLETA Cipher_algorithm_ecb1 * @param str * @throws excepción */ static void Method1 (string str) lanza la excepción {keyPairGenerator keyGenerator = keyyPairGenerator.getInstance (key_algorithm) CiMair.GetPrivate (); Arrays.tostring (encrypt)); Cipher_algorithm_ecb1 * @param str * @throws excepción */ static void método2 (string str) lanza la excepción {keyPairGenerator keyGenerator = keyPairGenerator.getInstance (key_algorithm); KeyPair keypair = keyGenerator.GenerateKeypair (); publickey = keypair.getPublic (); privateKey = keypair.getPrivate (); cipher = cipher.getInstance (key_algorithm); cipher.init (cipher.encrypt_mode, privateKey); // byte de cifrado de clave privada [] encrypt = cipher.dofinal (str.getbytes ()); System.out.println ("Cifrado de clave privada 2:" + arrays.toString (encrypt)); cipher.init (cipher.decrypt_mode, public key); // Public Key Decrypt Byte [] Decrypt = Cipher.Dofinal (CiCrypt); System.out.println ("Public Key Decrypt 2:" + New String (Decrypt)); }/** * Cifrado de clave privada, descifrado de clave pública utiliza cipher_algorithm_ecb1 = rsa/ecb/pkcs1padding * @param str * @throws excepción */static void método3 (string str) lanza excepción {keypairGenerator keyGenerator = keypairGenerator.getinstance (key_algorithm); KeyPair keypair = keyGenerator.GenerateKeypair (); publickey = keypair.getPublic (); privateKey = keypair.getPrivate (); cipher = cipher.getInstance (cipher_algorithm_ecb1); cipher.init (cipher.encrypt_mode, privateKey); // byte de cifrado de clave privada [] encrypt = cipher.dofinal (str.getbytes ()); System.out.println ("Cifrado de clave privada 3:" + Arrays.ToString (CiCrypt)); cipher.init (cipher.decrypt_mode, public key); // Byte de descifrado de clave pública [] Decrypt = cipher.dofinal (encrypt); System.out.println ("3 después del descifrado de la clave pública:" + nueva cadena (Decrypt)); }} Algoritmo DSA y firma digital
DSA se usa generalmente para firmas digitales y certificación.
DSA es una variante de los algoritmos de firma Schnorr y Elgamal, y es utilizado por NIST en los Estados Unidos como DSS (Estándar de firma digital).
DSA se basa en el problema logarítmico discreto de dominio finito entero, y su seguridad es similar a la RSA.
En la firma y autenticación digital DSA, el remitente usa su propia clave privada para firmar un archivo o mensaje, y el destinatario utiliza la clave pública del remitente para verificar la autenticidad de la firma después de recibir el mensaje. DSA es solo un algoritmo, y la diferencia entre RSA es que no se puede usar para el cifrado y el descifrado, ni para el intercambio de claves.
Solo para firmas, es mucho más rápido que RSA.
paquete com.stone.security; import java.security.key; import java.security.KeyFactory; import java.security.keypair; import java.security.keypairgenerator; import java.security.privatekey; import java.security.publickey; import java.security.secureurandom; import java.security.signature; import java.security.spec.pkcs8EncodedKeySpec; import java.security.spec.x509EncodedKeySpec; import java.util.hashmap; import java.util.map; import sun.misc.base64decoder; import sun.misc.base64Encoder; /*** El algoritmo de firma DSA-digital es una variante de los algoritmos de firma Schnorr y Elgamal, y es utilizado como DSS por NIST en los Estados Unidos. * En resumen, este es un método de verificación más avanzado utilizado como firma digital. No solo las claves públicas y privadas, sino también las firmas digitales. El cifrado de clave privada genera firmas digitales, datos de verificación de clave pública y firmas. * Si los datos y la firma no coinciden, ¡se considerará que la verificación está fallada! Es decir, los datos en la transmisión ya no se pueden encriptar. Después de que el receptor obtiene los datos, obtiene la clave pública y la firma para verificar si los datos son válidos. */ clase pública DSA {/ ***No solo puede usar el algoritmo DSA, sino que también puede usar el algoritmo RSA para firmas digitales*/ public static final String key_algorithm = "rsa"; Public static final String firature_algorithm = "md5withrsa";*/ public static final string key_algorithm = "dsa"; cadena final estática pública firma_algorithm = "dsa"; Public static final String Default_seed = "$%^*%^() (hjg8awfjas7"; // sembrada predeterminada static static string final public_key = "dsapublickey"; public static final string private_key = "dsaprivatekey"; public static static void main (string [] args) Exception {stry str = "!@#$#^$#&#& ZXVDF You*() _ + "; byte [] data = str.getBytes (); map <string, object> keyMap = initKey (); // construir clave publickey public keyke = (publickey) keyMap.get (public_key); privateKey privateKey = (privateKey) keyMap.get (private_key); system.println (" Formateo clave privado: " + keyke.getformat (getformat ());) System.out.println ("Formato de clave pública:" + publickey.getformat ()); Verify1); } / *** Genere la tecla** @param semilla semilla* @return objeto clave* @throws excepción* / public static map <string, object> initkey (string sement) lanza la excepción {system.out.println ("generar tecla"); KeyPairGenerator keygen = keyPairGenerator.getInstance (key_algorithm); Secureandom SecureRandom = new SecureRandom (); Securerandom.SetSeed (Seed.getBytes ()); // El tamaño del módulo debe variar de 512 a 1024 y ser un múltiplo de 64 keygen.initialize (640, SecureRandom); KeyPair Keys = KeyGen.GenKeyPair (); PrivateKey privateKey = Keys.getPrivate (); PublicKey PublicKey = Keys.getPublic (); Map <string, object> map = new HashMap <String, Object> (2); map.put (public_key, public key); map.put (private_key, privatekey); mapa de retorno; } / *** Genere la tecla predeterminada** @return Key Object* @throws Exception* / public static Map <String, Object> InitKey () lanza Exception {return initKey (default_seed); } / ** * Obtenga la clave privada * * @param keyMap * @return * @throws excepción * / public static string getPrivateKey (map <string, object> keyMap) lanza excepción {key = (key) keyMap.get (private_key); return CiCryPTBase64 (key.getEncoded ()); // Base64 Cifrado de cifrado Clave privada}/** * Obtenga la clave pública * * @param keymap * @return * @throws excepción */public static string getPublickey (map <string, object> keyMap) lanza excepción {key = (key) keyMap.get (public_key); return CiCryPTBase64 (key.getEncoded ()); // Base64 Cifrado de cifrado clave}/** * Use la clave privada para firmar digitalmente la información * @param Datos Datos cifrados * @param PrivateKey Private Key - Base64 cifrado * @return * @throws Exception */public static String Sign (byte [] String PrivateKey) Lanza la excepción {System.Println ("Digitize la información con la clave privada"); byte [] keyBytes = Decryptbase64 (privateKey); PKCS8EncodedKeySpec KeySpec = new PKCS8EncodedKeySpec (KeyBytes); KeyFactory factory = keyFactory.getInstance (key_algorithm); PrivateKey prikeY = factory.GeneratePrivate (KeySpec); // Generar clave privada // información de señalización de dígitos con firma de clave privada firma = firma.getInstance (firma_algorithm); Signature.initsign (prikey); firma.update (datos); return encryptbase64 (firma.sign ()); } / *** Cifrado de Base64Encoder* @param Data Data para estar encriptados* @return encrypted String* / private static string encryptbase64 (byte [] data) {Base64Encoder Encoder = new Base64Encoder (); String codeDe = encoder.encode (datos); devolver la codificación; } / *** Base64Decoder Decrypt* @param La cadena de datos para descifrar* @return descifrado byte []* @throws excepción* / private static byte [] Decryptbase64 (string data) lanza excepción {base64decoder decoder = new Base64Decoder (); byte [] buffer = decoder.decodeBuffer (datos); buffer de retorno; } / *** Verifique la firma digital* @param datos cifrados de datos* @param public keyk* @param firma digital firma* @return* @throws excepción* / public static boolean verify (byte [] data, string publickey, string firma) lanza la excepción {byte [] keybytes = DecryptBase64 (publickey); X509CodedKeySpec KeySpec = new X509EncodedKeySpec (KeyBytes); KeyFactory KeyFactory = KeyFactory.GetInstance (key_algorithm); PublicKey PubKey = KeyFactory.GeneratePublic (KeySpec); Signature Signature = Signature.getInstance (firature_algorithm); Signature.initverify (PubKey); firma.update (datos); devolver firma.verify (DecryptBase64 (signo)); // Verificar firma}}