OAEPWithSHA-512AndMGF1Padding

基于PKCS#1 V2.1规范的OAEPWithSHA-512AndMGF1Padding算法实现

java中可以直接使用RSA/ECB/OAEPWithSHA-512AndMGF1Padding来完成公钥加密数据。

例如:

	public static byte[] encode(byte[] data) throws Exception
	{
		byte[] keyBytes = Base64Utils.getFromBASE64(key);

		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		Key publicKey = keyFactory.generatePublic(x509KeySpec);

		Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-512AndMGF1Padding");
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);

		return cipher.doFinal(data);
	}


其他语言与java语言对接时,可以参考如下填充算法实现过程:

package com.matrix.cipher;

public abstract class Base64Utils
{
	public static String encode(byte[] btData)
	{
		int iLen = 0;
		boolean l_bFlag;
		int l_iGroup;
		char[] l_szData;
		byte[] l_btTmp;

		int ii;
		int jj;
		int kk;

		String l_stEncoding = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

		if (btData == null)
		{
			return null;
		}

		if ((iLen <= 0) || (iLen > btData.length))
		{
			iLen = btData.length;
		}

		l_bFlag = ((iLen % 3) == 0);

		l_iGroup = iLen / 3;

		ii = l_iGroup;

		if (!l_bFlag)
		{
			ii++;
		}

		l_szData = new char[4 * ii];
		l_btTmp = new byte[3];

		for (ii = 0, jj = 0, kk = 0; ii < l_iGroup; ii++)
		{
			l_btTmp[0] = btData[kk++];
			l_btTmp[1] = btData[kk++];
			l_btTmp[2] = btData[kk++];

			l_szData[jj++] = l_stEncoding.charAt((l_btTmp[0] >> 2) & 0x3F);
			l_szData[jj++] = l_stEncoding.charAt(((l_btTmp[0] & 0x03) << 4)
					| ((l_btTmp[1] >> 4) & 0x0F));
			l_szData[jj++] = l_stEncoding.charAt(((l_btTmp[1] & 0x0F) << 2)
					| ((l_btTmp[2] >> 6) & 0x03));
			l_szData[jj++] = l_stEncoding.charAt(l_btTmp[2] & 0x3F);
		}

		if (!l_bFlag)
		{
			l_btTmp[0] = btData[kk++];

			l_szData[jj++] = l_stEncoding.charAt((l_btTmp[0] >> 2) & 0x3F);
			l_szData[jj + 1] = '=';
			l_szData[jj + 2] = '=';

			if ((iLen % 3) == 1)
			{
				l_szData[jj] = l_stEncoding.charAt((l_btTmp[0] & 0x03) << 4);
			}
			else
			// if ((iLen % 3) == 2)
			{
				l_btTmp[1] = btData[kk];

				l_szData[jj++] = l_stEncoding.charAt(((l_btTmp[0] & 0x03) << 4)
						| ((l_btTmp[1] >> 4) & 0x0F));
				l_szData[jj] = l_stEncoding.charAt((l_btTmp[1] & 0x0F) << 2);
			}
		}

		return new String(l_szData);
	}

