ANSI X9.8标准 PIN xor PAN获取PIN BlOCK

ANSI X9.8标准 PIN xor PAN获取PIN BlOCK

之前看到几篇介绍,把ANSI说成16个字节,真心扯淡,各种误人子弟,真正的ANSI算法其实是8个字节,具体格式如下:

(1) ANSI X9.8 Format(不带主账号信息)

PIN(个人识别码 Personal Identity Number)总共有8个byte长度,分为两个部分;(类似数据包的格式)

1:Byte1 记录PIN的长度

2:Byte2-Byte8 6-12位(字符)PIN(每个字符占4个BIT,不足8位右补F)

例如:明文PIN为 123456,

则PIN BLOCK为 0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF

0x06记录了PIN的长度为6,后边不足16位均以F补齐,然后转换为BCD码(BCD码为8位二进制数为一个单元,也就是一个Byte的大小也是一个十六进制数HEX的占用长度)。

2)ANSI X9.8 Format带主帐号信息)
PIN BLOCK 格式:等于 PIN 按位异或主帐号
PIN 格式:(与1中的格式类似)
Byte 1 PIN的长度
Byte 2 – Byte 3/4/5/6/7 4--12个PIN(每个PIN占4个BIT)
Byte4/5/6/7/8 – Byte 8 FILLER “F” (每个“F“占4个BIT)

PAN(主帐号 Primary Account Number)同样包含8个byte,格式如下:
Byte 1 — Byte 2 0x00 0x00
Byte 3 — Byte 8 12个主帐号字符(最后一位为校验位)
12位字符主帐号的取法:取主帐号的右12位(不包括最右边的校验位),不足12位左补“0X00”。

例子:

明文 PIN:123456,
主帐号 PAN:123456789012345678
截取下的主帐号为:678901234567 (最后一位校验位8的前12位字符为截取的主帐号)

则用于PIN加密的主帐号为:0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
则 PIN BLOCK (PIN按位异或主帐号PAN)

即是为:  0x06 0x12 0x34 0x56 0xFF 0xFF 0xFF 0xFF
异或上:  0x00 0x00 0x67 0x89 0x01 0x23 0x45 0x67
结果为:  0x06 0x12 0x53 0xDF 0xFE 0xDC 0xBA 0x98

算法源码:(包含一个工具类Util和一个转换类ANSIFormat.java)

Util.java

package CodeApe;

public class Util {
 public Util() {

}

 
 public static void printHexString(String hint, byte[] b) {
     System.out.print(hint);
     for (int i = 0; i < b.length; i++) {
       String hex = Integer.toHexString(b[i] & 0xFF);
       if (hex.length() == 1) {
         hex = ‘0‘ + hex;
       }
       System.out.print(hex.toUpperCase() + " ");
     }
     System.out.println("");
   }

 
 
public static String Bytes2HexString(byte[] b) {
     String ret = "";
     for (int i = 0; i < b.length; i++) {
       String hex = Integer.toHexString(b[i] & 0xFF);
       if (hex.length() == 1) {
         hex = ‘0‘ + hex;
       }
       ret += hex.toUpperCase();
     }
     return ret;
   }

 
 
public static byte uniteBytes(byte src0, byte src1) {
  byte _b0 = Byte.decode("0x" + new String(new byte[] { src0 }))
    .byteValue();
  _b0 = (byte) (_b0 << 4);
  byte _b1 = Byte.decode("0x" + new String(new byte[] { src1 }))
    .byteValue();
  byte ret = (byte) (_b0 ^ _b1);
  return ret;
 }

 
 public static byte[] HexString2Bytes(String src) {
  byte[] ret = new byte[8];
  byte[] tmp = src.getBytes();
  for (int i = 0; i < 8; i++) {
  
 ret[i] = uniteBytes(tmp[i * 2], tmp[i * 2 + 1]);
  }
  return ret;
 }

}

ANSIFormat.java

package CodeApe;

import java.io.ObjectInputStream.GetField;

import javax.annotation.processing.Processor;

