Added support for loading from Softcam.key
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 1m28s
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 1m28s
This commit is contained in:
parent
3bc81db95e
commit
cd2055a07a
@ -35,6 +35,7 @@ using skyscraper8.SatIp.RtspResponses;
|
||||
using skyscraper8.SimpleServiceDiscoveryProtocol;
|
||||
using skyscraper8.Skyscraper.Math;
|
||||
using skyscraper8.Skyscraper;
|
||||
using skyscraper8.Skyscraper.Security.AccessControl;
|
||||
|
||||
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
|
||||
namespace skyscraper5
|
||||
@ -91,6 +92,7 @@ namespace skyscraper5
|
||||
logger.DebugFormat("I'm a {0}-bit Process.", Environment.Is64BitProcess ? 64 : 32);
|
||||
|
||||
PluginManager.GetInstance();
|
||||
SoftcamKeyset.GetInstance().InitializeFromFile();
|
||||
|
||||
if (args.Length != 0)
|
||||
{
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
public class AccessControlException : SkyscraperSecurityException
|
||||
{
|
||||
public AccessControlException()
|
||||
{
|
||||
}
|
||||
|
||||
public AccessControlException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public AccessControlException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
42
skyscraper8/Skyscraper/Security/AccessControl/BissKey.cs
Normal file
42
skyscraper8/Skyscraper/Security/AccessControl/BissKey.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class BissKey
|
||||
{
|
||||
public BissKey(uint bissCoordinate, byte[] keyData)
|
||||
{
|
||||
Coordinate = bissCoordinate;
|
||||
Key = keyData;
|
||||
}
|
||||
|
||||
public byte[] Key { get; set; }
|
||||
|
||||
public uint Coordinate { get; set; }
|
||||
|
||||
protected bool Equals(BissKey other)
|
||||
{
|
||||
return Coordinate == other.Coordinate;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
return false;
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
if (obj.GetType() != this.GetType())
|
||||
return false;
|
||||
return Equals((BissKey)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)Coordinate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal interface MultipartKey
|
||||
{
|
||||
bool SetHint(string keyType, byte[] key);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class NagravisionKey : MultipartKey
|
||||
{
|
||||
public NagravisionKey(uint nagravisionGroupid)
|
||||
{
|
||||
Group = nagravisionGroupid;
|
||||
}
|
||||
|
||||
public uint Group { get; private set; }
|
||||
|
||||
public bool SetHint(string keyType, byte[] key)
|
||||
{
|
||||
switch (keyType)
|
||||
{
|
||||
case "00":
|
||||
KeyA = key;
|
||||
return true;
|
||||
case "01":
|
||||
KeyB = key;
|
||||
return true;
|
||||
case "M1":
|
||||
Master = key;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Master { get; set; }
|
||||
|
||||
public byte[] KeyB { get; set; }
|
||||
|
||||
public byte[] KeyA { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class PowerVuKeyGroup
|
||||
{
|
||||
public uint Coordinate { get; }
|
||||
|
||||
public PowerVuKeyGroup(uint coordinate, ushort groupId)
|
||||
{
|
||||
Coordinate = coordinate;
|
||||
GroupId = groupId;
|
||||
}
|
||||
|
||||
public ushort GroupId { get; set; }
|
||||
|
||||
public bool SetHint(uint coordinate, uint keyType, byte[] key)
|
||||
{
|
||||
if ((coordinate & 0x0000ffff) == 0x0000ffff)
|
||||
{
|
||||
if (keyType == 0)
|
||||
{
|
||||
EcmA = key;
|
||||
return true;
|
||||
}
|
||||
else if (keyType == 1)
|
||||
{
|
||||
EcmB = key;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (_keys == null)
|
||||
_keys = new List<Tuple<uint, uint, byte[]>>();
|
||||
|
||||
_keys.Add(new Tuple<uint, uint, byte[]>(coordinate, keyType, key));
|
||||
return true;
|
||||
}
|
||||
|
||||
public byte[] EcmB { get; set; }
|
||||
|
||||
public byte[] EcmA { get; set; }
|
||||
|
||||
private List<Tuple<uint, uint, byte[]>> _keys;
|
||||
public IReadOnlyList<Tuple<uint, uint, byte[]>> Keys;
|
||||
}
|
||||
}
|
||||
217
skyscraper8/Skyscraper/Security/AccessControl/SoftcamKeyset.cs
Normal file
217
skyscraper8/Skyscraper/Security/AccessControl/SoftcamKeyset.cs
Normal file
@ -0,0 +1,217 @@
|
||||
using log4net;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class SoftcamKeyset
|
||||
{
|
||||
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||
private static SoftcamKeyset _singleton;
|
||||
public static SoftcamKeyset GetInstance()
|
||||
{
|
||||
if (_singleton == null)
|
||||
{
|
||||
_singleton = new SoftcamKeyset();
|
||||
}
|
||||
return _singleton;
|
||||
}
|
||||
|
||||
private FileInfo TryFindSoftcamKey()
|
||||
{
|
||||
foreach (FileInfo fi in GetPossibleLocations())
|
||||
{
|
||||
if (fi.Exists)
|
||||
{
|
||||
return fi;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private const string FILE_NAME = "SoftCam.Key";
|
||||
private IEnumerable<FileInfo> GetPossibleLocations()
|
||||
{
|
||||
FileInfo self = new FileInfo(FILE_NAME);
|
||||
yield return self;
|
||||
|
||||
string assemblyLocation = this.GetType().Assembly.Location;
|
||||
FileInfo assemblyLocationFileInfo = new FileInfo(assemblyLocation);
|
||||
DirectoryInfo assemblyLocationDirectory = assemblyLocationFileInfo.Directory;
|
||||
string assemblyLocationKeyfileName = Path.Combine(assemblyLocationDirectory.FullName, FILE_NAME);
|
||||
yield return new FileInfo(assemblyLocationKeyfileName);
|
||||
|
||||
DirectoryInfo rootDirectory = self.Directory.Root;
|
||||
DirectoryInfo selfDirectory = self.Directory;
|
||||
do
|
||||
{
|
||||
selfDirectory = selfDirectory.Parent;
|
||||
if (selfDirectory == null)
|
||||
break;
|
||||
string possibleName = Path.Combine(selfDirectory.FullName, FILE_NAME);
|
||||
yield return new FileInfo(possibleName);
|
||||
} while (!selfDirectory.Equals(rootDirectory));
|
||||
|
||||
yield return new FileInfo("C:\\FT\\SoftCam_Emu\\SoftCam.Key");
|
||||
}
|
||||
|
||||
private int LoadSoftcamKey(FileInfo fi)
|
||||
{
|
||||
int result = 0;
|
||||
StreamReader streamReader = fi.OpenText();
|
||||
PowerVuKeyGroup currentPowerVuKeyGroup = null;
|
||||
while (!streamReader.EndOfStream)
|
||||
{
|
||||
string line = streamReader.ReadLine();
|
||||
line = line.Trim();
|
||||
if (line.Contains(";"))
|
||||
{
|
||||
int indexOf = line.IndexOf(";");
|
||||
line = line.Substring(0, indexOf);
|
||||
}
|
||||
if (string.IsNullOrEmpty(line))
|
||||
continue;
|
||||
|
||||
char keyType = line[0];
|
||||
string[] split = line.Split(' ');
|
||||
byte[] keyData = null;
|
||||
switch (keyType)
|
||||
{
|
||||
case '#':
|
||||
case ';': //comment
|
||||
break;
|
||||
case '-': //unknown, perhaps seperator?
|
||||
break;
|
||||
case 'V': //Viaccess
|
||||
uint viaccessGroup = split[1].HexToUint32BE();
|
||||
string viaccessKeyType = split[2];
|
||||
keyData = split[3].HexToBytes();
|
||||
|
||||
if (_viaccessKeys == null)
|
||||
_viaccessKeys = new List<ViaccessKey>();
|
||||
ViaccessKey viaccessKey = _viaccessKeys.FirstOrDefault(x => x.Group == viaccessGroup);
|
||||
if (viaccessKey == null)
|
||||
{
|
||||
viaccessKey = new ViaccessKey(viaccessGroup);
|
||||
_viaccessKeys.Add(viaccessKey);
|
||||
}
|
||||
|
||||
if (viaccessKey.SetHint(viaccessKeyType, keyData))
|
||||
result++;
|
||||
break;
|
||||
case 'N':
|
||||
uint nagravisionGroupid = split[1].HexToUint32BE();
|
||||
string nagravisionKeyType = split[2];
|
||||
keyData = split[3].HexToBytes();
|
||||
|
||||
if (_nagravisionKeys == null)
|
||||
_nagravisionKeys = new List<NagravisionKey>();
|
||||
NagravisionKey nagravisionKey = _nagravisionKeys.FirstOrDefault(x => x.Group == nagravisionGroupid);
|
||||
if (nagravisionKey == null)
|
||||
{
|
||||
nagravisionKey = new NagravisionKey(nagravisionGroupid);
|
||||
_nagravisionKeys.Add(nagravisionKey);
|
||||
}
|
||||
|
||||
if (nagravisionKey.SetHint(nagravisionKeyType, keyData))
|
||||
result++;
|
||||
break;
|
||||
case 'T':
|
||||
ushort tandbergChannelId = split[1].HexToUInt16BE();
|
||||
byte tandbergStreamId = split[2].HexToUInt8();
|
||||
keyData = split[3].HexToBytes();
|
||||
|
||||
TandbergKey tandbergKey = new TandbergKey(tandbergChannelId, tandbergStreamId, keyData);
|
||||
if (tandbergKey.Valid)
|
||||
{
|
||||
if (_tandbergKeys == null)
|
||||
_tandbergKeys = new HashSet<TandbergKey>();
|
||||
_tandbergKeys.Add(tandbergKey);
|
||||
result++;
|
||||
}
|
||||
break;
|
||||
case 'P':
|
||||
case 'p':
|
||||
uint powerVuKeyCoordinate = split[1].HexToUint32BE();
|
||||
string powerVuKeyType = split[2];
|
||||
if (powerVuKeyType.Equals("GROUP"))
|
||||
{
|
||||
ushort groupId = split[3].HexToUInt16BE();
|
||||
PowerVuKeyGroup powerVuGroup = new PowerVuKeyGroup(powerVuKeyCoordinate, groupId);
|
||||
currentPowerVuKeyGroup = powerVuGroup;
|
||||
if (_powerVuGroups == null)
|
||||
_powerVuGroups = new List<PowerVuKeyGroup>();
|
||||
_powerVuGroups.Add(currentPowerVuKeyGroup);
|
||||
}
|
||||
else
|
||||
{
|
||||
keyData = split[3].HexToBytes();
|
||||
currentPowerVuKeyGroup.SetHint(powerVuKeyCoordinate, powerVuKeyType.HexToUint32LE(), keyData);
|
||||
result++;
|
||||
}
|
||||
break;
|
||||
case 'F':
|
||||
uint bissCoordinate = split[1].HexToUint32BE();
|
||||
uint bissFixed = split[2].HexToUint32BE();
|
||||
keyData = split[3].HexToBytes();
|
||||
if (bissFixed != 0)
|
||||
{
|
||||
logger.ErrorFormat("I don't understand this key: {0}", line);
|
||||
break;
|
||||
}
|
||||
|
||||
if (_bissKeys == null)
|
||||
_bissKeys = new HashSet<BissKey>();
|
||||
if (_bissKeys.Add(new BissKey(bissCoordinate, keyData)))
|
||||
result++;
|
||||
else
|
||||
logger.ErrorFormat("Duplicate BISS Key for {0}", split[1]);
|
||||
break;
|
||||
default:
|
||||
logger.ErrorFormat("Unknown Key Type \"{0}\". Abort loading key set.",keyType);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool doneFileInitalization;
|
||||
public void InitializeFromFile()
|
||||
{
|
||||
if (doneFileInitalization)
|
||||
{
|
||||
throw new AccessControlException("Softcam.key Keyset already initalized.");
|
||||
}
|
||||
|
||||
doneFileInitalization = true;
|
||||
FileInfo keyLocation = TryFindSoftcamKey();
|
||||
if (keyLocation != null)
|
||||
{
|
||||
logger.InfoFormat("Loading keys from: {0}", keyLocation.FullName);
|
||||
int numKeysLoaded = LoadSoftcamKey(keyLocation);
|
||||
logger.InfoFormat("I suppose you are legally entitled to use those {0} keys I just loaded, You are, right?",numKeysLoaded);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ViaccessKey> _viaccessKeys;
|
||||
public IReadOnlyList<ViaccessKey> ViaccessKeys => _viaccessKeys;
|
||||
|
||||
private List<NagravisionKey> _nagravisionKeys;
|
||||
public IReadOnlyList<NagravisionKey> NagravisionKeys => _nagravisionKeys;
|
||||
|
||||
private HashSet<TandbergKey> _tandbergKeys;
|
||||
public IReadOnlySet<TandbergKey> TandbergKeys => _tandbergKeys;
|
||||
|
||||
private List<PowerVuKeyGroup> _powerVuGroups;
|
||||
public IReadOnlyList<PowerVuKeyGroup> PowerVuGroups => _powerVuGroups;
|
||||
|
||||
private HashSet<BissKey> _bissKeys;
|
||||
public IReadOnlySet<BissKey> BissKeys => _bissKeys;
|
||||
}
|
||||
}
|
||||
54
skyscraper8/Skyscraper/Security/AccessControl/TandbergKey.cs
Normal file
54
skyscraper8/Skyscraper/Security/AccessControl/TandbergKey.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class TandbergKey : Validatable
|
||||
{
|
||||
public ushort ChannelId { get; }
|
||||
public byte StreamId { get; }
|
||||
public byte[] Key { get; }
|
||||
|
||||
public TandbergKey(ushort channelId, byte streamId, byte[] key)
|
||||
{
|
||||
ChannelId = channelId;
|
||||
StreamId = streamId;
|
||||
Key = key;
|
||||
|
||||
if (key == null)
|
||||
Valid = false;
|
||||
else if (key.Length != 8)
|
||||
Valid = false;
|
||||
else
|
||||
Valid = true;
|
||||
}
|
||||
|
||||
protected bool Equals(TandbergKey other)
|
||||
{
|
||||
ulong ourKey = BitConverter.ToUInt64(Key, 0);
|
||||
ulong theirKey = BitConverter.ToUInt64(other.Key, 0);
|
||||
return ChannelId == other.ChannelId && StreamId == other.StreamId && ourKey == theirKey;
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj))
|
||||
return false;
|
||||
if (ReferenceEquals(this, obj))
|
||||
return true;
|
||||
if (obj.GetType() != this.GetType())
|
||||
return false;
|
||||
return Equals((TandbergKey)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
ulong numericKey = BitConverter.ToUInt64(Key, 0);
|
||||
return HashCode.Combine(ChannelId, StreamId, numericKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
78
skyscraper8/Skyscraper/Security/AccessControl/ViaccessKey.cs
Normal file
78
skyscraper8/Skyscraper/Security/AccessControl/ViaccessKey.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security.AccessControl
|
||||
{
|
||||
internal class ViaccessKey : MultipartKey
|
||||
{
|
||||
public ViaccessKey(uint viaccessGroup)
|
||||
{
|
||||
Group = viaccessGroup;
|
||||
}
|
||||
|
||||
public uint Group { get; set; }
|
||||
|
||||
public bool SetHint(string viaccessKeyType, byte[] keyData)
|
||||
{
|
||||
viaccessKeyType = viaccessKeyType.ToUpper();
|
||||
switch (viaccessKeyType)
|
||||
{
|
||||
case "00":
|
||||
case "01":
|
||||
case "02":
|
||||
case "03":
|
||||
case "04":
|
||||
case "05":
|
||||
case "06":
|
||||
case "07":
|
||||
case "08":
|
||||
case "09":
|
||||
case "0A":
|
||||
case "0B":
|
||||
case "0C":
|
||||
case "0D":
|
||||
case "0E":
|
||||
case "0F":
|
||||
uint keyNUmber = viaccessKeyType.HexToUint32BE();
|
||||
keyNUmber >>= 24;
|
||||
if (Keyset == null)
|
||||
Keyset = new byte[16][];
|
||||
Keyset[keyNUmber] = keyData;
|
||||
return true;
|
||||
case "D1":
|
||||
Des1Key = keyData;
|
||||
return true;
|
||||
case "X1":
|
||||
XorArray = keyData;
|
||||
return true;
|
||||
case "P1":
|
||||
PermArray = keyData;
|
||||
return true;
|
||||
case "C1":
|
||||
ChainArray = keyData;
|
||||
return true;
|
||||
case "T1":
|
||||
TransformTable = keyData;
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] TransformTable { get; set; }
|
||||
|
||||
public byte[] ChainArray { get; set; }
|
||||
|
||||
public byte[] PermArray { get; set; }
|
||||
|
||||
public byte[] XorArray { get; set; }
|
||||
|
||||
public byte[] Des1Key { get; set; }
|
||||
|
||||
public byte[][] Keyset { get; private set; }
|
||||
}
|
||||
}
|
||||
@ -24,7 +24,6 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
public DvbCsa2(EntropyMode mode = EntropyMode.REDUCE_ENTROPY)
|
||||
{
|
||||
SetEntropyMode(mode);
|
||||
canProcessInPlace(true);
|
||||
}
|
||||
|
||||
static readonly int[] sbox1 = {
|
||||
@ -75,13 +74,7 @@ namespace skyscraper8.Skyscraper.Security.Cryptography
|
||||
1,0,3,3,0,1,1,2,
|
||||
2,3,1,0,2,3,0,2
|
||||
};
|
||||
|
||||
|
||||
private void canProcessInPlace(bool b)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public void SetEntropyMode(EntropyMode mode)
|
||||
{
|
||||
_mode = mode;
|
||||
|
||||
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Skyscraper.Security
|
||||
{
|
||||
public class SkyscraperSecurityException : SkyscraperCoreException
|
||||
{
|
||||
public SkyscraperSecurityException()
|
||||
{
|
||||
}
|
||||
|
||||
public SkyscraperSecurityException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public SkyscraperSecurityException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -37,5 +37,73 @@ namespace skyscraper5.Skyscraper
|
||||
|
||||
return new string(charArray);
|
||||
}
|
||||
|
||||
public static byte[] HexToBytes(this string hex)
|
||||
{
|
||||
return Enumerable.Range(0, hex.Length)
|
||||
.Where(x => x % 2 == 0)
|
||||
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
public static uint HexToUint32BE(this string hex)
|
||||
{
|
||||
byte[] hexToBytes = hex.HexToBytes();
|
||||
if (hexToBytes.Length < 4)
|
||||
{
|
||||
byte[] better = new byte[4];
|
||||
Array.Copy(hexToBytes, 0, better, 0, hexToBytes.Length);
|
||||
hexToBytes = better;
|
||||
}
|
||||
|
||||
(hexToBytes[3], hexToBytes[2], hexToBytes[1], hexToBytes[0]) = (hexToBytes[0], hexToBytes[1], hexToBytes[2], hexToBytes[3]);
|
||||
return BitConverter.ToUInt32(hexToBytes, 0);
|
||||
}
|
||||
|
||||
public static uint HexToUint32LE(this string hex)
|
||||
{
|
||||
byte[] hexToBytes = hex.HexToBytes();
|
||||
if (hexToBytes.Length < 4)
|
||||
{
|
||||
byte[] better = new byte[4];
|
||||
Array.Copy(hexToBytes, 0, better, 0, hexToBytes.Length);
|
||||
hexToBytes = better;
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt32(hexToBytes, 0);
|
||||
}
|
||||
|
||||
public static ushort HexToUInt16LE(this string hex)
|
||||
{
|
||||
byte[] hexToBytes = hex.HexToBytes();
|
||||
if (hexToBytes.Length < 2)
|
||||
{
|
||||
byte[] better = new byte[2];
|
||||
Array.Copy(hexToBytes, 0, better, 0, hexToBytes.Length);
|
||||
hexToBytes = better;
|
||||
}
|
||||
|
||||
return BitConverter.ToUInt16(hexToBytes, 0);
|
||||
}
|
||||
|
||||
public static ushort HexToUInt16BE(this string hex)
|
||||
{
|
||||
byte[] hexToBytes = hex.HexToBytes();
|
||||
if (hexToBytes.Length < 2)
|
||||
{
|
||||
byte[] better = new byte[2];
|
||||
Array.Copy(hexToBytes, 0, better, 0, hexToBytes.Length);
|
||||
hexToBytes = better;
|
||||
}
|
||||
|
||||
(hexToBytes[1], hexToBytes[0]) = (hexToBytes[0], hexToBytes[1]);
|
||||
return BitConverter.ToUInt16(hexToBytes, 0);
|
||||
}
|
||||
|
||||
public static byte HexToUInt8(this string hex)
|
||||
{
|
||||
byte[] hexToBytes = hex.HexToBytes();
|
||||
return hexToBytes[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user