Data security management: RSA algorithm, signature verification process details

Keywords: Programming github xml encoding

Source code: GitHub point here || GitEE point here

I. Introduction to RSA algorithm

1. Encryption and decryption

RSA encryption is a kind of asymmetric encryption, which is widely used in public key encryption and electronic commerce. The encryption and decryption can be completed without passing the key directly. This can ensure the security of information and avoid the risk of disclosure caused by the direct transfer of key. It is a process of encryption and decryption by a pair of keys, which are called public key and private key respectively. The principle of the encryption algorithm is the difficulty of factoring a maximum integer to ensure the security.

2. Signature verification

Digital signature is to add an encrypted string which can't be forged to the source of information. This string is an effective proof of the authenticity of the source of information. This process is called signature and signature verification.

II. Scene description

  • Message sender: Party A, holding public key
  • Message receiver: Party B, holding private key

1. Encryption and decryption process

(1) Party B generates a pair of keys, i.e. public key and private key. The private key is not public, which is held by Party B itself. The public key is public and held by Party A.

(2) after receiving the encrypted message from Party A, Party B uses the private key to decrypt the message and obtain the clear text.

2. Signature verification process

(1) after receiving the message, Party B needs to reply to Party A, sign the reply message with the private key, and reply to Party A with the message clear text and message signature.

(2) after receiving the message, Party A shall use the public key for signature verification. If the result of signature verification is correct, it shall be proved that the message is replied by Party B.

III. source code implementation

1. Key string acquisition

  • code generation
private static HashMap<String, String> getTheKeys() {
    HashMap<String, String> keyPairMap = new HashMap<String, String>();
    KeyPairGenerator keyPairGen = null;
    try {
        keyPairGen = KeyPairGenerator.getInstance("RSA");
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    }
    // Key size: 1024 bits
    keyPairGen.initialize(1024);
    KeyPair keyPair = keyPairGen.generateKeyPair();
    String publicKey = printBase64Binary(keyPair.getPublic().getEncoded());
    String privateKey = printBase64Binary(keyPair.getPrivate().getEncoded());
    keyPairMap.put("publicKey", publicKey);
    keyPairMap.put("privateKey", privateKey);
    return keyPairMap ;
}
  • read file

file location

public static final String PUB_KEY = "rsaKey/public.key" ;
public static final String PRI_KEY = "rsaKey/private.key" ;

File loading

public static String getKey (String keyPlace) throws Exception {
    BufferedReader br= null;
    try {
        br= new BufferedReader(new InputStreamReader(RsaCryptUtil.class.getClassLoader().
                                                     getResourceAsStream(keyPlace)));
        String readLine= null;
        StringBuilder keyValue = new StringBuilder();
        while((readLine= br.readLine())!=null){
            if(!(readLine.charAt(0)=='-')){
                keyValue.append(readLine);
            }
        }
        return keyValue.toString();
    } catch (Exception e) {
        throw new Exception("RSA Key read error",e) ;
    } finally{
        if (br != null) {
            try {
                br.close();
            } catch (Exception e) {
                System.out.println("Key read stream shutdown exception");
            }
        }
    }
}

2. Public key and private key

  • Public key string generate public key
public static RSAPublicKey createPublicKey(String publicKeyValue) throws Exception {
    try {
        byte[] buffer = DatatypeConverter.parseBase64Binary(publicKeyValue);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
        return (RSAPublicKey) keyFactory.generatePublic(keySpec);
    } catch (Exception e) {
        throw new Exception("Public key creation failed", e);
    }
}
  • Private key string generate private key
public static RSAPrivateKey createPrivateKey(String privateKeyValue) throws Exception {
    try {
        byte[] buffer = javax.xml.bind.DatatypeConverter.parseBase64Binary(privateKeyValue);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
    } catch (Exception e) {
        throw new Exception("Private key creation failed", e);
    }
}

3. Encryption and decryption

  • Public key encryption
public static String encrypt(RSAPublicKey publicKey, byte[] clearData) throws Exception {
    if (publicKey == null) {
        throw new Exception("Encryption public key is empty, Unable to encrypt");
    }
    try {
        Cipher cipher = Cipher.getInstance("RSA") ;
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] output = cipher.doFinal(clearData);
        return printBase64Binary(output);
    } catch (Exception e) {
        throw new Exception("Public key encryption failed",e);
    }
}
  • Private key decryption