import CodeApe.Util;

public class ANSIFormat {

 private String pin;
 private String accno;
 public ANSIFormat(String pin , String accno){
  this.pin = pin;
  this.accno = accno;
 }
 
 public byte[] process(String pin, String accno) {
     byte arrPin[] = getHPin(pin);
     byte arrAccno[] = getHAccno(accno);
     byte arrRet[] = new byte[8];
     //PIN BLOCK 格式等于 PIN 按位异或 主帐号;
     for (int i = 0; i < 8; i++) {
       arrRet[i] = (byte) (arrPin[i] ^ arrAccno[i]);
     }
    
     Util.printHexString("PinBlock:", arrRet);
     return arrRet;
 }

 
 private byte[] getHPin(String pin) {
     byte arrPin[] = pin.getBytes();
     byte encode[] = new byte[8];
     encode[0] = (byte) 0x06;
     encode[1] = (byte) Util.uniteBytes(arrPin[0], arrPin[1]);
     encode[2] = (byte) Util.uniteBytes(arrPin[2], arrPin[3]);
     encode[3] = (byte) Util.uniteBytes(arrPin[4], arrPin[5]);
     encode[4] = (byte) 0xFF;
     encode[5] = (byte) 0xFF;
     encode[6] = (byte) 0xFF;
     encode[7] = (byte) 0xFF;
     Util.printHexString("encoded pin:", encode);
     return encode;
 }

 
 private byte[] getHAccno(String accno) {
     //取出主帐号;
     int len = accno.length();
     byte arrTemp[] = accno.substring(len < 13 ? 0 : len - 13, len - 1).getBytes();
     byte arrAccno[] = new byte[12];
     for (int i = 0; i < 12; i++) {
       arrAccno[i] = (i <= arrTemp.length ? arrTemp[i] : (byte) 0x00);
     }
     byte encode[] = new byte[8];
     encode[0] = (byte) 0x00;
     encode[1] = (byte) 0x00;
     encode[2] = (byte) Util.uniteBytes(arrAccno[0], arrAccno[1]);
     encode[3] = (byte) Util.uniteBytes(arrAccno[2], arrAccno[3]);
     encode[4] = (byte) Util.uniteBytes(arrAccno[4], arrAccno[5]);
     encode[5] = (byte) Util.uniteBytes(arrAccno[6], arrAccno[7]);
     encode[6] = (byte) Util.uniteBytes(arrAccno[8], arrAccno[9]);
     encode[7] = (byte) Util.uniteBytes(arrAccno[10], arrAccno[11]);
     Util.printHexString("encoded accno:", encode);
     return encode;
 }

 
}

test.java(测试类)

package CodeApe;

public class test {

 private static ANSIFormat pass;
 
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  String pin = "123456";
  String accno = "123456789012345678";
  System.out.println("encoded pin:"+pin);
  System.out.println("encoded accno:"+accno);
  pass = new ANSIFormat(pin, accno);
  byte[] b = pass.process(pin, accno);
  
 }

}

效果图: - -!

时间: 2024-10-13 04:43:20

ANSI X9.8标准 PIN xor PAN获取PIN BlOCK的相关文章

Java实现3DES加密--及ANSI X9.8 Format标准 PIN PAN获取PIN BlOCK

1, 采用银联ANSI X9.8标准 PIN xor PAN获取PIN BlOCK 2, 采用3Des进行加密 参考: des和3Des加密算法实现 要点:因为3DES是对称加密算法,key是24位,当只有16位时,后8位取key的前8位 ANSI X9.8标准 PIN xor PAN获取PIN BlOCK (1) ANSI X9.8 Format(不带主账号信息) PIN(个人识别码 Personal Identity Number)总共有8个byte长度,分为两个部分;(类似数据包的格式)

GNU C 、ANSI C、标准C、标准c++区别和联系

