@@ -14,8 +14,7 @@ namespace JT809.Protocol.Test.JT809Encrypt | |||||
{ | { | ||||
IA1 = 20000000, | IA1 = 20000000, | ||||
IC1 = 20000000, | IC1 = 20000000, | ||||
M1 = 30000000, | |||||
Key = 256178, | |||||
M1 = 30000000 | |||||
}; | }; | ||||
[Fact] | [Fact] | ||||
@@ -26,7 +25,7 @@ namespace JT809.Protocol.Test.JT809Encrypt | |||||
01,02,03,04,05,06,07 | 01,02,03,04,05,06,07 | ||||
}; | }; | ||||
IJT809Encrypt jT809Encrypt = new JT809EncryptImpl(options); | IJT809Encrypt jT809Encrypt = new JT809EncryptImpl(options); | ||||
var data = jT809Encrypt.Encrypt(bytes).ToHexString(); | |||||
var data = jT809Encrypt.Encrypt(bytes, 256178).ToHexString(); | |||||
//"D3 4C 70 78 A7 3A 41" | //"D3 4C 70 78 A7 3A 41" | ||||
} | } | ||||
@@ -35,7 +34,7 @@ namespace JT809.Protocol.Test.JT809Encrypt | |||||
{ | { | ||||
byte[] bytes = "D3 4C 70 78 A7 3A 41".ToHexBytes(); | byte[] bytes = "D3 4C 70 78 A7 3A 41".ToHexBytes(); | ||||
IJT809Encrypt jT809Encrypt = new JT809EncryptImpl(options); | IJT809Encrypt jT809Encrypt = new JT809EncryptImpl(options); | ||||
var data = jT809Encrypt.Decrypt(bytes); | |||||
var data = jT809Encrypt.Decrypt(bytes, 256178); | |||||
Assert.Equal(new byte[] | Assert.Equal(new byte[] | ||||
{ | { | ||||
01,02,03,04,05,06,07 | 01,02,03,04,05,06,07 | ||||
@@ -53,5 +53,19 @@ namespace JT809.Protocol.Test | |||||
}); | }); | ||||
var sn = JT809GlobalConfig.Instance.MsgSNDistributed.Increment(); | var sn = JT809GlobalConfig.Instance.MsgSNDistributed.Increment(); | ||||
} | } | ||||
[Fact] | |||||
public void Test4() | |||||
{ | |||||
JT809Header jT809Header = new JT809Header(); | |||||
jT809Header.MsgLength = 24; | |||||
jT809Header.MsgSN = 1024; | |||||
jT809Header.BusinessType = JT809Enums.JT809BusinessType.从链路静态信息交换消息; | |||||
jT809Header.MsgGNSSCENTERID = 1200; | |||||
jT809Header.Version = new JT809Header_Version (0xFF,0xAA,0xBB); | |||||
jT809Header.EncryptFlag = JT809Header_Encrypt.None; | |||||
jT809Header.EncryptKey = 0; | |||||
var hex = JT809Serializer.Serialize(jT809Header).ToHexString(); | |||||
} | |||||
} | } | ||||
} | } |
@@ -17,8 +17,7 @@ namespace JT809.Protocol.Test.JT809Packages | |||||
{ | { | ||||
IA1 = 20000000, | IA1 = 20000000, | ||||
IC1 = 20000000, | IC1 = 20000000, | ||||
M1 = 30000000, | |||||
Key = 256178, | |||||
M1 = 30000000 | |||||
})); | })); | ||||
} | } | ||||
@@ -28,11 +27,11 @@ namespace JT809.Protocol.Test.JT809Packages | |||||
JT809Package jT809Package = new JT809Package(); | JT809Package jT809Package = new JT809Package(); | ||||
jT809Package.Header = new JT809Header | jT809Package.Header = new JT809Header | ||||
{ | { | ||||
EncryptFlag= JT809Header_Encrypt.Common, | |||||
MsgSN= 133, | |||||
EncryptKey=5819, | |||||
BusinessType= JT809Enums.JT809BusinessType.主链路登录请求消息, | |||||
MsgGNSSCENTERID= 20180920, | |||||
EncryptFlag = JT809Header_Encrypt.Common, | |||||
MsgSN = 133, | |||||
EncryptKey = 256178, | |||||
BusinessType = JT809Enums.JT809BusinessType.主链路登录请求消息, | |||||
MsgGNSSCENTERID = 20180920, | |||||
}; | }; | ||||
JT809_0x1001 jT809_0X1001 = new JT809_0x1001(); | JT809_0x1001 jT809_0X1001 = new JT809_0x1001(); | ||||
jT809_0X1001.UserId = 20180920; | jT809_0X1001.UserId = 20180920; | ||||
@@ -47,16 +46,15 @@ namespace JT809.Protocol.Test.JT809Packages | |||||
[Fact] | [Fact] | ||||
public void Test2() | public void Test2() | ||||
{ | { | ||||
var bytes = "5B 00 00 00 48 00 00 00 85 10 01 01 33 EF B8 01 00 00 01 00 00 16 BB D3 7D 9C C4 90 0C 77 DC 78 F8 67 65 27 D8 AE 12 24 3C FB 64 CC 2F BA 61 9A EF AD 33 AC CB 32 56 F6 7B FF 19 DF 33 09 78 41 09 86 65 70 3F 2E B5 5D".ToHexBytes(); | |||||
var bytes = "5B000000480000008510010133EFB8010000010003E8B2D37D9CC4900C77DC78F8676527D8AE12243CFB64CC2FBA619AEFAD33ACCB3256F67BFF19DF33097841098665703FE36E5D".ToHexBytes(); | |||||
JT809Package jT809Package = JT809Serializer.Deserialize(bytes); | JT809Package jT809Package = JT809Serializer.Deserialize(bytes); | ||||
Assert.Equal(JT809Header_Encrypt.Common, jT809Package.Header.EncryptFlag); | Assert.Equal(JT809Header_Encrypt.Common, jT809Package.Header.EncryptFlag); | ||||
Assert.Equal((uint)5819, jT809Package.Header.EncryptKey); | |||||
Assert.Equal((uint)256178, jT809Package.Header.EncryptKey); | |||||
Assert.Equal((uint)72, jT809Package.Header.MsgLength); | Assert.Equal((uint)72, jT809Package.Header.MsgLength); | ||||
Assert.Equal((uint)133, jT809Package.Header.MsgSN); | Assert.Equal((uint)133, jT809Package.Header.MsgSN); | ||||
Assert.Equal((uint)5819, jT809Package.Header.EncryptKey); | |||||
Assert.Equal((uint)20180920, jT809Package.Header.MsgGNSSCENTERID); | Assert.Equal((uint)20180920, jT809Package.Header.MsgGNSSCENTERID); | ||||
Assert.Equal(JT809Enums.JT809BusinessType.主链路登录请求消息, jT809Package.Header.BusinessType); | Assert.Equal(JT809Enums.JT809BusinessType.主链路登录请求消息, jT809Package.Header.BusinessType); | ||||
Assert.Equal(new JT809Header_Version().ToString(), jT809Package.Header.Version.ToString()); | |||||
Assert.Equal("1.0.0", jT809Package.Header.Version.ToString()); | |||||
JT809_0x1001 jT809_0X1001 = (JT809_0x1001)jT809Package.Bodies; | JT809_0x1001 jT809_0X1001 = (JT809_0x1001)jT809Package.Bodies; | ||||
Assert.Equal((uint)20180920, jT809_0X1001.UserId); | Assert.Equal((uint)20180920, jT809_0X1001.UserId); | ||||
Assert.Equal("20180920", jT809_0X1001.Password); | Assert.Equal("20180920", jT809_0X1001.Password); | ||||
@@ -2,7 +2,7 @@ | |||||
{ | { | ||||
public interface IJT809Encrypt | public interface IJT809Encrypt | ||||
{ | { | ||||
byte[] Encrypt(byte[] buffer); | |||||
byte[] Decrypt(byte[] buffer); | |||||
byte[] Encrypt(byte[] buffer, uint privateKey); | |||||
byte[] Decrypt(byte[] buffer, uint privateKey); | |||||
} | } | ||||
} | } |
@@ -5,6 +5,5 @@ | |||||
public uint M1 { get; set; } | public uint M1 { get; set; } | ||||
public uint IA1 { get; set; } | public uint IA1 { get; set; } | ||||
public uint IC1 { get; set; } | public uint IC1 { get; set; } | ||||
public uint Key { get; set; } | |||||
} | } | ||||
} | } |
@@ -14,17 +14,17 @@ namespace JT809.Protocol.JT809Encrypt | |||||
this.jT809EncryptOptions = jT809EncryptOptions; | this.jT809EncryptOptions = jT809EncryptOptions; | ||||
} | } | ||||
public byte[] Decrypt(byte[] buffer) | |||||
public byte[] Decrypt(byte[] buffer, uint privateKey) | |||||
{ | { | ||||
return Encrypt(buffer); | |||||
return Encrypt(buffer, privateKey); | |||||
} | } | ||||
public byte[] Encrypt(byte[] buffer) | |||||
public byte[] Encrypt(byte[] buffer, uint privateKey) | |||||
{ | { | ||||
byte[] data = new byte[buffer.Length]; | byte[] data = new byte[buffer.Length]; | ||||
if (0 == jT809EncryptOptions.Key) | |||||
if (0 == privateKey) | |||||
{ | { | ||||
jT809EncryptOptions.Key = 1; | |||||
privateKey = 1; | |||||
} | } | ||||
uint mkey = jT809EncryptOptions.M1; | uint mkey = jT809EncryptOptions.M1; | ||||
if (0 == mkey) | if (0 == mkey) | ||||
@@ -33,8 +33,8 @@ namespace JT809.Protocol.JT809Encrypt | |||||
} | } | ||||
for (int idx = 0; idx < buffer.Length; idx++) | for (int idx = 0; idx < buffer.Length; idx++) | ||||
{ | { | ||||
jT809EncryptOptions.Key = jT809EncryptOptions.IA1 * (jT809EncryptOptions.Key % mkey) + jT809EncryptOptions.IC1; | |||||
buffer[idx] ^= (byte)((jT809EncryptOptions.Key >> 20) & 0xFF); | |||||
privateKey = jT809EncryptOptions.IA1 * (privateKey % mkey) + jT809EncryptOptions.IC1; | |||||
buffer[idx] ^= (byte)((privateKey >> 20) & 0xFF); | |||||
data[idx] = buffer[idx]; | data[idx] = buffer[idx]; | ||||
} | } | ||||
return data; | return data; | ||||
@@ -19,14 +19,24 @@ namespace JT809.Protocol.JT809Extensions | |||||
return bcdSb.ToString(); | return bcdSb.ToString(); | ||||
} | } | ||||
public static int WriteBCDLittle(IMemoryOwner<byte> memoryOwner, int offset, string data, int digit, int len) | |||||
public static int WriteBCDLittle(IMemoryOwner<byte> memoryOwner, int offset, string data,int len) | |||||
{ | { | ||||
ReadOnlySpan<char> bcd = data.PadLeft(len, '0').AsSpan(); | |||||
for (int i = 0; i < digit; i++) | |||||
string bcdText = data == null ? "" : data; | |||||
byte[] bytes = new byte[len]; | |||||
int startIndex = 0; | |||||
int noOfZero = len * 2 - bcdText.Length; | |||||
if (noOfZero > 0) | |||||
{ | { | ||||
memoryOwner.Memory.Span[offset + i] = Convert.ToByte(bcd.Slice(i * 2, 2).ToString(), 16); | |||||
bcdText = bcdText.Insert(startIndex, new string('0', noOfZero)); | |||||
} | } | ||||
return digit; | |||||
int byteIndex = 0; | |||||
while (startIndex < bcdText.Length && byteIndex < len) | |||||
{ | |||||
memoryOwner.Memory.Span[startIndex + offset] = Convert.ToByte(bcdText.Substring(startIndex, 2), 16); | |||||
startIndex += 2; | |||||
byteIndex++; | |||||
} | |||||
return len; | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -118,27 +118,9 @@ namespace JT809.Protocol.JT809Extensions | |||||
/// <param name="hexString"></param> | /// <param name="hexString"></param> | ||||
/// <param name="separator"></param> | /// <param name="separator"></param> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static byte[] ToHexBytes(this string hexString, string separator = " ") | |||||
public static byte[] ToHexBytes(this string hexString) | |||||
{ | { | ||||
return hexString.Split(new string[] { separator }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); | |||||
} | |||||
/// <summary> | |||||
/// 16进制字符串转16进制数组 | |||||
/// </summary> | |||||
/// <param name="hexString"></param> | |||||
/// <returns></returns> | |||||
public static byte[] ToStr2HexBytes(this string hexString) | |||||
{ | |||||
//byte[] buf = new byte[hexString.Length / 2]; | |||||
//for (int i = 0; i < hexString.Length; i++) | |||||
//{ | |||||
// if (i % 2 == 0) | |||||
// { | |||||
// buf[i / 2] = Convert.ToByte(hexString.Substring(i, 2), 16) ; | |||||
// } | |||||
//} | |||||
hexString = hexString.Replace(" ", ""); | |||||
byte[] buf = new byte[hexString.Length / 2]; | byte[] buf = new byte[hexString.Length / 2]; | ||||
ReadOnlySpan<char> readOnlySpan = hexString.AsSpan(); | ReadOnlySpan<char> readOnlySpan = hexString.AsSpan(); | ||||
for (int i = 0; i < hexString.Length; i++) | for (int i = 0; i < hexString.Length; i++) | ||||
@@ -149,13 +131,6 @@ namespace JT809.Protocol.JT809Extensions | |||||
} | } | ||||
} | } | ||||
return buf; | return buf; | ||||
//List<byte> bytes = new List<byte>(); | |||||
//while (hexString.Length>0) | |||||
//{ | |||||
// bytes.Add(Convert.ToByte(hexString.AsSpan(0, 2).ToString(), 16)); | |||||
// hexString = hexString.Remove(0,2); | |||||
//} | |||||
//return Regex.Replace(hexString, @"(\w{2})", "$1 ").Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).Select(s => Convert.ToByte(s, 16)).ToArray(); | |||||
} | } | ||||
public unsafe static string ReadHexStringLittle(ReadOnlySpan<byte> read, ref int offset, int len) | public unsafe static string ReadHexStringLittle(ReadOnlySpan<byte> read, ref int offset, int len) | ||||
@@ -65,7 +65,7 @@ namespace JT809.Protocol.JT809Formatters | |||||
jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), buffer.Slice(offset, checkIndex - offset), out readSize); | jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), buffer.Slice(offset, checkIndex - offset), out readSize); | ||||
break; | break; | ||||
case JT809Header_Encrypt.Common: | case JT809Header_Encrypt.Common: | ||||
byte[] bodiesData = JT809GlobalConfig.Instance.Encrypt.Decrypt(buffer.Slice(offset, checkIndex - offset).ToArray()); | |||||
byte[] bodiesData = JT809GlobalConfig.Instance.Encrypt.Decrypt(buffer.Slice(offset, checkIndex - offset).ToArray(), jT809Package.Header.EncryptKey); | |||||
jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), bodiesData, out readSize); | jT809Package.Bodies = JT809FormatterResolverExtensions.JT809DynamicDeserialize(JT809FormatterExtensions.GetFormatter(jT809BodiesTypeAttribute.JT809BodiesType), bodiesData, out readSize); | ||||
break; | break; | ||||
} | } | ||||
@@ -104,7 +104,7 @@ namespace JT809.Protocol.JT809Formatters | |||||
case JT809Header_Encrypt.None: | case JT809Header_Encrypt.None: | ||||
break; | break; | ||||
case JT809Header_Encrypt.Common: | case JT809Header_Encrypt.Common: | ||||
messageBodyData = JT809GlobalConfig.Instance.Encrypt.Encrypt(messageBodyData); | |||||
messageBodyData = JT809GlobalConfig.Instance.Encrypt.Encrypt(messageBodyData, value.Header.EncryptKey); | |||||
break; | break; | ||||
} | } | ||||
} | } | ||||
@@ -27,7 +27,7 @@ namespace JT809.Protocol.JT809Formatters.JT809SubMessageBodyFormatters | |||||
public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809_0x9500_0x9505 value) | public int Serialize(IMemoryOwner<byte> memoryOwner, int offset, JT809_0x9500_0x9505 value) | ||||
{ | { | ||||
offset += JT809BinaryExtensions.WriteBCDLittle(memoryOwner, offset, value.AuthenticationCode,10,20); | |||||
offset += JT809BinaryExtensions.WriteBCDLittle(memoryOwner, offset, value.AuthenticationCode,20); | |||||
offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.AccessPointName,20); | offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.AccessPointName,20); | ||||
offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.UserName, 49); | offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.UserName, 49); | ||||
offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.Password, 22); | offset += JT809BinaryExtensions.WriteStringLittle(memoryOwner, offset, value.Password, 22); | ||||
@@ -1,4 +1,5 @@ | |||||
using JT809.Protocol.JT809Configs; | using JT809.Protocol.JT809Configs; | ||||
using JT809.Protocol.JT809Encrypt; | |||||
using JT809.Protocol.JT809Internal; | using JT809.Protocol.JT809Internal; | ||||
using System; | using System; | ||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
@@ -27,7 +28,9 @@ namespace JT809.Protocol | |||||
public IJT809Encrypt Encrypt { get; private set; } | public IJT809Encrypt Encrypt { get; private set; } | ||||
public IMsgSNDistributed MsgSNDistributed {get;private set;} | |||||
public JT809EncryptOptions EncryptOptions { get; private set; } | |||||
public IMsgSNDistributed MsgSNDistributed { get; private set; } | |||||
public JT809HeaderOptions HeaderOptions { get; private set; } | public JT809HeaderOptions HeaderOptions { get; private set; } | ||||
/// <summary> | /// <summary> | ||||
@@ -36,6 +39,19 @@ namespace JT809.Protocol | |||||
/// </summary> | /// </summary> | ||||
public bool SkipCRCCode { get; private set; } | public bool SkipCRCCode { get; private set; } | ||||
/// <summary> | /// <summary> | ||||
/// 设置加密算法选项值 | |||||
/// 不同的上下级平台之间,加密的算法是一致的,但是针对 M1, IA1, IC1 的不同。 | |||||
/// 数据先经过加密而后解密。 | |||||
/// </summary> | |||||
/// <param name="jT809Encrypt"></param> | |||||
/// <returns></returns> | |||||
public JT809GlobalConfig SetEncryptOptions(JT809EncryptOptions jT809EncryptOptions) | |||||
{ | |||||
instance.Value.Encrypt = new JT809EncryptImpl(jT809EncryptOptions); | |||||
instance.Value.EncryptOptions = jT809EncryptOptions; | |||||
return instance.Value; | |||||
} | |||||
/// <summary> | |||||
/// 设置加密算法实现 | /// 设置加密算法实现 | ||||
/// </summary> | /// </summary> | ||||
/// <param name="jT809Encrypt"></param> | /// <param name="jT809Encrypt"></param> | ||||
@@ -38,6 +38,7 @@ namespace JT809.Protocol | |||||
/// 协议版本号标识,上下级平台之间采用的标准协议版 | /// 协议版本号标识,上下级平台之间采用的标准协议版 | ||||
/// 编号;长度为 3 个字节来表示,0x01 0x02 0x0F 标识 | /// 编号;长度为 3 个字节来表示,0x01 0x02 0x0F 标识 | ||||
/// 的版本号是 v1.2.15,以此类推。 | /// 的版本号是 v1.2.15,以此类推。 | ||||
/// Hex编码 | |||||
/// </summary> | /// </summary> | ||||
public JT809Header_Version Version { get; set; } = new JT809Header_Version(); | public JT809Header_Version Version { get; set; } = new JT809Header_Version(); | ||||
/// <summary> | /// <summary> | ||||
@@ -4,6 +4,10 @@ using System.Text; | |||||
namespace JT809.Protocol | namespace JT809.Protocol | ||||
{ | { | ||||
/// <summary> | |||||
/// 协议版本号标识 | |||||
/// Hex编码 | |||||
/// </summary> | |||||
public class JT809Header_Version | public class JT809Header_Version | ||||
{ | { | ||||
public byte[] Buffer { get; } = new byte[3]; | public byte[] Buffer { get; } = new byte[3]; | ||||
@@ -32,6 +36,7 @@ namespace JT809.Protocol | |||||
/// <summary> | /// <summary> | ||||
/// 默认1.0.0版本 | /// 默认1.0.0版本 | ||||
/// Hex编码 | |||||
/// </summary> | /// </summary> | ||||
public JT809Header_Version() | public JT809Header_Version() | ||||
{ | { | ||||
@@ -39,14 +44,22 @@ namespace JT809.Protocol | |||||
Minor = 0; | Minor = 0; | ||||
Build = 0; | Build = 0; | ||||
} | } | ||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
/// <param name="major">0x00~0xFF</param> | |||||
/// <param name="minor">0x00~0xFF</param> | |||||
/// <param name="buid">0x00~0xFF</param> | |||||
public JT809Header_Version(byte major, byte minor, byte buid) | public JT809Header_Version(byte major, byte minor, byte buid) | ||||
{ | { | ||||
Major = major; | Major = major; | ||||
Minor = minor; | Minor = minor; | ||||
Build = buid; | Build = buid; | ||||
} | } | ||||
/// <summary> | |||||
/// | |||||
/// </summary> | |||||
/// <param name="bytes">[0x00~0xFF,0x00~0xFF,0x00~0xFF]</param> | |||||
public JT809Header_Version(byte[] bytes) | public JT809Header_Version(byte[] bytes) | ||||
{ | { | ||||
Major = bytes[0]; | Major = bytes[0]; | ||||