diff --git a/.example-config b/.example-config index dab8846..a81e41e 100644 --- a/.example-config +++ b/.example-config @@ -1,4 +1,2 @@ arl_cookie = '1d9e90abb452a61b1b7463f0953e1b303c4e2e7e5fd404fde9b385f4de01c340ac0f62f1c8c1550405b0b9beded0e28c481e96a6148e8f4548351add5d7db746b2785ecf83b1768e5dd8cc73b1ad30c18d07c9cb37f5c6b9cd7a78a4de2aff11' -license_token = 'AAAAA1bcDFgHJKLmnOPqrsTUvwXYZ12o3lmNOjR2xWiQRT3v5zxL4mKoWjxL82jD7sWx93KfYGsN2IkdPxsUw9PTas7oFbgR3nY9qpZmVyHFJKLPxT7sWmqErXyTn5iKoNpRtV7bPdQZ8qLmWoJpU2nKrXz6vW' secret_key = 'hTv1IAw19qWy9i3f' -iv = '0001020304050607' \ No newline at end of file diff --git a/internal/config/config.go b/internal/config/config.go index e3bc16f..0aa813d 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -11,7 +11,6 @@ import ( type Config struct { ArlCookie string `mapstructure:"arl_cookie"` SecretKey string `mapstructure:"secret_key"` - IV string `mapstructure:"iv"` } func New(cfgPath, cfgDir string) (*Config, error) { @@ -22,7 +21,7 @@ func New(cfgPath, cfgDir string) (*Config, error) { if _, err := os.Stat(cfgPath); os.IsNotExist(err) { fmt.Printf("Config file not found, creating one at %s\n", cfgPath) - content := []byte("arl_cookie = ''\nsecret_key = ''\niv = '0001020304050607'\n") + content := []byte("arl_cookie = ''\nsecret_key = ''\n") if err := os.WriteFile(cfgPath, content, 0644); err != nil { return nil, fmt.Errorf("failed to create config file: %w", err) } @@ -52,12 +51,6 @@ func New(cfgPath, cfgDir string) (*Config, error) { if len(cfg.SecretKey) != 16 { return nil, fmt.Errorf("secret_key must be 16 bytes long") } - if cfg.IV == "" { - return nil, fmt.Errorf("iv is not set in config file") - } - if len(cfg.IV) != 16 { - return nil, fmt.Errorf("iv must be 16 bytes long") - } return cfg, nil } diff --git a/internal/crypto/blowfish.go b/internal/crypto/blowfish.go index 09a06cb..e6704a8 100644 --- a/internal/crypto/blowfish.go +++ b/internal/crypto/blowfish.go @@ -8,6 +8,8 @@ import ( "golang.org/x/crypto/blowfish" ) +var iv = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07} + func GetKey(secretKey, songID string) []byte { hash := md5.Sum([]byte(songID)) hashHex := fmt.Sprintf("%x", hash) @@ -20,7 +22,7 @@ func GetKey(secretKey, songID string) []byte { return key } -func Decrypt(data, key, iv []byte) ([]byte, error) { +func Decrypt(data, key []byte) ([]byte, error) { block, err := blowfish.NewCipher(key) if err != nil { return nil, err diff --git a/internal/downloader/client.go b/internal/downloader/client.go index afd7cf3..06a72bb 100644 --- a/internal/downloader/client.go +++ b/internal/downloader/client.go @@ -2,7 +2,6 @@ package downloader import ( "context" - "encoding/hex" "errors" "fmt" "io" @@ -20,7 +19,7 @@ import ( "github.com/mathismqn/godeez/internal/tags" ) -const ChunkSize = 2048 +const chunkSize = 2048 type Client struct { appCtx *app.Context @@ -135,7 +134,8 @@ func (c *Client) downloadSong(ctx context.Context, resource deezer.Resource, son dlCtx, cancel := context.WithTimeout(ctx, opts.Timeout) defer cancel() - if err := c.streamToFile(dlCtx, stream, outputPath, song.ID); err != nil { + key := crypto.GetKey(c.appCtx.Config.SecretKey, song.ID) + if err := c.streamToFile(dlCtx, stream, outputPath, key); err != nil { fileutil.DeleteFile(outputPath) return fmt.Errorf("unable to write to file: %w", err) @@ -180,7 +180,7 @@ func (c *Client) shouldSkipDownload(ctx context.Context, songID, mediaFormat str return "", false } -func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputPath, songID string) error { +func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputPath string, key []byte) error { defer stream.Close() file, err := os.Create(outputPath) @@ -189,13 +189,7 @@ func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputP } defer file.Close() - key := crypto.GetKey(c.appCtx.Config.SecretKey, songID) - iv, err := hex.DecodeString(c.appCtx.Config.IV) - if err != nil { - return err - } - - buffer := make([]byte, ChunkSize) + buffer := make([]byte, chunkSize) for chunk := 0; ; chunk++ { select { case <-ctx.Done(): @@ -205,7 +199,7 @@ func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputP } totalRead := 0 - for totalRead < ChunkSize { + for totalRead < chunkSize { n, err := stream.Read(buffer[totalRead:]) if err != nil { if errors.Is(err, io.EOF) { @@ -223,8 +217,8 @@ func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputP break } - if chunk%3 == 0 && totalRead == ChunkSize { - buffer, err = crypto.Decrypt(buffer, key, iv) + if chunk%3 == 0 && totalRead == chunkSize { + buffer, err = crypto.Decrypt(buffer, key) if err != nil { return err } @@ -235,7 +229,7 @@ func (c *Client) streamToFile(ctx context.Context, stream io.ReadCloser, outputP return err } - if totalRead < ChunkSize { + if totalRead < chunkSize { break } }