public static String decrypt(RSAPrivateKey privateKey, byte[] cipherData) throws Exception {
    if (privateKey == null) {
        throw new Exception("Decryption private key is empty, Unable to decrypt");
    }
    try {
        Cipher cipher = Cipher.getInstance("RSA") ;
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] output = cipher.doFinal(cipherData);
        return new String(output);
    } catch (BadPaddingException e) {
        throw new Exception("Private key decryption failed",e);
    }
}

4. Signature and signature verification

  • Private key signature
public static String sign (String signData, PrivateKey privateKey) throws Exception {
    byte[] keyBytes = privateKey.getEncoded();
    PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PrivateKey key = keyFactory.generatePrivate(keySpec);
    Signature signature = Signature.getInstance("MD5withRSA");
    signature.initSign(key);
    signature.update(signData.getBytes());
    return printBase64Binary(signature.sign());
}
  • Public key verification
public static boolean verify(String srcData, PublicKey publicKey, String sign) throws Exception {
    byte[] keyBytes = publicKey.getEncoded();
    X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
    KeyFactory keyFactory = KeyFactory.getInstance("RSA");
    PublicKey key = keyFactory.generatePublic(keySpec);
    Signature signature = Signature.getInstance("MD5withRSA");
    signature.initVerify(key);
    signature.update(srcData.getBytes());
    return signature.verify(parseBase64Binary(sign));
}

5. Encoding and decoding

/**
 * Byte array to character
 */
public static String printBase64Binary(byte[] bytes) {
    return DatatypeConverter.printBase64Binary(bytes);
}
/**
 * Character to byte array
 */
public static byte[] parseBase64Binary(String value) {
    return DatatypeConverter.parseBase64Binary(value);
}

6. Test code block

  • Key generation test
public static void testCreateKey () throws Exception {
    HashMap<String, String> map = RsaCryptUtil.getTheKeys();
    String privateKeyStr=map.get("privateKey");
    String publicKeyStr=map.get("publicKey");
    System.out.println("Private key:"+privateKeyStr);
    System.out.println("Public key:"+publicKeyStr);
    //message sender 
    String originData="cicada-smile";
    System.out.println("Original text:"+originData);
    String encryptData = RsaCryptUtil.encrypt(RsaCryptUtil.createPublicKey(publicKeyStr),
                                              originData.getBytes());
    System.out.println("Encryption:"+encryptData);
    //message receiver 
    String decryptData=RsaCryptUtil.decrypt(RsaCryptUtil.createPrivateKey(privateKeyStr),
                                            RsaCryptUtil.parseBase64Binary(encryptData));
    System.out.println("Decrypt:"+decryptData);
}
  • Key read test
public static void testReadKey () throws Exception {
    String value = getKey("rsaKey/public.key");
    System.out.println(value);
    String privateKeyStr = getKey(RsaCryptUtil.PRI_KEY) ;
    String publicKeyStr = getKey(RsaCryptUtil.PUB_KEY) ;
    //message sender 
    String originData="cicada-smile";
    System.out.println("Original text:"+originData);
    String encryptData = RsaCryptUtil.encrypt(RsaCryptUtil.createPublicKey(publicKeyStr),
                                              originData.getBytes());
    System.out.println("Encryption:"+encryptData);
    //message receiver 
    String decryptData=RsaCryptUtil.decrypt(RsaCryptUtil.createPrivateKey(privateKeyStr),
                                            RsaCryptUtil.parseBase64Binary(encryptData));
    System.out.println("Decrypt:"+decryptData);
}
  • Signature verification test
public static void testSignVerify () throws Exception {
    String signData = "cicada-smile" ;
    String privateKeyStr = getKey(RsaCryptUtil.PRI_KEY) ;
    String publicKeyStr = getKey(RsaCryptUtil.PUB_KEY) ;
    String signValue = sign(signData,RsaCryptUtil.createPrivateKey(privateKeyStr)) ;
    boolean flag = verify(signData,RsaCryptUtil.createPublicKey(publicKeyStr),signValue);
    System.out.println("original text:"+signData);
    System.out.println("autograph:"+signValue);
    System.out.println("Check sign:"+flag);
}

IV. source code address

GitHub·address
https://github.com/cicadasmile
GitEE·address
https://gitee.com/cicadasmile

Posted by mtombs on Sun, 20 Oct 2019 16:54:05 -0700