diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index 37e6c29..e44699a 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -1974,6 +1974,94 @@ public class SydApi4j implements SydApi { } + /** + * 短数据MAC计算接口,对数据进行SM4 MAC计算 + * + * @param keyIndex:输入。计算mac所需要的密钥索引值 + * @param pcData: 输入。计算mac所需要的数据。 + * + * @return mac值(固定长度16字节)转HEX 字符串格式 + * */ + public String SYD_SM4Mac_ShortData( + String keyIndex, + byte[] pcData + ){ + ByteBuffer bb = ByteBuffer.allocate(10 * 1024); + PacketSN sn = PacketSN.gen(); + bb.put( new byte[2] ); + bb.put( sn.getSn().array() ); + bb.put( "E0".getBytes() ); + bb.put( (byte) 0x30 ); // 仅一块 + bb.put( (byte) ( 0x38) ); // SM4 加密 + bb.put( (byte) ( 0x32) ); // CBC + bb.put( (byte) ( 0x30) ); // ZEK + + // 填充密钥 + // 1A+K+27位的索引号 + bb.put( keyIndex.getBytes() ); + + bb.put( (byte) ( 0x30) ); // 输入消息类型二进制 + bb.put( (byte) ( 0x30) ); // 输出消息类型二进制 + + bb.put( (byte) ( 0x31) ); // 填充模式 + bb.put( "0000".getBytes() ); // 填充字符 + bb.put( (byte) ( 0x32) ); // 填充类型 + + // iv + byte[] iv = new byte[ 32 ]; + Arrays.fill( iv, (byte)0x30 ); + bb.put( iv ); + + // P 长度暂未支持 + + + // 填充消息数据长度 + bb.put( String.format("%03X", pcData.length).getBytes() ); + + // 填充消息数据 + bb.put( pcData ); + + // 重新计算长度 + int len = bb.position(); + len -= 2; + byte[] lenArray = new byte[ 2 ]; + lenArray[0] = (byte)((len >> 8) & 0xFF); + lenArray[1] = (byte)( len & 0xFF); + + bb.put( 0, (byte)((len >> 8) & 0xFF) ); + bb.put( 1, (byte)( len & 0xFF) ); + + // 通信 + synchronized (this) { + // 响应解析 + bb = syncRead(syncSend(bb)); + } + + bb.flip(); + bb.position( 12 ); + byte[] code = new byte[2]; + bb.get( code ); + + int retCode = Integer.valueOf( new String( code ) ); + if ( 0 != retCode ) { + throw new SydApiException( retCode ); + } + + // 跳过输出模式 + bb.get(); + + // 获取长度 + byte[] iLenArray = new byte[3]; + bb.get( iLenArray ); + int ilen = Integer.valueOf( new String( iLenArray ), 16 ); + byte[] skip = new byte[ ilen - 16 ]; + bb.get(skip); + byte[] mac = new byte[16]; + bb.get(mac); + + return Util.bytes2HexString(mac); + } + public List SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List pINdata) { int batchSize = pINdata.size();