	public static byte[] getFromBASE64(String stData)
	{
		if (null == stData || stData.trim().isEmpty())
		{
			return null;
		}
		int l_iLen;
		int l_iGroup;
		int ii;
		int jj;
		int kk;
		boolean l_bFlag;
		char[] l_szTmp;
		byte[] l_btData = new byte[0];

		l_iLen = stData.length();

		if ((l_iLen % 4) != 0)
		{
			return l_btData;
		}

		l_iGroup = l_iLen / 4;
		ii = l_iGroup * 3;
		l_bFlag = true;
		l_szTmp = new char[4];

		if (stData.charAt(l_iLen - 1) == '=')
		{
			l_iLen--;
			ii--;
			l_iGroup--;

			l_bFlag = false;

			if (stData.charAt(l_iLen - 1) == '=')
			{
				l_iLen--;
				ii--;
			}
		}

		for (jj = 0; jj < l_iLen; jj++)
		{
			l_szTmp[0] = stData.charAt(jj);

			if (!((l_szTmp[0] == '+')
					|| (('/' <= l_szTmp[0]) && (l_szTmp[0] <= '9'))
					|| (('A' <= l_szTmp[0]) && (l_szTmp[0] <= 'Z')) || (('a' <= l_szTmp[0]) && (l_szTmp[0] <= 'z'))))
			{
				return l_btData;
			}
		}

		l_btData = new byte[ii];

		for (ii = 0, jj = 0, kk = 0; ii < l_iGroup; ii++)
		{
			l_szTmp[0] = returnToData(stData.charAt(kk++));
			l_szTmp[1] = returnToData(stData.charAt(kk++));
			l_szTmp[2] = returnToData(stData.charAt(kk++));
			l_szTmp[3] = returnToData(stData.charAt(kk++));

			l_btData[jj++] = (byte) ((l_szTmp[0] << 2) | ((l_szTmp[1] >> 4) & 0x03));
			l_btData[jj++] = (byte) ((l_szTmp[1] << 4) | ((l_szTmp[2] >> 2) & 0x0F));
			l_btData[jj++] = (byte) ((l_szTmp[2] << 6) | (l_szTmp[3] & 0x3F));
		}

		if (!l_bFlag)
		{
			l_szTmp[0] = returnToData(stData.charAt(kk++));
			l_szTmp[1] = returnToData(stData.charAt(kk++));

			l_btData[jj++] = (byte) ((l_szTmp[0] << 2) | ((l_szTmp[1] >> 4) & 0x03));

			if ((l_iLen % 4) == 3)
			{
				l_szTmp[2] = returnToData(stData.charAt(kk));

				l_btData[jj] = (byte) ((l_szTmp[1] << 4) | ((l_szTmp[2] >> 2) & 0x0F));
			}
		}

		return l_btData;
	}

	private static char returnToData(char cChar)
	{
		if (('A' <= cChar) && (cChar <= 'Z'))
		{
			cChar -= 'A';
		}
		else if (('a' <= cChar) && (cChar <= 'z'))
		{
			cChar -= 'a';
			cChar += 26;
		}
		else if (('0' <= cChar) && (cChar <= '9'))
		{
			cChar -= '0';
			cChar += 52;
		}
		else if (cChar == '+')
		{
			cChar = 62;
		}
		else
		// if (cChar == '/')
		{
			cChar = 63;
		}

		return cChar;
	}
}



package com.matrix.cipher;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class SHAUtils
{
	/**
	 * @param strSrc
	 * @param encName
	 *            :SHA-1;SHA-256;SHA-512;
	 * @return
	 */
	public static byte[] encrypt(String strSrc, String encName)
	{
		MessageDigest md = null;
		byte[] encode = null;

		try
		{
			byte[] bt = strSrc.getBytes("UTF-8");
			md = MessageDigest.getInstance(encName);
			md.update(bt);
			encode = md.digest();
		}
		catch (NoSuchAlgorithmException e)
		{
			return null;
		}
		catch (UnsupportedEncodingException e)
		{
			return null;
		}
		return encode;
	}

	public static byte[] encryptSHA1(String strSrc)
	{
		return encrypt(strSrc, "SHA-1");
	}

	public static byte[] encryptSHA256(String strSrc)
	{
		return encrypt(strSrc, "SHA-256");
	}

	public static byte[] encryptSHA512(String strSrc)
	{
		return encrypt(strSrc, "SHA-512");
	}

}



package com.matrix.cipher;

import java.security.MessageDigest;

/**
 * 掩模生成函数
 * mask generator function, as described in PKCS1v2.
 */
public class MGF1
{
	private MessageDigest digest;

	/**
	 * Create a version of MGF1 for the given digest.
	 * 
	 * @param digest
	 *            digest to use as the basis of the function.
	 */
	public MGF1(MessageDigest digest)
	{
		this.digest = digest;
	}

	/**
	 * int to octet string.
	 */
	private void I2OSP(int i, byte[] sp)
	{
		sp[0] = (byte) (i >>> 24);
		sp[1] = (byte) (i >>> 16);
		sp[2] = (byte) (i >>> 8);
		sp[3] = (byte) (i >>> 0);
	}

