`
lgd_java2eye
  • 浏览: 189530 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

银联生成ARQC,ARPC,MAC,CVN生成

 
阅读更多

针对银联生成ARQC,ARPC,还有MAC进行了软加密实现,一般的银行都是进行调用加密机实现,为了方便测试使用自己对其进行了软加密算法实现:

 

基本帮助类如下:

package com.omini.common.utils;

import java.nio.ByteBuffer;
import java.util.Arrays;

/**
 * @author sandy
 * @version $Revision: 1.1 $ 建立日期 2012-9-11
 */
public class StringUtils
{

	/**
	 * 抽取字符或是数字 若isNumber传入true则表示抽取数字,false则表示抽取字符
	 * 
	 * @param result
	 * @param isNumber
	 * @return
	 */
	public static String extract(String result, boolean isNumber)
	{
		if (null == result || result.equals("") || result.length() == 0)
		{
			throw new IllegalArgumentException("参数不正确,不能为空!");
		}
		StringBuffer resultBuffer = new StringBuffer();

		char[] chars = result.toUpperCase().toCharArray();

		for (char c : chars)
		{
			boolean flag = Character.isDigit(c);

			if (isNumber && flag)
			{
				resultBuffer.append(c);
			}

			if (!flag && !isNumber)
			{
				resultBuffer.append(c);
			}

		}
		return resultBuffer.toString();

	}

	/**
	 * 减去10
	 * 
	 * @param input
	 * @return
	 */
	public static String divide(String input)
	{

		if (null == input || input.equals("") || input.length() == 0)
		{
			throw new IllegalArgumentException("参数不正确,不能为空!");
		}

		char[] output = new char[input.length()];

		for (int i = 0; i < input.length(); i++)
		{
			if (output[i] > 96)
			{
				output[i] = (char) (output[i] - 49);

			} else if (output[i] > 64)
			{

				output[i] = (char) (output[i] - 17);

			} else
			{
				output[i] = output[i];
			}
		}
		return Arrays.toString(output);
	}

	/**
	 * 追加字符到指定长度的字符
	 * 
	 * @param srcData
	 *            :原数据
	 * @param alignMode
	 *            :对齐方式
	 * @param paddCharacter
	 *            :填补的字符
	 * @param totalLen
	 *            :填充到的长度
	 * @return
	 */
	public static String padding(String srcData, String alignMode, String paddCharacter, int totalLen)
	{

		if (srcData == null || null == alignMode || null == paddCharacter || totalLen == 0)
		{
			throw new IllegalArgumentException("传入的数据不能为空或0,请检查数据!");
		}

		int paddLen = totalLen - srcData.length();

		StringBuffer paddResultBuffer = new StringBuffer();

		if (alignMode.equalsIgnoreCase("left"))
		{
			for (int i = 0; i < paddLen; i++)
			{
				paddResultBuffer.append(paddCharacter);
			}
			paddResultBuffer.append(srcData);
		} else if (alignMode.equalsIgnoreCase("right"))
		{
			paddResultBuffer.append(srcData);
			for (int i = 0; i < paddLen; i++)
			{
				paddResultBuffer.append(paddCharacter);
			}

		} else
		{
			throw new IllegalArgumentException("paddAlign  is not left or right,please check !");
		}

		return paddResultBuffer.toString();
	}

	/**
	 * 两个数据进行异或操作
	 * 
	 * @param hexSrcData1
	 *            :32CB95B36D89477C
	 * @param hexSrcData2
	 *            :3030000000000000
	 * @return
	 */
	public static String XOR(String hexSrcData1, String hexSrcData2)
	{

		if (hexSrcData1.length() != hexSrcData2.length())
		{
			throw new IllegalArgumentException("异或的两个数据长度不相等,请检查数据!");
		}

		byte[] bytes1 = HexBinary.decode(hexSrcData1);

		byte[] bytes2 = HexBinary.decode(hexSrcData2);

		ByteBuffer buffer = ByteBuffer.allocate(bytes2.length);

		for (int i = 0; i < bytes2.length; i++)
		{
			byte temp = (byte) ((int) bytes1[i] ^ (int) bytes2[i]);
			buffer.put(temp);
		}

		return HexBinary.encode(buffer.array());
	}

	/**
	 * 按位取反操作
	 * 
	 * @param hexSrcData
	 * @return
	 */
	public static String reversBytes(String hexSrcData)
	{
		if (null == hexSrcData || hexSrcData.equals("") || hexSrcData.length() == 0)
		{
			throw new IllegalArgumentException("非法的按位取反的数据,请检查数据");
		}

		byte[] srcBytes = HexBinary.decode(hexSrcData);

		ByteBuffer destBuffer = ByteBuffer.allocate(srcBytes.length);

		for (int i = 0; i < srcBytes.length; i++)
		{

			byte temp = (byte) (~(int) srcBytes[i]);

			destBuffer.put(temp);
		}

		return HexBinary.encode(destBuffer.array());
	}

}

 

package com.omini.common.utils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author sandy
 * @version $Revision: 1.1 $ 建立日期 2012-9-11
 */
public class DESUtils
{

	/**
	 * DES加密数据非填充方式
	 * 
	 * @param hexKey
	 * @param hexData
	 * @param mode
	 * @return
	 * @throws Exception
	 */
	public static String decEncNoPaddingDES(String hexKey, String hexData, int mode) throws Exception
	{
		SecretKey desKey = new SecretKeySpec(HexBinary.decode(hexKey), "DES/ECB/NoPadding");

		Cipher cp = Cipher.getInstance("DES/ECB/NoPadding");
		cp.init(mode, desKey);
		byte[] bytes = cp.doFinal(HexBinary.decode(hexData));

		return HexBinary.encode(bytes);
	}

	public static String encrypt(String hexKey, String hexData) throws Exception
	{
		SecretKey desKey = new SecretKeySpec(HexBinary.decode(hexKey), "DES");

		Cipher cp = Cipher.getInstance("DES");
		cp.init(Cipher.ENCRYPT_MODE, desKey);
		byte[] bytes = cp.doFinal(HexBinary.decode(hexData));

		return HexBinary.encode(bytes);
	}

	/**
	 * 3Des加密非填充
	 * 
	 * @param hexKey
	 * @param hexData
	 * @return
	 * @throws Exception
	 */
	public static String encryptDesSede(String hexKey, String hexData) throws Exception
	{
		SecretKey desKey = new SecretKeySpec(HexBinary.decode(hexKey), "DESede/ECB/NoPadding");

		Cipher cp = Cipher.getInstance("DESede/ECB/NoPadding");
		cp.init(Cipher.ENCRYPT_MODE, desKey);
		byte[] bytes = cp.doFinal(HexBinary.decode(hexData));

		return HexBinary.encode(bytes);
	}

}

 

package com.omini.common.utils;

/**
 * @author sandy
 * @version $Revision: 1.1 $ 建立日期 2012-9-11
 */
public class HexBinary
{

	/**
	 * Creates a clone of the given byte array.
	 */
	public static byte[] getClone(byte[] pHexBinary)
	{
		byte[] result = new byte[pHexBinary.length];
		System.arraycopy(pHexBinary, 0, result, 0, pHexBinary.length);
		return result;
	}

	/**
	 * Converts the string <code>pValue</code> into an array of hex bytes.
	 */
	public static byte[] decode(String pValue)
	{
		if ((pValue.length() % 2) != 0)
		{
			throw new IllegalArgumentException("A HexBinary string must have even length.");
		}
		byte[] result = new byte[pValue.length() / 2];
		int j = 0;
		for (int i = 0; i < pValue.length();)
		{
			byte b;
			char c = pValue.charAt(i++);
			char d = pValue.charAt(i++);
			if (c >= '0' && c <= '9')
			{
				b = (byte) ((c - '0') << 4);
			} else if (c >= 'A' && c <= 'F')
			{
				b = (byte) ((c - 'A' + 10) << 4);
			} else if (c >= 'a' && c <= 'f')
			{
				b = (byte) ((c - 'a' + 10) << 4);
			} else
			{
				throw new IllegalArgumentException("Invalid hex digit: " + c);
			}
			if (d >= '0' && d <= '9')
			{
				b += (byte) (d - '0');
			} else if (d >= 'A' && d <= 'F')
			{
				b += (byte) (d - 'A' + 10);
			} else if (d >= 'a' && d <= 'f')
			{
				b += (byte) (d - 'a' + 10);
			} else
			{
				throw new IllegalArgumentException("Invalid hex digit: " + d);
			}
			result[j++] = b;
		}
		return result;
	}

	/**
	 * Converts the byte array <code>pHexBinary</code> into a string.
	 */
	public static String encode(byte[] pHexBinary)
	{
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < pHexBinary.length; i++)
		{
			byte b = pHexBinary[i];
			byte c = (byte) ((b & 0xf0) >> 4);
			if (c <= 9)
			{
				result.append((char) ('0' + c));
			} else
			{
				result.append((char) ('A' + c - 10));
			}
			c = (byte) (b & 0x0f);
			if (c <= 9)
			{
				result.append((char) ('0' + c));
			} else
			{
				result.append((char) ('A' + c - 10));
			}
		}
		return result.toString();
	}

	public static void main(String[] args)
	{
		String a = "12";
		System.out.println(encode(a.getBytes()));
		String ab = "00000000000100000000000001560000000000015611041501112233447C00000603A00002";
		System.out.println("::::::::::[" + HexBinary.encode(ab.getBytes()) + "]");
	}

}

 

package com.omini.common.utils;

import javax.crypto.Cipher;

/**
 * 生成ARQC,ARPC,MAC,CVN,CVN2工具类
 * 
 * @author sandy
 * @version $Revision: 1.1 $ 建立日期 2012-9-11
 */
public class UnionUtils
{

	/**
	 * 其实生成ARQC就是调用的生成MAC方法,只不过MAC值是取得的前4个字节的值
	 * 
	 * @param pan
	 * @param panSN
	 * @param hexATC
	 * @param mainKey
	 * @param arqcDataSource
	 * @return
	 * @throws Exception
	 */
	public static String generateARQC(String pan, String panSN, String hexATC, String mainKey, String arqcDataSource) throws Exception
	{

		if (null == mainKey || mainKey.length() != 32)
		{
			throw new IllegalArgumentException("非法的工作主密钥的值");
		}

		if (pan == null || pan.equals("") || pan.length() == 0)
		{
			throw new IllegalArgumentException("卡号不能为空,请检查传入的卡号");
		}

		String processKey = generateProcesKey(pan, panSN, hexATC, mainKey);

		String result = process(processKey, arqcDataSource);

		if (result.length() != 16)
		{
			throw new IllegalArgumentException("返回的mac结果非8字节(16位hex)");
		}
		return result;
	}

	/**
	 * 根据ARQC来生成ARPC
	 * 
	 * @param hexArqc表示ARQC的值8字节
	 * @param pan
	 *            :表示卡号
	 * @param panSN
	 *            :表示卡序号00或01
	 * @param hexATC
	 *            :交易记数器
	 * @param mainKey
	 *            :工作主密钥
	 * @param authCode
	 *            :授权响应码2个字节
	 * @return
	 * @throws Exception
	 */

	public static String generateARPC(String hexArqc, String pan, String panSN, String hexATC, String mainKey, String authCode) throws Exception
	{

		if (null == mainKey || mainKey.length() != 32)
		{
			throw new IllegalArgumentException("非法的工作主密钥的值");
		}
		if (pan == null || pan.equals("") || pan.length() == 0)
		{
			throw new IllegalArgumentException("卡号不能为空,请检查传入的卡号");
		}

		if (hexArqc == null || hexArqc.equals("") || pan.length() == 0 || hexArqc.length() != 16)
		{
			throw new IllegalArgumentException("非法的ARQC数据");
		}

		String processKey = generateProcesKey(pan, panSN, hexATC, mainKey);

		String paddARC = StringUtils.padding(authCode, "right", "0", 16);

		String arqcAndARCXORResult = StringUtils.XOR(hexArqc, paddARC);

		String arpc = DESUtils.encryptDesSede(processKey, arqcAndARCXORResult);

		System.out.println(arpc);

		return arpc;
	}

	/**
	 * 生成MAC,并获取计算后的前4个字节 命令中需要加密的数据加密以后再计算MAC。MAC使用对称密钥算法计算的, 步骤如下: 步骤1:初始值为8
	 * 字节全零(此步骤可省略); 步骤2:下列数据按顺序排列得到一个数据块D: ——CLA、INS、P1、P2 和Lc(Lc 的长度包括MAC
	 * 的长度); ——ATC(对于发卡行脚本处理,此ATC 在请求中报文中上送);
	 * ——应用密文(对于发卡行脚本处理,此应用密文通常是ARQC,或AAC,在请求报文中上送); ——命令数据域中的明文或密文数据(如果存在)。
	 * 步骤3:将上述数据块D 分成8 字节长的数据块D1、D2、D3…最后一块数据块的字节长度为1 到8; 步骤4:如果最后一块数据块的长度为8
	 * 字节,后面补8 字节数据块:80 00 00 00 00 00 00 00, 执行步骤5; 如果最后一块数据块的长度小于8
	 * 字节,后面补一个字节80,如果长度到8 字节,执行 步骤5。如果仍然不够8 字节,补00 直到8 字节; 步骤5:用MAC
	 * 过程密钥对数据块进行加密。MAC 过程密钥的生成见C.4; 图C.1 是使用MAC 过程密钥A 和B 生成MAC 的流程图。 步骤6:MAC
	 * 的计算结果为8 字节,从最左边的字节开始取4 字节
	 * 
	 * @param pan
	 * @param panSN
	 * @param hexATC
	 * @param mainKey
	 * @param macDataSource
	 * @return
	 * @throws Exception
	 */

	public static String generateMAC(String pan, String panSN, String hexATC, String mainKey, String macDataSource) throws Exception
	{

		if (null == mainKey || mainKey.length() != 32)
		{
			throw new IllegalArgumentException("非法的工作主密钥的值");
		}

		if (pan == null || pan.equals("") || pan.length() == 0)
		{
			throw new IllegalArgumentException("卡号不能为空,请检查传入的卡号");
		}

		String processKey = generateProcesKey(pan, panSN, hexATC, mainKey);

		String result = process(processKey, macDataSource);

		if (result.length() != 16)
		{
			throw new IllegalArgumentException("返回的mac结果非8字节(16位hex)");
		}

		result = result.substring(0, 8);

		return result;
	}

	/**
	 * 计算CVN时使用二个64位的验证密钥,KeyA和KeyB。 a) 计算CVN 的数据源包括:
	 * 主账号(PAN)、卡失效期和服务代码,从左至右顺序编排。 例如19位PAN、4位卡失效期和3位服务代码组成26个字符CVN数据源。 b)
	 * 将上述数据源扩展成128 位二进制数据(不足128 位右补二进制0)。 c) 将128 位二进制数据分成两个64 位的数据块。最左边的64
	 * 位为Block1,最右边的64 位为 Block2。 d) 使用KeyA 对Block1 进行加密。 e) 将Block1
	 * 的加密结果与Block2 进行异或。使用KeyA 对异或结果进行加密。 f) 使用KeyB 对加密结果进行解密。 g) 使用KeyA
	 * 对解密结果进行加密。 h) 从左至右将加密结果中的数字(0-9)抽出,组成一组数字。 i) 从左至右将加密结果中的字符(A-F)抽出,减10
	 * 后将余数组成一组数字,排列在步骤(8) 的数字之后。 j) 步骤(9)的左边第一组三位数即为CVN 值
	 * 
	 * @param pan
	 * @param invalidDate
	 * @param serviceCode
	 * @param hexKey:验证密钥
	 * @return
	 * @throws Exception
	 */
	public static String generateCVN(String pan, String invalidDate, String serviceCode, String hexKey) throws Exception
	{

		if (null == pan || null == invalidDate || null == serviceCode || null == hexKey)
		{
			throw new IllegalArgumentException("卡号或是失效日期或服务代码或验证密钥为空!");
		}

		if (hexKey.length() != 32)
		{
			throw new IllegalArgumentException("验证密钥长度非32位!");
		}

		String keyA = hexKey.substring(0, 16);

		String keyB = hexKey.substring(16);

		StringBuffer cvnDataSource = new StringBuffer();

		cvnDataSource.append(pan).append(invalidDate).append(serviceCode);

		String cvnDS = StringUtils.padding(cvnDataSource.toString(), "right", "0", 32);

		String blockA = cvnDS.substring(0, 16);

		String blockB = cvnDS.substring(16);

		String keyAEncryptBlockAResult = DESUtils.decEncNoPaddingDES(keyA, blockA, Cipher.ENCRYPT_MODE);

		String xorBlockBResult = StringUtils.XOR(keyAEncryptBlockAResult, blockB);

		String result = DESUtils.decEncNoPaddingDES(keyA, xorBlockBResult, Cipher.ENCRYPT_MODE);

		result = DESUtils.decEncNoPaddingDES(keyB, result, Cipher.DECRYPT_MODE);

		result = DESUtils.decEncNoPaddingDES(keyA, result, Cipher.ENCRYPT_MODE);

		String numberData = StringUtils.extract(result, true);

		String characterData = StringUtils.extract(result, false);

		characterData = StringUtils.divide(characterData);

		result = numberData + characterData;

		if (result.length() < 3)
		{
			throw new IllegalArgumentException("计算CVN返回的长度小于3位长度不正确");
		}

		result = result.substring(0, 3);

		return result;
	}
	
	/**
	 * 印刷在签名条的右上方处并放在卡号(后4位)后
	 * 
	 * 生成CVN2其实就是把服务码变成常数000即可
	 * 
	 * @param pan:卡号
	 * @param invalidDate:失效日期
	 * @param serviceCode:服务码
	 * @param hexKey:验证密钥
	 * @return
	 * @throws Exception
	 */
	public static String generateCVN2(String pan, String invalidDate, String serviceCode, String hexKey) throws Exception
	{

		return generateCVN(pan,invalidDate,"000",hexKey);
	}
	

	/**
	 * 生成过程密钥
	 * 
	 * @param pan
	 * @param panSN
	 * @param hexATC
	 * @param mainKey
	 * @return
	 * @throws Exception
	 */
	private static String generateProcesKey(String pan, String panSN, String hexATC, String mainKey) throws Exception
	{
		int cardNoLength = pan.length();

		String cardNoRight14 = pan.substring(cardNoLength - 14);

		// 分散因子
		String dispersionFactor = cardNoRight14 + panSN;

		// 对分散因子取反
		String reversDispersionFactor = StringUtils.reversBytes(dispersionFactor);

		StringBuffer dispersionBuffer = new StringBuffer();

		dispersionBuffer.append(dispersionFactor).append(reversDispersionFactor);

		// 生成子密钥
		String subKey = DESUtils.encryptDesSede(mainKey, dispersionBuffer.toString());

		String paddATC = StringUtils.padding(hexATC, "left", "0", 16);

		String reversATC = StringUtils.reversBytes(hexATC);

		String paddReversATC = StringUtils.padding(reversATC, "left", "0", 16);

		String mergerATC = paddATC + paddReversATC;

		// 生成过程密钥
		String processKey = DESUtils.encryptDesSede(subKey, mergerATC);

		return processKey;
	}

	/**
	 * 计算MAC处理
	 * 
	 * @param processKey
	 *            :过程密钥
	 * @param macDataSource
	 *            :计算MAC的数据源
	 * @return
	 * @throws Exception
	 */
	private static String process(String processKey, String macDataSource) throws Exception
	{

		if (null == processKey || processKey.equals("") || processKey.length() != 32)
		{
			throw new IllegalArgumentException("过程密钥不能为空或不够32位!");
		}

		String leftKey = processKey.substring(0, 16);

		String rightKey = processKey.substring(16);

		// 拆分MAC数据源,每组16位hex(8 byte())
		String[] ds = splitData(macDataSource);

		String des = "";

		for (int i = 0; i < ds.length; i++)
		{
			if (i == 0)
			{
				// 第一次只做DES加密
				des = DESUtils.decEncNoPaddingDES(leftKey, ds[i], Cipher.ENCRYPT_MODE).toUpperCase();
			} else
			{
				// 用上一次 DES加密结果对 第 i 组数据做异或
				des = StringUtils.XOR(des, ds[i]);
				// 对异或后的数据做DES加密
				des = DESUtils.decEncNoPaddingDES(leftKey, des, Cipher.ENCRYPT_MODE).toUpperCase();
			}
		}
		// DES 加密最终结果用processKey后16位解密
		des = DESUtils.decEncNoPaddingDES(rightKey, des, Cipher.DECRYPT_MODE).toUpperCase();

		// 解密后 再用processKey前16位加密
		des = DESUtils.decEncNoPaddingDES(leftKey, des, Cipher.ENCRYPT_MODE).toUpperCase();

		return des;

	}

	/*
	 * 将hexMacDataSource进行分组 每 16 字符 8byte 一组
	 */
	private static String[] splitData(String hexMacDataSource)
	{
		int len = 0;

		int modValue = hexMacDataSource.length() % 16;

		if (modValue == 0)
		{
			// 补上80000000000000
			hexMacDataSource += "80000000000000";
			len = hexMacDataSource.length() / 16;
		} else if (modValue == 14)
		{
			// 补上80
			hexMacDataSource += "80";
			len = hexMacDataSource.length() / 16;
		} else
		{
			hexMacDataSource += "80";
			int hexSrcDataLen = hexMacDataSource.length();
			int totalLen = hexSrcDataLen + (16 - modValue - 2);
			hexMacDataSource = StringUtils.padding(hexMacDataSource, "right", "0", totalLen);
			len = hexMacDataSource.length() / 16;

		}

		String[] ds = new String[len];

		for (int i = 0; i < ds.length; i++)
		{
			if (hexMacDataSource.length() >= 16)
			{
				ds[i] = hexMacDataSource.substring(0, 16);
				hexMacDataSource = hexMacDataSource.substring(16);
			} else
			{
				throw new IllegalArgumentException("填充的数据非法!");
			}
		}
		return ds;
	}

}

 

测试代码如下:

 

package com.omini.common.utils;

/**
 * @author sandy
 * @version $Revision: 1.1 $ 建立日期 2012-9-11
 */
public class UnionUtilsTest
{

	public static void main(String[] args) throws Exception
	{
		// UnionUtilsTest.generateMACTest();
		UnionUtilsTest.generateCVN();

	}

	public static void generateARPCTest() throws Exception
	{
		String arpc = UnionUtils.generateARPC("32CB95B36D89477C", "6214618888000002074", "00", "0008", "00000000000000000000000000000000", "3030");

		System.out.println("arpc=" + arpc);
	}

	public static void generateMACTest() throws Exception
	{
		String result = UnionUtils.generateMAC("6214618888000002074", "00", "0029", "00000000000000000000000000000000", "04DA9F790A00299E99DA1521DAA0A3000000000000");

		System.out.println("MAC=" + result);
	}

	public static void generateARQCTest() throws Exception
	{
		String result = UnionUtils.generateARQC("6214610200000004163", "01", "000B", "77777777777777777777777777777777", "00000001000000000000000001568008000800015610052801112233447C00000B03A03000");

		System.out.println("ARQC=" + result);
	}

	public static void generateCVN() throws Exception
	{
		String result = UnionUtils.generateCVN("6221234567891234", "0712", "111", "0123456789ABCDEFFEDCBA9876543210");

		System.out.println("CVN=" + result);
	}
	
	public static void generateCVN2() throws Exception
	{
		String result = UnionUtils.generateCVN("6221234567891234", "0712", "000", "0123456789ABCDEFFEDCBA9876543210");

		System.out.println("CVN2=" + result);
	}

}

 

 

分享到:
评论
5 楼 elena_me 2018-04-20  
o0teamo0o 写道
您的这个 缺少了一个StringUtils工具类,能提供一下么 麻烦了


上面就有啊,自己建个类,拷代码就行了
4 楼 o0teamo0o 2016-03-29  
您的这个 缺少了一个StringUtils工具类,能提供一下么 麻烦了
3 楼 306963591 2014-04-29  
附件密码123456
2 楼 zxing 2013-08-30  
谢谢分享,请问一下附件密码是多少啊?
1 楼 xuri808422 2013-07-09  
附件要密码啊。。。

相关推荐

    IC卡工具证书、ARQC、ARPC、加密解密等

    IC卡工具,功能包括:校验ARQC,生成ARPC,生成MAC,生成CVN,加密解密,国密算法,IC卡证书,SDA静态数据认证,DDA动态数据认证,RSA算法等等

    arqc_gen_new.rar_C++ emv_EMV_arpc generator_arqc_gen_arqc_gen_ne

    emv arqc and arpc generator (writed in c#)

    Attachments-freeworld_arqc_arpcgenerator_Attachments_ARQCgenerat

    标题中的"Attachments-freeworld_arqc_arpcgenerator_Attachments_ARQCgenerat"部分暗示了这是一个与ARQC(Authorization Request Cryptogram)和ARPC(Authorization Response Cryptogram)生成相关的附件,可能是...

    pboc3.0国密升级改造点分析_tj

    包括IC卡发卡系统升级,如新增国密IC卡卡产品定义,国密+国际密码个人化模板以及参数维护,对KMS国密接口调用,以及SM2密钥(AC/MAC/ENC)的保存和国密ARQC/ARPC/TC生成和验证调用。 5. POS类系统升级 涉及到POS类...

    X2-ARQC EMV (2)_x2-arqc_x2arqc_x2emv_x2_emvx2_

    x2 software xw zip file

    中国银联基础加解密工具.zip

    同时也支持非对称RSA算法、国际hash算法、对称DES算法在内国际算法,另外还支持异或、HEX和字符串互转、数学运算、生成随机数,加解密、计算MAC、计算ARQC、ARPC等功能

    X2-ARQC - demo_X2-ARQCDEMO_arqc_

    在实际操作中,用户可能需要了解LTE或5G NR的协议栈结构,理解物理层、MAC层以及RRC层的工作原理,以便更好地理解和利用X2-ARQC DEMO。此外,软件提供的日志和监控功能可以帮助用户观察和分析ARQC算法在不同条件下的...

    X2-ARQC - demo_arqc_x2_x2software_x2arqc_x2demo.zip

    【标题】"X2-ARQC - demo_arqc_x2_x2software_x2arqc_x2demo.zip" 提供的是一个关于X2-ARQC技术的演示程序,它可能是一个软件开发工具包或者示例代码集,用于帮助开发者理解和应用X2-ARQC的相关功能。 【描述】"X2-...

    X2-ARQC_arqc_X2-Software_x2_x2software_x2arqc.zip

    【标题】"X2-ARQC_arqc_X2-Software_x2_x2software_x2arqc.zip" 提供的是一个与X2-ARQC相关的软件开发资源包,它可能包含了用于开发、调试或理解X2-ARQC系统的核心源代码。 【描述】描述中的信息与标题相同,"X2-...

    X2-ARQC_arqc_X2-Software_x2_x2software_x2arqc_源码.zip

    标题 "X2-ARQC_arqc_X2-Software_x2_x2software_x2arqc_源码.zip" 暗示我们关注的是一个名为 "X2-ARQC" 的软件项目,其源代码被压缩在 ZIP 文件中。ARQC 可能代表 "Application Request Control" 或者是某种特定的...

    X2-ARQC - demo_arqc_x2_x2software_x2arqc_x2demo_源码.zip

    【X2-ARQC 源码解析】 X2-ARQC,全称为X2 Advanced Radio Quality Control,是针对无线通信领域的一种高级射频质量控制技术。这个技术主要用于提升网络性能,确保数据传输的稳定性和可靠性,特别是在复杂的无线环境...

    X2-ARQC - update_arqc_smartcard_x2emvsoftware_X2EMVARQC_x2emv.zi

    《X2-ARQC:智能卡EMV软件更新与ARQC功能详解》 在现代支付系统中,安全性和效率是至关重要的。X2-ARQC(Authentication Request Cryptogram)是智能卡EMV(Europay, Mastercard, Visa)技术中的一个重要组成部分,...

    X2-ARQC_arqc_nuvot_x2_x2software_emv__源码.zip

    2. **ARQC算法**:涉及生成和验证ARQC的过程,这通常涉及到对卡片的密钥管理、交易数据加密和解密。 3. **非接触式支付**:由于提到了非更新式离线验证终端(NUVOT),所以源码可能处理的是非接触式交易,如挥卡支付...

Global site tag (gtag.js) - Google Analytics