diff --git a/src/main/java/com/sunyard/inf/SydCryptionApi.java b/src/main/java/com/sunyard/inf/SydCryptionApi.java index 4a5f9c9..ad980a0 100644 --- a/src/main/java/com/sunyard/inf/SydCryptionApi.java +++ b/src/main/java/com/sunyard/inf/SydCryptionApi.java @@ -275,7 +275,7 @@ interface SydSYMApi { byte[] SYMEncryptData(int nAlg, String seesionKey, int fullmode, byte[] pINdata); - List SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List pINdata); + // List SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List pINdata); /** * 用输入的会话密钥,对指定报文数据进行加密处理。 diff --git a/src/main/java/racal/sunyard/main/SydApi4j.java b/src/main/java/racal/sunyard/main/SydApi4j.java index cc078de..b6e2bfc 100644 --- a/src/main/java/racal/sunyard/main/SydApi4j.java +++ b/src/main/java/racal/sunyard/main/SydApi4j.java @@ -1983,6 +1983,84 @@ public class SydApi4j implements SydApi { } + public byte[] SYD_SM3_LongData(byte[] pcData, byte[] procData, int iPkgNum) { + + if ( pcData.length > MaxDataLenEachPack ) { + throw new IllegalArgumentException("单包数据超长"); + } + + ByteBuffer bb = ByteBuffer.allocate(10 * 1024); + PacketSN sn = PacketSN.gen(); + bb.put( new byte[2] ); + bb.put( sn.getSn().array() ); + bb.put( "76".getBytes() ); + bb.put( (byte) (0x30 + iPkgNum) ); // 包序号 + + // 填充消息数据长度 + bb.put( String.format("%04d", pcData.length).getBytes() ); + + if ( 0 == iPkgNum || 1 == iPkgNum ) { + // 填充消息数据 + bb.put( pcData ); + + // 无用户 id + bb.put( String.format("%02d", 0).getBytes() ); + + // 无公钥 + bb.put( String.format("%04d", 0).getBytes() ); + + } else { + // 过渡数据 + bb.put( String.format("%04d", procData.length).getBytes() ); + bb.put( procData ); + } + + + // 重新计算长度 + 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(); + + if ( 0 == iPkgNum || 3 == iPkgNum ){ + byte[] hash = new byte[ 32 ]; + bb.get(hash); + return hash; + } else { + // 获取长度 + byte[] iLenArray = new byte[4]; + bb.get( iLenArray ); + int ilen = Integer.valueOf( new String( iLenArray ), 10 ); + byte[] data = new byte[ ilen ]; + bb.get(data); + return data; + } + } + + /** * 短数据MAC计算接口,对数据进行SM4 MAC计算 * @@ -2071,7 +2149,7 @@ public class SydApi4j implements SydApi { return Util.bytes2HexString(mac); } - public byte[] SYD_SM4_LongData(int nAlg, String keyIndex, int fullmode, byte[] pcData, int iPkgNum) { + public byte[] SYD_SM4_LongData(int nAlg, int round, byte[] iv, String keyIndex, int fullmode, byte[] pcData, int iPkgNum) { if ( pcData.length > MaxDataLenEachPack ) { throw new IllegalArgumentException("单包数据超长"); @@ -2083,9 +2161,9 @@ public class SydApi4j implements SydApi { bb.put( sn.getSn().array() ); bb.put( "E0".getBytes() ); bb.put( (byte) (0x30 + iPkgNum) ); // 包序号 - bb.put( (byte) ( 0x30 + nAlg) ); // 密钥模式 - bb.put( (byte) ( 0x31) ); // ECB - bb.put( (byte) ( 0x30) ); // ZEK + bb.put( (byte) ( 0x30 + nAlg) ); // 密钥模式 + bb.put( (byte) ( 0x30 + round )); // 1=ECB 2=CBC + bb.put( (byte) ( 0x30) ); // ZEK // 填充密钥 bb.put( keyIndex.getBytes() ); @@ -2093,11 +2171,22 @@ public class SydApi4j implements SydApi { bb.put( (byte) ( 0x30) ); // 输入消息类型二进制 bb.put( (byte) ( 0x30) ); // 输出消息类型二进制 - bb.put( (byte) ( 0x30 + fullmode) ); // 填充模式 - bb.put( "0000".getBytes() ); // 填充字符 - bb.put( (byte) ( 0x32) ); // 填充类型 - // iv 暂未支持 + if( 0 == iPkgNum || 3 == iPkgNum || 4 == iPkgNum ) { + bb.put( (byte) ( 0x30 + fullmode) ); // 填充模式 + bb.put( "0000".getBytes() ); // 填充字符 + bb.put( (byte) ( 0x32) ); // 填充类型 + } + + // iv + if ( 2 == round ) { + if ( null == iv ) { + iv = new byte[ 32 ]; + Arrays.fill( iv, (byte)0x30 ); + } + bb.put( iv ); + } + // P 长度暂未支持 @@ -2147,7 +2236,7 @@ public class SydApi4j implements SydApi { return d; } - public List SYMEncryptDecryptBatchData(int nAlg, String[] seesionKey, int fullmode, List pINdata) { + public List SYMEncryptDecryptBatchData(int nAlg, int round, byte[] iv, String[] seesionKey, int fullmode, List pINdata) { int batchSize = pINdata.size(); if ( batchSize < 1 || batchSize > 10 ) { @@ -2182,7 +2271,7 @@ public class SydApi4j implements SydApi { bb.put( (byte) 0x34 ); // 批量加解密 bb.put( (byte) batchSize ); // 批量数 bb.put( (byte) ( 0x30 + nAlg) ); // 密钥模式 - bb.put( (byte) ( 0x31) ); // ECB + bb.put( (byte) ( 0x30 + round) ); // 1=ECB 2=CBC bb.put( (byte) ( 0x30) ); // ZEK // 填充多个密钥 @@ -2197,10 +2286,20 @@ public class SydApi4j implements SydApi { bb.put( "0000".getBytes() ); // 填充字符 bb.put( (byte) ( 0x32) ); // 填充类型 - // iv 暂未支持 - // P 长度暂未支持 + // 多个 iv + if ( 2 == round ) { + if ( null == iv ) { + iv = new byte[ 32 ]; + Arrays.fill( iv, (byte)0x30 ); + } + for (int i = 0 ; i < batchSize ; i ++ ) { + bb.put( iv ); + } + } + // P 长度暂未支持 + // 填充多个消息数据长度 for ( byte[] data : pINdata ) { bb.put( String.format("%03X", data.length).getBytes() ); diff --git a/src/test/java/com/sunyard/sydapi/test/TestBatchData.java b/src/test/java/com/sunyard/sydapi/test/TestBatchData.java index c14d640..a0dfc74 100644 --- a/src/test/java/com/sunyard/sydapi/test/TestBatchData.java +++ b/src/test/java/com/sunyard/sydapi/test/TestBatchData.java @@ -22,7 +22,7 @@ public class TestBatchData { List pINdata = new ArrayList(); pINdata.add("12345678".getBytes()); - List datas = api.SYMEncryptDecryptBatchData(0x8, keys, 1, pINdata); +// List datas = api.SYMEncryptDecryptBatchData(0x8, keys, 1, pINdata); // boolean pass = api.SM2Verify( 1, Util.hexString2Bytes(pk), Util.hexString2Bytes(inHexData), sign ); }