Skip to content

Commit abe3ac2

Browse files
committed
2 parents 50ce24a + ed55dc3 commit abe3ac2

File tree

6 files changed

+41
-35
lines changed

6 files changed

+41
-35
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ Add WinUI 3 Publish.
3030

3131
Async optimize on RC4 Stream
3232

33+
Add linux Support
34+
3335

3436
### v2.2.0 2024.03.24
3537

src/NCMDumpCLI/NCMDumpCLI.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<ApplicationManifest>app.manifest</ApplicationManifest>
1111
<Version>2.3.0</Version>
1212
<Platforms>x64</Platforms>
13+
<PublishAot>False</PublishAot>
1314
</PropertyGroup>
1415

1516

src/NCMDumpCore/NCMDumper.cs

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ namespace NCMDumpCore
1111
public class NCMDumper
1212
{
1313
private readonly int vectorSize = Vector256<byte>.Count;
14-
private readonly byte[] coreKey = { 0x68, 0x7A, 0x48, 0x52, 0x41, 0x6D, 0x73, 0x6F, 0x35, 0x6B, 0x49, 0x6E, 0x62, 0x61, 0x78, 0x57 };
15-
private readonly byte[] metaKey = { 0x23, 0x31, 0x34, 0x6C, 0x6A, 0x6B, 0x5F, 0x21, 0x5C, 0x5D, 0x26, 0x30, 0x55, 0x3C, 0x27, 0x28 };
14+
private readonly byte[] coreKey = [0x68, 0x7A, 0x48, 0x52, 0x41, 0x6D, 0x73, 0x6F, 0x35, 0x6B, 0x49, 0x6E, 0x62, 0x61, 0x78, 0x57];
15+
private readonly byte[] metaKey = [0x23, 0x31, 0x34, 0x6C, 0x6A, 0x6B, 0x5F, 0x21, 0x5C, 0x5D, 0x26, 0x30, 0x55, 0x3C, 0x27, 0x28];
1616

1717
private bool VerifyHeader(ref MemoryStream ms)
1818
{
@@ -35,7 +35,7 @@ private byte[] ReadRC4Key(ref MemoryStream ms)
3535
ms.Read(buffer);
3636

3737
//SIMD XOR 0x64
38-
Vector256<byte> xor = Vector256.Create(0x64646464).AsByte();
38+
Vector256<byte> xor = Vector256.Create((byte)0x64);
3939
int i;
4040
for (i = 0; i <= buffer.Length - vectorSize; i += vectorSize)
4141
{
@@ -49,11 +49,13 @@ private byte[] ReadRC4Key(ref MemoryStream ms)
4949
}
5050

5151
// decrypt keybox data
52-
using (var decrypter = new AesCng() { Key = coreKey, Mode = CipherMode.ECB }.CreateDecryptor())
52+
using (Aes aes = Aes.Create())
5353
{
54-
buffer = decrypter.TransformFinalBlock(buffer.ToArray(), 0, buffer.Length).Skip(17).ToArray(); // 17 = len("neteasecloudmusic")
54+
aes.Mode = CipherMode.ECB;
55+
aes.Key = coreKey;
56+
var cleanText = aes.DecryptEcb(buffer.ToArray(), PaddingMode.PKCS7).ToArray()[17..];
57+
return cleanText;
5558
}
56-
return buffer.ToArray();
5759
}
5860

5961
private MetaInfo ReadMeta(ref MemoryStream ms)
@@ -65,7 +67,7 @@ private MetaInfo ReadMeta(ref MemoryStream ms)
6567
ms.Read(buffer);
6668

6769
//SIMD XOR 0x63
68-
Vector256<byte> xor = Vector256.Create(0x63636363).AsByte();
70+
Vector256<byte> xor = Vector256.Create((byte)0x63);
6971
int i;
7072
for (i = 0; i <= buffer.Length - vectorSize; i += vectorSize)
7173
{
@@ -81,21 +83,23 @@ private MetaInfo ReadMeta(ref MemoryStream ms)
8183
buffer = System.Convert.FromBase64String(Encoding.ASCII.GetString(buffer.ToArray()[22..]));
8284

8385
// decrypt meta data which is a json contains info of the song
84-
using (var cryptor = new AesCng() { Key = metaKey, Mode = CipherMode.ECB }.CreateDecryptor())
86+
using (Aes aes = Aes.Create())
8587
{
86-
buffer = cryptor.TransformFinalBlock(buffer.ToArray(), 0, buffer.Length);
87-
var MetaJsonString = Encoding.UTF8.GetString(buffer).Replace("music:", "");
88+
aes.Mode = CipherMode.ECB;
89+
aes.Key = metaKey;
90+
var cleanText = aes.DecryptEcb(buffer.ToArray(), PaddingMode.PKCS7);
91+
var MetaJsonString = Encoding.UTF8.GetString(cleanText[6..]);
8892
MetaInfo metainfo = JsonSerializer.Deserialize<MetaInfo>(MetaJsonString);
8993
return metainfo;
9094
}
9195
}
9296

9397
private async Task<byte[]> ReadAudioData(MemoryStream ms, byte[] Key)
9498
{
95-
using (RC4_NCM_Stream rc4s = new RC4_NCM_Stream(ms, Key))
99+
using (RC4_NCM_Stream rc4s = new(ms, Key))
96100
{
97101
byte[] data = new byte[ms.Length - ms.Position];
98-
Memory<byte> m_data = new Memory<byte>(data);
102+
Memory<byte> m_data = new(data);
99103
await rc4s.ReadAsync(m_data);
100104
return data;
101105
}
@@ -122,7 +126,7 @@ private void AddTag(string fileName, byte[]? ImgData, MetaInfo metainfo)
122126
}
123127
}
124128