	/**
	 * Generate the mask.
	 * 
	 * @param seed
	 *            source of input bytes for initial digest state
	 * @param length
	 *            length of mask to generate
	 * 
	 * @return a byte array containing a MGF1 generated mask
	 */
	public byte[] generateMask(byte[] seed, int length)
	{
		byte[] mask = new byte[length];
		byte[] C = new byte[4];
		int counter = 0;
		int hLen = digest.getDigestLength();
		digest.reset();
		while (counter < (length / hLen))
		{
			I2OSP(counter, C);
			digest.update(seed);
			digest.update(C);
			System.arraycopy(digest.digest(), 0, mask, counter * hLen, hLen);

			counter++;
		}
		if ((counter * hLen) < length)
		{
			I2OSP(counter, C);
			digest.update(seed);
			digest.update(C);
			System.arraycopy(digest.digest(), 0, mask, counter * hLen,
					mask.length - (counter * hLen));
		}
		return mask;
	}
}



package com.matrix.cipher;

import java.math.BigInteger;
import java.security.KeyFactory;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;

import javax.crypto.Cipher;

/**
 * @author Matrix
 *
 */
public class RSA2048Utils
{
	public static final String ALGORITHM = "RSA";

	private static String RSA_TRANSFORMATION = "RSA/ECB/NoPadding";
	
	/**
	 * 首先要取得公钥,并使用setPublicKey方法来初始化变量key
	 */
	public static String key;

	public static byte[] encode(byte[] data) throws Exception
	{
		byte[] keyBytes = Base64Utils.getFromBASE64(key);

		X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
		KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
		RSAPublicKey publicKey = (RSAPublicKey) keyFactory
				.generatePublic(x509KeySpec);

		Cipher cipher = Cipher.getInstance(RSA_TRANSFORMATION);
		cipher.init(Cipher.ENCRYPT_MODE, publicKey);

		byte[] EM = OAEPWithSHA512AndMGF1Padding(data, publicKey);
		return cipher.doFinal(EM);
	}

	private static byte[] OAEPWithSHA512AndMGF1Padding(byte[] data,
			RSAPublicKey publicKey) throws Exception
	{
		byte[] lHash = SHAUtils.encrypt("", "SHA-512");
		
		byte[] ps = new byte[publicKey.getModulus().bitLength() / 8
				- data.length - 2 * lHash.length - 2];
		for (int i = 0; i < ps.length; i++)
		{
			ps[i] = 0;
		}

		byte[] DB = new byte[publicKey.getModulus().bitLength() / 8
				- lHash.length - 1];
		System.arraycopy(lHash, 0, DB, 0, lHash.length);
		System.arraycopy(ps, 0, DB, lHash.length, ps.length);
		DB[lHash.length + ps.length] = 1;
		System.arraycopy(data, 0, DB, lHash.length + ps.length + 1, data.length);

		byte[] seed = SecureRandom.getSeed(lHash.length);

		MGF1 mgf1 = new MGF1(MessageDigest.getInstance("SHA-1"));
		byte[] dbMask = mgf1.generateMask(seed, publicKey.getModulus()
				.bitLength() / 8 - lHash.length - 1);

		// DB和dbMask做异或运算生成maskedDB
		byte[] maskedDB = new BigInteger(DB).xor(new BigInteger(dbMask))
				.toByteArray();

		byte[] seedMask = mgf1.generateMask(maskedDB, lHash.length);

		// seed和seedMask做异或运算生成maskedSeed
		byte[] maskedSeed = new BigInteger(seed).xor(new BigInteger(seedMask))
				.toByteArray();

		byte[] EM = new byte[publicKey.getModulus().bitLength() / 8];
		EM[0] = 0;
		System.arraycopy(maskedSeed, 0, EM, 1, maskedSeed.length);
		System.arraycopy(maskedDB, 0, EM, maskedSeed.length + 1,
				maskedDB.length);
		
		return EM;
	}

	
	/**
	 * @param key
	 */
	public static void setPublicKey(String key)
	{
		RSA2048Utils.key = key;
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值