GNU计划,又称革奴计划,是由Richard Stallman在1983年9月27日公开发起的.它的目标是创建一套完全自由的操作系统.它在编写linux的时候自己制作了一个标准成为 GNU C标准.ANSI 美国国家标准协会,它对C做的标准ANSI C标准后来被国际标准协会接收成为 标准C 所以 ANSI C 和标准C是一个概念 总体来说现在linux也支持标准C,以后标准C可以跨平台,而GUN c 一般只在linux c下应用 18.1 ANSI C和标准C++的差别 这里的ANSI C指的是

Python 使用标准库根据进程名获取进程PID

应用场景 在进行 Linux 运维的环境中,我们经常会遇到维护同一台服务器上的多个程序,涉及到程序的启动.关闭和重启操作. 通常这些程序之间存在着相互依存的关系需要进行依次的启动关闭操作. 下面介绍几种通过进程名获取进程PID的方法: 方法一: 使用 subprocess 的 check_output 函数执行pidof命令 from subprocess import check_output def get_pid(name): return map(int,check_output(["p

倍福TwinCAT(贝福Beckhoff)常见问题(FAQ)-如何获取标准驱动器扭矩值获取电流值

双击某个驱动器(以松下伺服驱动器为例),在Process Data中,注意默认显示了PDO mapping1的数据(Error code, status word等) ? 注意左侧,2和3分别表示了与驱动器的所有数据输入和输出,如果我选中2 Output之后,勾选四个选项,那么就会有PDO mapping1到4,当然如果3 Input只勾选了第一项,那么就只会有Receive PDO mapping1 ? 在PDO mapping2中可以找到Torque actual value ? 我们还是输

LPC43xx MCU PIN Name and GPIO PIN Name Table

//--------------------------------------------------------------------------------+ // LPC43xx Pin Names, All pins defined. | // Package determines which are available. | //-------+---------+----------------+----------------+------------+------------

文件I/O与标准I/

一.先来了解下什么是文件I/O和标准I/O: 文件I/O:文件I/O称之为不带缓存的IO(unbuffered I/O).不带缓存指的是每个read,write都调用内核中的一个系统调用.也就是一般所说的低级I/O--操作系统提供的基本IO服务,与os绑定,特定于linix或unix平台. 标准I/O:标准I/O是ANSI C建立的一个标准I/O模型,是一个标准函数包和stdio.h头文件中的定义,具有一定的可移植性.标准I/O库处理很多细节.例如缓存分配,以优化长度执行I/O等.标准的I/O提

Linux 编程学习笔记----ANSI C 文件I/O管理

转载请注明出处:http://blog.csdn.net/suool/article/details/38129201 问题引入 文件的种类 依据数据存储的方式不同,能够将文件分为文本文件和二进制文件.详细的差别和关系例如以下: 文本文件与二进制文件在计算机文件系统中的物理存储都是二进制的,也就是在物理存储方面没有差别都是01码,这个没有异议.他们的差别主要在逻辑存储上,也就是编码上. 文本文件格式存储时是将值作为字符然后存入其字符编码的二进制,文本文件用'字符'作为单位来表示和存储数据,比方对

Linux 程序设计学习笔记----ANSI C 文件I/O管理

转载请注明出处:http://blog.csdn.net/suool/article/details/38129201 问题引入 文件的种类 根据数据存储的方式不同,可以将文件分为文本文件和二进制文件.具体的区别和关系如下: 文本文件与二进制文件在计算机文件系统中的物理存储都是二进制的,也就是在物理存储方面没有区别都是01码,这个没有异议,他们的区别主要在逻辑存储上,也就是编码上. 文本文件格式存储时是将值作为字符然后存入其字符编码的二进制,文本文件用'字符'作为单位来表示和存储数据,比如对于1

最简单的基于DirectShow的示例:获取Filter信息

===================================================== 最简单的基于DirectShow的示例文章列表: 最简单的基于DirectShow的示例:视频播放器 最简单的基于DirectShow的示例:视频播放器图形界面版 最简单的基于DirectShow的示例:视频播放器自定义版 最简单的基于DirectShow的示例:获取Filter信息 =====================================================