125-
//Add more infomation
129+
//Add more information
126130
tagfile.Tag.Title = metainfo.musicName;
127131
tagfile.Tag.Performers = metainfo.artist.Select(x => x[0]).ToArray();
128132
tagfile.Tag.Album = metainfo.album;
@@ -132,7 +136,7 @@ private void AddTag(string fileName, byte[]? ImgData, MetaInfo metainfo)
132136

133137
private byte[]? FetchUrl(Uri uri)
134138
{
135-
HttpClient client = new HttpClient();
139+
HttpClient client = new();
136140
try
137141
{
138142
var response = client.GetAsync(uri).Result;
@@ -182,7 +186,7 @@ public async Task<bool> ConvertAsync(string path)
182186
}
183187

184188
//Read all bytes to ram.
185-
MemoryStream ms = new MemoryStream(await System.IO.File.ReadAllBytesAsync(path));
189+
MemoryStream ms = new(await System.IO.File.ReadAllBytesAsync(path));
186190

187191
//Verify Header
188192
if (!VerifyHeader(ref ms))
@@ -201,9 +205,7 @@ public async Task<bool> ConvertAsync(string path)
201205
MetaInfo metainfo = ReadMeta(ref ms);
202206

203207
//CRC32 Check
204-
var crc32bytes = new byte[4];
205-
ms.Read(crc32bytes, 0, crc32bytes.Length);
206-
var crc32len = MemoryMarshal.Read<int>(crc32bytes);
208+
uint crc32 = ReadUint32(ref ms);
207209

208210
// skip 5 character,
209211
ms.Seek(5, SeekOrigin.Current);
@@ -226,16 +228,15 @@ public async Task<bool> ConvertAsync(string path)
226228
byte[] AudioData = await ReadAudioData(ms, RC4Key);
227229

228230
//Flush Audio Data to disk drive
229-
string OutputPath = path.Substring(0, path.LastIndexOf("."));
231+
string OutputPath = path[..path.LastIndexOf('.')];
230232

231233
string format = metainfo.format;
232234
if (format is null or "") format = "mp3";
233235
await System.IO.File.WriteAllBytesAsync($"{OutputPath}.{format}", AudioData);
234236

235237
//Add tag and cover
236238
await Task.Run(() => AddTag($"{OutputPath}.{format}", ImageData, metainfo));
237-
ms.Flush();
238-
ms.Close();
239+
await ms.DisposeAsync();
239240
return true;
240241
}
241242
}

src/NCMDumpCore/RC4_NCM.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
{
33
public class RC4_NCM
44
{
5-
private byte[] Keybox;
5+
private readonly byte[] Keybox;
66
private int i = 0, j = 0;
77

88
public RC4_NCM(byte[] key)
@@ -19,7 +19,7 @@ public RC4_NCM(byte[] key)
1919

2020
public byte[] Encrypt(byte[] data)
2121
{
22-
Span<byte> span = new Span<byte>(data);
22+
Span<byte> span = new(data);
2323
Encrypt(ref span);
2424
return span.ToArray();
2525
}

src/NCMDumpCore/RC4_NCM_Stream.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
namespace NCMDumpCore
22
{
3-
internal class RC4_NCM_Stream : Stream
3+
public class RC4_NCM_Stream : Stream
44
{
5-
private Stream innerStream;
6-
private RC4_NCM rc4;
5+
private readonly Stream innerStream;
6+
private readonly RC4_NCM rc4;
77

88
public RC4_NCM_Stream(Stream innerStream, byte[] key)
99
{
@@ -73,16 +73,16 @@ public override void SetLength(long value)
7373

7474
public override void Write(byte[] buffer, int offset, int count)
7575
{
76-
Span<byte> span = buffer[offset..(offset + count)];
77-
int bytesWrite = rc4.Encrypt(ref span);
76+
Span<byte> span = buffer.AsSpan(offset, count);
77+
rc4.Encrypt(ref span);
7878
innerStream.Write(span);
7979
}
8080

8181
public override void Write(ReadOnlySpan<byte> buffer)
8282
{
8383
Span<byte> span = new byte[buffer.Length];
8484
buffer.CopyTo(span);
85-
int bytesWrite = rc4.Encrypt(ref span);
85+
rc4.Encrypt(ref span);
8686

8787
innerStream.Write(buffer);
8888
}
@@ -91,15 +91,15 @@ public override async Task WriteAsync(byte[] data, int offset, int count, Cancel
9191
{
9292
byte[] buffer = data[offset..(offset + count)];
9393
byte[] encrypted = await Task.Run(() => rc4.Encrypt(buffer));
94-
await innerStream.WriteAsync(encrypted);
94+
await innerStream.WriteAsync(encrypted, cancellationToken);
9595
return;
9696
}
9797

9898
public override async ValueTask WriteAsync(ReadOnlyMemory<byte> data, CancellationToken cancellationToken = default)
9999
{
100100
byte[] buffer = data.ToArray();
101101
await Task.Run(() => rc4.Encrypt(buffer));
102-
await innerStream.WriteAsync(buffer);
102+
await innerStream.WriteAsync(buffer, cancellationToken);
103103
return;
104104
}
105105
}

src/NCMDumpGUI/MainWindowViewModel.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public MainWindowViewModel(NCMDumper _core)
7171
Core = _core;
7272
WillDeleteNCM = true;
7373
ApplicationTitle = "NCMDump.NET";
74-
NCMCollection = new();
74+
NCMCollection = [];
7575
AddFolderCommand = new AsyncRelayCommand(FolderDialog);
7676
AddFileCommand = new AsyncRelayCommand(FileDialog);
7777
ClearCommand = new AsyncRelayCommand(ClearList, () => NCMCollection.Count > 0);
@@ -191,9 +191,11 @@ private async Task FolderDialog()
191191

192192
private async Task FileDialog()
193193
{
194-
Microsoft.Win32.OpenFileDialog ofp = new();
195-
ofp.Multiselect = true;
196-
ofp.Filter = "NCM File(*.ncm)|*.ncm";
194+
Microsoft.Win32.OpenFileDialog ofp = new()
195+
{
196+
Multiselect = true,
197+
Filter = "NCM File(*.ncm)|*.ncm"
198+
};
197199
if (ofp.ShowDialog() == true)
198200
{
199201
foreach (string file in ofp.FileNames)

0 commit comments

Comments
 (0)