VRFS-2481 : Jam Tracks python layer and source.
This commit is contained in:
parent
f6fef00ea5
commit
ac2daed4da
|
|
@ -0,0 +1 @@
|
|||
{"SKU": "0044454545454", "METADATA_VER": 1, "TrackData": {"track_2": {"length": 0.1, "bitrate": 96000}, "track_1": {"length": 264.5681632653061, "bitrate": 128003}, "track_0": {"length": 405.054693877551, "bitrate": 128003}}, "TrackInstrument": {"track_1": "Alto Sax", "track_0": "Bass Guitar"}, "Title": "SmFtS2F6YW0gcm9sbGluZyBpbiB0aGUgZG91Z2g="}
|
||||
|
|
@ -74,6 +74,7 @@ require "jam_ruby/app/uploaders/mix_uploader"
|
|||
require "jam_ruby/app/uploaders/music_notation_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_track_uploader"
|
||||
require "jam_ruby/app/uploaders/jam_track_right_uploader"
|
||||
require "jam_ruby/app/uploaders/max_mind_release_uploader"
|
||||
require "jam_ruby/lib/desk_multipass"
|
||||
require "jam_ruby/lib/ip"
|
||||
|
|
@ -189,6 +190,7 @@ require "jam_ruby/models/jam_company"
|
|||
require "jam_ruby/models/user_sync"
|
||||
require "jam_ruby/models/video_source"
|
||||
require "jam_ruby/models/recorded_video"
|
||||
require "jam_ruby/jam_tracks_manager"
|
||||
|
||||
include Jampb
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
class JamTrackRightUploader < CarrierWave::Uploader::Base
|
||||
# include CarrierWaveDirect::Uploader
|
||||
include CarrierWave::MimeTypes
|
||||
|
||||
process :set_content_type
|
||||
|
||||
def initialize(*)
|
||||
super
|
||||
JamRuby::UploaderConfiguration.set_aws_private_configuration(self)
|
||||
end
|
||||
|
||||
# Add a white list of extensions which are allowed to be uploaded.
|
||||
def extension_white_list
|
||||
%w(jkz)
|
||||
end
|
||||
|
||||
def store_dir
|
||||
nil
|
||||
end
|
||||
|
||||
def md5
|
||||
@md5 ||= ::Digest::MD5.file(current_path).hexdigest
|
||||
end
|
||||
|
||||
def filename
|
||||
"#{model.store_dir}/#{model.filename}" if model.id
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
module JamRuby
|
||||
|
||||
# describes an audio track (like the drums, or guitar) that comprises a JamTrack
|
||||
class JamTracksManager
|
||||
class << self
|
||||
def save_jam_track(jam_track, user)
|
||||
spec = Gem::Specification.find_by_name("jam_ruby")
|
||||
py_root = spec.gem_dir + "/lib/py/jam_tracks/"
|
||||
puts "Executing python in #{py_root}"
|
||||
|
||||
sku=""#jam_track.sku
|
||||
public_key=""
|
||||
private_key=""
|
||||
tracks_filename=""
|
||||
output_jkz=""
|
||||
title=""
|
||||
`python #{py_root}jkcreate.py -D -k #{sku} -c art.png -p #{public_key} -s #{private_key} -I #{tracks_filename} -o #{output_jkz} -t '#{title}'`
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@ module JamRuby
|
|||
|
||||
# describes what users have rights to which tracks
|
||||
class JamTrackRight < ActiveRecord::Base
|
||||
attr_accessible :user, :jam_track, :user_id, :jam_track_id
|
||||
attr_accessible :user, :jam_track, :user_id, :jam_track_id, :url, :md5, :length, :download_count
|
||||
belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track
|
||||
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
|
||||
|
||||
|
|
@ -11,6 +11,10 @@ module JamRuby
|
|||
validate :verify_download_count
|
||||
|
||||
validates_uniqueness_of :user_id, scope: :jam_track_id
|
||||
|
||||
# Uploads the JKZ:
|
||||
mount_uploader :url, JamTrackRightUploader
|
||||
|
||||
MAX_JAM_TRACK_DOWNLOADS = 1000
|
||||
|
||||
def verify_download_count
|
||||
|
|
@ -18,5 +22,11 @@ module JamRuby
|
|||
errors.add(:download_count, "must be less than or equal to #{MAX_JAM_TRACK_DOWNLOADS}")
|
||||
end
|
||||
end
|
||||
|
||||
# Create user-specific JKZ for the associated jam_track:
|
||||
def create_jkz
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
{"SKU": "0044454545454", "METADATA_VER": 1, "TrackData": {"track_2": {"length": 0.1, "bitrate": 96000}, "track_1": {"length": 264.5681632653061, "bitrate": 128003}, "track_0": {"length": 405.054693877551, "bitrate": 128003}}, "TrackInstrument": {"track_1": "Alto Sax", "track_0": "Bass Guitar"}, "Title": "SmFtS2F6YW0gcm9sbGluZyBpbiB0aGUgZG91Z2g="}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Bass.ogg+Bass
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Drums.ogg+Drums
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Guitar - Main.ogg+Guitar Main
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Guitar - Rhythm 2.ogg+Guitar Rhythm 2
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Guitar - Rhythm.ogg+Guitar Rhythm
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Guitar - Solo.ogg+Guitar Solo
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Vocals - Background.ogg+Vocals Background
|
||||
You Shook Me All Night Long/You Shook Me All Night Long Stem - Vocals - Lead.ogg+Vocals Lead
|
||||
|
|
@ -0,0 +1,212 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto import Random
|
||||
import base64
|
||||
import os
|
||||
import binascii
|
||||
import json
|
||||
import sys
|
||||
|
||||
class JKaes:
|
||||
|
||||
# the key size for the cipher object; must be 16, 24, or 32 for AES
|
||||
KEY_SIZE = 16
|
||||
#always 16 bytes for aes
|
||||
BLOCK_SIZE = 16
|
||||
|
||||
# the character used for padding--with a block cipher such as AES, the value
|
||||
# you encrypt must be a multiple of BLOCK_SIZE in length. This character is
|
||||
# used to ensure that your value is always a multiple of BLOCK_SIZE
|
||||
#PADDING_CHARACTER = '{'
|
||||
PADDING_CHARACTER = b'0'
|
||||
PADDING = 0
|
||||
op = 'encode'
|
||||
musicFile = ''
|
||||
|
||||
KEY=''
|
||||
IV=''
|
||||
|
||||
CIPHER_MODE = AES.MODE_CBC
|
||||
# CIPHER_MODE = AES.MODE_CFB
|
||||
|
||||
def __init__(self, fileName, keyFile='',operation='encode'):
|
||||
self.op = operation
|
||||
self.musicFile = fileName
|
||||
if len(keyFile) != 0:
|
||||
self.initKeyFromFile(keyFile)
|
||||
else:
|
||||
if operation == 'encode':
|
||||
self.generateNewKeys()
|
||||
|
||||
# one-liner to sufficiently pad the text to be encrypted
|
||||
def updatePadSize(self,dlen):
|
||||
self.PADDING = (self.BLOCK_SIZE - dlen % self.BLOCK_SIZE)
|
||||
|
||||
def getPadding(self):
|
||||
return self.PADDING
|
||||
|
||||
def pad(self,s):
|
||||
self.updatePadSize(len(s))
|
||||
pdata = self.PADDING * self.PADDING_CHARACTER
|
||||
if len(pdata) != self.PADDING :
|
||||
sys.exit('Pad data length %d does match %d. Check python pad character size!' %
|
||||
(len(pdata), self.PADDING))
|
||||
s = s + pdata
|
||||
return s
|
||||
|
||||
def EncodeAEStoB64(self,c, s):
|
||||
return base64.b64encode(c.encrypt(self.pad(s)))
|
||||
|
||||
def b64DecodeAES(self,c, e):
|
||||
return c.decrypt(base64.b64decode(e)).rstrip(self.PADDING_CHARACTER)
|
||||
|
||||
|
||||
def initKeyFromFile(self,fname):
|
||||
(self.KEY,self.IV)= self.readAesKeyFile(fname)
|
||||
|
||||
def generateNewKeys(self):
|
||||
self.KEY = self.generateAesKey();
|
||||
self.IV = self.generateAesIv()
|
||||
|
||||
def generateAesKey(self,keySize=KEY_SIZE):
|
||||
# generate a random secret key
|
||||
#secret = Random.get_random_bytes(keySize)
|
||||
secret = Random.new().read(keySize)
|
||||
return secret
|
||||
|
||||
def generateAesIv(self):
|
||||
secret = Random.new().read(AES.block_size)
|
||||
return secret
|
||||
|
||||
def getKeyStr(self):
|
||||
str = '%s_%s_%s' % (len(self.KEY),base64.b64encode(self.IV),base64.b64encode(self.KEY))
|
||||
#print 'okey=',str
|
||||
return str
|
||||
def getKeyModeStr(self):
|
||||
if self.CIPHER_MODE == AES.MODE_CBC:
|
||||
return 'CBC'
|
||||
elif self.CIPHER_MODE == AES.MODE_CFB:
|
||||
return 'CFB'
|
||||
else:
|
||||
sys.exit('Bad AES key mode')
|
||||
|
||||
def setKey(self, content):
|
||||
(keySize, ivstr, keystr) = content.split('_')
|
||||
#print 'ikey=',content
|
||||
self.IV = base64.b64decode(ivstr)
|
||||
self.KEY = base64.b64decode(keystr)
|
||||
|
||||
def writeAesKeytoFile(self, iv,key,Keyfilename):
|
||||
#initialization vector - iv
|
||||
#key - must be the same size as the iv
|
||||
#output filename
|
||||
str = '%s_%s_%s' % (len(key),base64.b64encode(iv),base64.b64encode(key))
|
||||
#print 'okey=',str
|
||||
fo = open(Keyfilename, 'w')
|
||||
fo.write(str)
|
||||
fo.close()
|
||||
|
||||
def writeAesKeytoFile(self,Keyfilename):
|
||||
self.writeAesKeytoFile(self.IV,self.KEY,Keyfilename)
|
||||
|
||||
def readAesKeyFile(self,keyFilename):
|
||||
# Given the filename of a file that contains a public or private key,
|
||||
# return the key as a (n,e) or (n,d) tuple value.
|
||||
fo = open(keyFilename)
|
||||
content = fo.read()
|
||||
fo.close()
|
||||
(keySize, ivstr, keystr) = content.split('_')
|
||||
|
||||
#print 'ikey=',content
|
||||
iv = base64.b64decode(ivstr)
|
||||
key = base64.b64decode(keystr)
|
||||
return (int(keySize), iv, key)
|
||||
|
||||
|
||||
def WriteFileData(self,outfile,data):
|
||||
#ddata = base64.b64decode(data)
|
||||
fi = open(outfile,'wb')
|
||||
fi.write(data);
|
||||
|
||||
def LoadFileData(self, infile):
|
||||
fi = open(infile,'rb')
|
||||
data = fi.read();
|
||||
return data
|
||||
#edata = base64.b64encode(data)
|
||||
#return edata
|
||||
|
||||
|
||||
def WriteAesFileData(self, outfile,data):
|
||||
# These files are assumed to be in cypher text - so we won't b64 encode/decode them
|
||||
fo = open(outfile,'wb')
|
||||
fo.write(data)
|
||||
|
||||
def LoadAesFileData(self, infile):
|
||||
# These files are assumed to be in cypher text - so we won't b64 encode/decode them
|
||||
fi = open(infile,'rb')
|
||||
data = fi.read();
|
||||
return data
|
||||
|
||||
def EncodeFileToMsgWithKey(self, key, iv, infile):
|
||||
infileData = self.LoadFileData(infile)
|
||||
pdata = self.pad(infileData)
|
||||
cipher = AES.new(key, self.CIPHER_MODE, iv)
|
||||
msg = cipher.encrypt(pdata)
|
||||
return msg
|
||||
|
||||
|
||||
def EncodeFileWithKeyAndWrite(self, key, iv, infile,outFile):
|
||||
msg = self.EncodeFileToMsgWithKey(key, iv, infile)
|
||||
self.WriteAesFileData(outFile,msg)
|
||||
return msg
|
||||
|
||||
def EncodeFileToMsg(self, infile):
|
||||
infileData = self.LoadFileData(infile)
|
||||
# file data must be in plain text
|
||||
pdata = self.pad(infileData)
|
||||
cipher = AES.new(self.KEY, self.CIPHER_MODE, self.IV)
|
||||
msg = cipher.encrypt(pdata)
|
||||
return msg
|
||||
|
||||
|
||||
def EncodeFileAndWrite(self, infile,outFile):
|
||||
edata = self.EncodeFileToMsg(infile)
|
||||
self.WriteAesFileData(outFile,edata)
|
||||
#return edata
|
||||
|
||||
def DecodeFileToMsgWithKey(self,key, iv, infile):
|
||||
infileData = self.LoadAesFileData(infile)
|
||||
cipher = AES.new(key, self.CIPHER_MODE, iv)
|
||||
#expects the file to have the right number of blocks
|
||||
data = cipher.decrypt(infileData)
|
||||
return data
|
||||
|
||||
def DecodeFileWithKeyAndWrite(self,key, iv, infile,outFile):
|
||||
msg = self.DecodeFileToMsgWithKey(key, iv, infile)
|
||||
self.WriteFileData(outFile,msg)
|
||||
|
||||
def DecodeFileToMsg(self, infile):
|
||||
msg = self.DecodeFileToMsgWithKey(self.KEY, self.IV, infile)
|
||||
return msg
|
||||
|
||||
def DecodeFileAndWrite(self, infile,outFile):
|
||||
data = self.DecodeFileToMsg(infile)
|
||||
self.WriteFileData(outFile,data)
|
||||
#return data
|
||||
|
||||
def DecodeMsg(self, pdata):
|
||||
cipher = AES.new(self.KEY,self.CIPHER_MODE, self.IV)
|
||||
data = cipher.decrypt(pdata)
|
||||
return data
|
||||
|
||||
def DecodeU64Msg(self, pdata):
|
||||
cipher = AES.new(self.KEY, self.CIPHER_MODE, self.IV)
|
||||
data = self.b64DecodeAES(cipher, pdata)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,431 @@
|
|||
import json
|
||||
from jktrack import JKtrack
|
||||
from jkrsa import JKrsa
|
||||
from pprint import pprint
|
||||
import sys
|
||||
import os
|
||||
import zipfile
|
||||
import random
|
||||
import base64
|
||||
import tempfile
|
||||
import datetime
|
||||
import zipfile
|
||||
import filecmp
|
||||
|
||||
#debug flags
|
||||
DEBUG_ENABLE = 0
|
||||
COMPARE_PARSEFILE = False
|
||||
|
||||
|
||||
JAMTRACK_PACKAGE_VERSION = 1
|
||||
JAMTRACK_PACKAGE_INFO_FILE = 'jamtrack.info'
|
||||
JAMTRACK_MEDIA_META_FILE = 'media_meta.info'
|
||||
JAMTRACK_COVER_ART_TAG ='cover_art'
|
||||
|
||||
def print_info(archive_name):
|
||||
zf = zipfile.ZipFile(archive_name)
|
||||
for info in zf.infolist():
|
||||
print info.filename
|
||||
print '\tComment:\t', info.comment
|
||||
print '\tModified:\t', datetime.datetime(*info.date_time)
|
||||
print '\tSystem:\t\t', info.create_system, '(0 = Windows, 3 = Unix)'
|
||||
print '\tZIP version:\t', info.create_version
|
||||
print '\tCompressed:\t', info.compress_size, 'bytes'
|
||||
print '\tUncompressed:\t', info.file_size, 'bytes'
|
||||
print
|
||||
|
||||
import zipfile
|
||||
try:
|
||||
import zlib
|
||||
compression = zipfile.ZIP_DEFLATED
|
||||
except:
|
||||
compression = zipfile.ZIP_STORED
|
||||
|
||||
modes = { zipfile.ZIP_DEFLATED: 'deflated',
|
||||
zipfile.ZIP_STORED: 'stored',
|
||||
}
|
||||
#use store - the encrypted files really does not gain from any zlib attempt to encrypt
|
||||
compression = zipfile.ZIP_STORED
|
||||
|
||||
class JKasset:
|
||||
rawMediaFiles=[]
|
||||
encryptedMediaFiles = []
|
||||
mediaAesKeyFile = []
|
||||
packageFileInfo = ''
|
||||
otherAssetFile = ''
|
||||
coverArtFile=''
|
||||
encryptedCoverFile =''
|
||||
rsaPubKeyFile=''
|
||||
rsaPrivKeyFile=''
|
||||
outputPackageFile=''
|
||||
packageFileName=''
|
||||
def __init__(self, fileName, operation='encode', pubRsaKeyFile=''):
|
||||
self.op = operation
|
||||
self.packageFileInfo = fileName
|
||||
if operation == 'encode':
|
||||
self.loadEncodeContainerData()
|
||||
self.generateContainer()
|
||||
if operation == 'decode':
|
||||
# print fileName
|
||||
#self.loadDecodeContainerData()
|
||||
self.parseContainer(pubRsaKeyFile)
|
||||
|
||||
def loadEncodeContainerData(self):
|
||||
json_data=open(self.packageFileInfo)
|
||||
jdata = json.load(json_data)
|
||||
print
|
||||
pprint(jdata)
|
||||
json_data.close()
|
||||
|
||||
self.rawMediaFiles = jdata['tracks']
|
||||
|
||||
if len(self.rawMediaFiles) == 0:
|
||||
sys.exit('ERROR: No tracks specified.')
|
||||
|
||||
try:
|
||||
self.mediaAesKeyFile = jdata['aesKeyFiles']
|
||||
except:
|
||||
print "no aes key file "
|
||||
|
||||
self.otherAssetFile = jdata["jamktrack_info"]
|
||||
if len(self.otherAssetFile) == 0:
|
||||
sys.exit('ERROR: No JamTrack infoFile specified.')
|
||||
|
||||
self.rsaPrivKeyFile = jdata['rsa_priv_file']
|
||||
self.rsaPubKeyFile = jdata["rsa_pub_file"]
|
||||
|
||||
if len(self.rsaPubKeyFile) == 0:
|
||||
sys.exit('ERROR: A RSA pubkey file must be specified.')
|
||||
|
||||
self.outputPackageFile = jdata['container_file']
|
||||
if len(self.outputPackageFile) == 0:
|
||||
sys.exit('ERROR: A output container file must be specified.')
|
||||
|
||||
try:
|
||||
self.coverArtFile = jdata['coverart']
|
||||
except:
|
||||
print 'no covert art file'
|
||||
|
||||
def encodeMediaFiles(self):
|
||||
|
||||
for mediaFileInfo in self.rawMediaFiles:
|
||||
print 'mediaFileInfo:',mediaFileInfo
|
||||
##the file, and track name
|
||||
mediaFile = JKtrack(mediaFileInfo["name"],mediaFileInfo["trackName"])
|
||||
if not self.mediaAesKeyFile :
|
||||
mediaFile.EncodeToTmpFile();
|
||||
else:
|
||||
mediaFile.setKey(self.mediaAesKeyFile)
|
||||
mediaFile.EncodeToTmpFile();
|
||||
|
||||
self.encryptedMediaFiles.append(mediaFile)
|
||||
|
||||
# Debug: save a copy of the encoded file
|
||||
# mediaFile.saveEncFileCopy('enc_'+mediaFileInfo["name"])
|
||||
|
||||
def encodeCoverArt(self):
|
||||
if not self.coverArtFile:
|
||||
return
|
||||
|
||||
coverFile = JKtrack(self.coverArtFile,JAMTRACK_COVER_ART_TAG)
|
||||
if not self.mediaAesKeyFile :
|
||||
coverFile.EncodeToTmpFile();
|
||||
else:
|
||||
coverFile.setKey(self.mediaAesKeyFile)
|
||||
coverFile.EncodeToTmpFile();
|
||||
|
||||
self.encryptedCoverFile = coverFile
|
||||
|
||||
|
||||
def generateContainerCoverMetaData(self):
|
||||
# create a json object with info on all the asset that are in the
|
||||
# the container
|
||||
if not self.encryptedCoverFile:
|
||||
return '[{}]'
|
||||
|
||||
mediaInfo = []
|
||||
trackNum=0
|
||||
mediaFileInfo = self.encryptedCoverFile
|
||||
if mediaFileInfo:
|
||||
statinfo = os.stat(mediaFileInfo.getOutputFileName())
|
||||
|
||||
info = { 'filename': mediaFileInfo.getCoverEncryptFilePackageName(),
|
||||
'datafile': mediaFileInfo.getCoverEncryptFilePackageName(trackNum),
|
||||
'padding': mediaFileInfo.getEncryptPadding(),
|
||||
'size': statinfo.st_size,
|
||||
'keymode': mediaFileInfo.getKeyModeStr(),
|
||||
'key': mediaFileInfo.getKeyStr()}
|
||||
|
||||
mediaInfo.append(info)
|
||||
return mediaInfo;
|
||||
|
||||
def generateContainerMediaMetaData(self):
|
||||
# create a json object with info on all the asset that are in the
|
||||
# the container
|
||||
mediaInfo = []
|
||||
trackNum=0
|
||||
for mediaFileInfo in self.encryptedMediaFiles:
|
||||
statinfo = os.stat(mediaFileInfo.getOutputFileName())
|
||||
|
||||
info = { 'filename': mediaFileInfo.getEncryptFilePackageName(),
|
||||
'trackname': mediaFileInfo.getEncryptFilePackageName(trackNum),
|
||||
'padding': mediaFileInfo.getEncryptPadding(),
|
||||
'size': statinfo.st_size,
|
||||
'keymode': mediaFileInfo.getKeyModeStr(),
|
||||
'key': mediaFileInfo.getKeyStr()}
|
||||
trackNum += 1
|
||||
mediaInfo.append(info)
|
||||
return mediaInfo;
|
||||
|
||||
def addJamTrackAssetToContainer(self,assetfile,rsa,zfile):
|
||||
#this is assumed to be text file..
|
||||
fi = open(assetfile,'rb')
|
||||
fi.seek(0)
|
||||
amsg = fi.read();
|
||||
pstr = rsa.pad(amsg)
|
||||
|
||||
#print pstr
|
||||
|
||||
if DEBUG_ENABLE != 0:
|
||||
print 'plaintext:', pstr
|
||||
|
||||
encMediaStr = rsa.encryptMesssage(pstr)
|
||||
edata = ''.join(encMediaStr)
|
||||
metaInfoFile = tempfile.NamedTemporaryFile()
|
||||
metaInfoFile.write(edata)
|
||||
metaInfoFile.seek(0)
|
||||
|
||||
if DEBUG_ENABLE != 0:
|
||||
ddata = rsa.decryptMesssage(bytes(edata))
|
||||
print 'decrypt: ', ''.join(ddata)
|
||||
|
||||
|
||||
try:
|
||||
zfile.write(metaInfoFile.name,
|
||||
arcname=JAMTRACK_PACKAGE_INFO_FILE, compress_type=compression)
|
||||
except:
|
||||
sys.exit("error writing package info file")
|
||||
|
||||
|
||||
def initContainer(self):
|
||||
|
||||
|
||||
mediaMeta = {'JPACK_VER': JAMTRACK_PACKAGE_VERSION,
|
||||
'jamktrack_info' : self.otherAssetFile,
|
||||
JAMTRACK_COVER_ART_TAG : self.generateContainerCoverMetaData(),
|
||||
"tracks": self.generateContainerMediaMetaData()}
|
||||
|
||||
mediaMeta_str = json.dumps( mediaMeta )
|
||||
if DEBUG_ENABLE != 0:
|
||||
pprint(mediaMeta)
|
||||
#print mediaMeta_str
|
||||
|
||||
#now rsa encrypt this string
|
||||
rsa = JKrsa()
|
||||
rsa.generateKey(self.rsaPrivKeyFile, self.rsaPubKeyFile)
|
||||
mediaMeta_str = rsa.pad(mediaMeta_str)
|
||||
|
||||
if DEBUG_ENABLE != 0:
|
||||
print 'plaintext:', mediaMeta_str
|
||||
|
||||
encMediaStr = rsa.encryptMesssage(mediaMeta_str)
|
||||
edata = ''.join(encMediaStr)
|
||||
|
||||
#write the encrypted media info to a file so we can zip in the asset
|
||||
metaInfoFile = tempfile.NamedTemporaryFile()
|
||||
metaInfoFile.write(edata)
|
||||
metaInfoFile.seek(0)
|
||||
|
||||
#try decrypting the data
|
||||
if DEBUG_ENABLE != 0:
|
||||
ddata = rsa.decryptMesssage(bytes(edata))
|
||||
print 'decrypt: ', ''.join(ddata)
|
||||
|
||||
#zip package
|
||||
if DEBUG_ENABLE != 0:
|
||||
print 'creating archive'
|
||||
#self.packageFileName = outfile = "media_%s" % (self.outputPackageFile)
|
||||
self.packageFileName = outfile = "%s" % (self.outputPackageFile)
|
||||
zfile = zipfile.ZipFile(outfile, mode='w')
|
||||
|
||||
try:
|
||||
if DEBUG_ENABLE != 0:
|
||||
print 'adding media_meta file with compression mode', modes[compression]
|
||||
zfile.write(metaInfoFile.name,
|
||||
arcname=JAMTRACK_MEDIA_META_FILE, compress_type=compression)
|
||||
except:
|
||||
sys.exit("error writing media info file")
|
||||
|
||||
#also add the other asset file - contain jamtrack title and other description etc...
|
||||
self.addJamTrackAssetToContainer(self.otherAssetFile,rsa,zfile)
|
||||
zfile.close()
|
||||
|
||||
#print_info(outfile)
|
||||
|
||||
def generateContainer(self):
|
||||
self.encodeMediaFiles()
|
||||
self.encodeCoverArt();
|
||||
|
||||
self.initContainer()
|
||||
|
||||
#now append file to container
|
||||
zf = zipfile.ZipFile(self.packageFileName, mode='a')
|
||||
|
||||
if self.encryptedCoverFile:
|
||||
try:
|
||||
zf.write(self.encryptedCoverFile.getOutputFileName(),
|
||||
arcname=self.encryptedCoverFile.getCoverEncryptFilePackageName(0),
|
||||
compress_type=compression)
|
||||
except:
|
||||
sys.exit("error writing cover art info container file")
|
||||
|
||||
trackNum=0
|
||||
for mediaFileInfo in self.encryptedMediaFiles:
|
||||
# store the file in the archive under the track name
|
||||
try:
|
||||
zf.write(mediaFileInfo.getOutputFileName(),
|
||||
arcname=mediaFileInfo.getEncryptFilePackageName(trackNum),
|
||||
compress_type=compression)
|
||||
except:
|
||||
sys.exit("error writing media info container file")
|
||||
|
||||
trackNum = trackNum + 1
|
||||
zf.close()
|
||||
#dump the details of the final package
|
||||
if DEBUG_ENABLE != 0:
|
||||
print_info(self.packageFileName)
|
||||
|
||||
def extractMediaMetaData(self,fname,rsa,zf):
|
||||
# first extract the media_meta file
|
||||
metadata =''
|
||||
for info in zf.infolist():
|
||||
if fname in info.filename:
|
||||
try:
|
||||
metadata = zf.read(info.filename)
|
||||
except KeyError:
|
||||
print 'ERROR: Did not find %s in zip file' % info.filename
|
||||
sys.exit()
|
||||
|
||||
break
|
||||
if metadata == '':
|
||||
print 'No media meta data found in package'
|
||||
sys.exit()
|
||||
|
||||
metadata = rsa.decryptMesssage(bytes(metadata))
|
||||
#print metadata
|
||||
#convert to to string
|
||||
estr = ''.join(metadata)
|
||||
#strip padding
|
||||
estr = estr.rstrip(b'\0')
|
||||
if DEBUG_ENABLE:
|
||||
print estr
|
||||
|
||||
return estr
|
||||
|
||||
def extractCoverArtData(self,fname,zf):
|
||||
# first extract the media_meta file
|
||||
metadata =''
|
||||
for info in zf.infolist():
|
||||
if fname in info.filename:
|
||||
try:
|
||||
metadata = zf.read(info.filename)
|
||||
except KeyError:
|
||||
print 'ERROR: Did not find %s in zip file' % info.filename
|
||||
sys.exit()
|
||||
|
||||
break
|
||||
if metadata == '':
|
||||
print 'No cover art data found in package'
|
||||
sys.exit()
|
||||
|
||||
metadata = rsa.decryptMesssage(bytes(metadata))
|
||||
#print metadata
|
||||
#convert to to string
|
||||
estr = ''.join(metadata)
|
||||
#strip padding
|
||||
estr = estr.rstrip(b'\0')
|
||||
if DEBUG_ENABLE:
|
||||
print estr
|
||||
|
||||
return estr
|
||||
|
||||
def decryptAesFile(self,aesKey,fdata,fname,tname, padding):
|
||||
print fname,'->',tname
|
||||
# write the content to tmp file
|
||||
outTmpFile = tempfile.NamedTemporaryFile()
|
||||
outTmpFile.write(fdata)
|
||||
|
||||
track = JKtrack('dec_'+fname)
|
||||
track.setKeyStr(aesKey)
|
||||
track.DecodeBufferToFile(fdata,tname,padding)
|
||||
if COMPARE_PARSEFILE:
|
||||
# write the encrypted files out
|
||||
fi = open('enc_'+tname,'wb')
|
||||
fi.write(fdata);
|
||||
fi.close()
|
||||
|
||||
if filecmp.cmp(tname,fname):
|
||||
print 'OK: file %s match %s' % (fname,tname)
|
||||
else:
|
||||
print 'BAD: file %s does not match %s' % (fname,tname)
|
||||
|
||||
def parseContainer(self, rsaKeyFile):
|
||||
# file must be zip file
|
||||
zf = zipfile.ZipFile(self.packageFileInfo)
|
||||
|
||||
#now decrypt data with rsa public key
|
||||
rsa = JKrsa()
|
||||
rsa.loadKey(rsaKeyFile)
|
||||
|
||||
# get the jam package info file
|
||||
pinfo = self.extractMediaMetaData(JAMTRACK_PACKAGE_INFO_FILE,rsa,zf)
|
||||
fi = open(JAMTRACK_PACKAGE_INFO_FILE,'wb')
|
||||
fi.write(pinfo);
|
||||
fi.close()
|
||||
|
||||
#get the media details
|
||||
estr = self.extractMediaMetaData(JAMTRACK_MEDIA_META_FILE,rsa,zf)
|
||||
data = json.loads(estr)
|
||||
if DEBUG_ENABLE:
|
||||
pprint(data)
|
||||
|
||||
try:
|
||||
coverFileInfoArray = data[JAMTRACK_COVER_ART_TAG]
|
||||
try:
|
||||
coverFileInfo= coverFileInfoArray[0]
|
||||
cfile = coverFileInfo['datafile']
|
||||
aesKey = coverFileInfo['key']
|
||||
fname = coverFileInfo['filename']
|
||||
fsize = coverFileInfo['size']
|
||||
padding = coverFileInfo['padding']
|
||||
try:
|
||||
fdata = zf.read(cfile)
|
||||
except KeyError:
|
||||
print 'ERROR: Did not find %s in zip file' % cfile
|
||||
sys.exit()
|
||||
else:
|
||||
self.decryptAesFile(aesKey,fdata,fname,cfile,padding)
|
||||
except:
|
||||
print 'no cover art data'
|
||||
except:
|
||||
print 'no cover art'
|
||||
|
||||
#now extract the file
|
||||
mediaFilesInfo = data["tracks"]
|
||||
|
||||
for mediaFileInfo in mediaFilesInfo:
|
||||
aesKey = mediaFileInfo['key']
|
||||
fname = mediaFileInfo['filename']
|
||||
fsize = mediaFileInfo['size']
|
||||
tname = mediaFileInfo['trackname']
|
||||
padding = mediaFileInfo['padding']
|
||||
fdata = ''
|
||||
try:
|
||||
fdata = zf.read(tname)
|
||||
except KeyError:
|
||||
print 'ERROR: Did not find %s in zip file' % tname
|
||||
sys.exit()
|
||||
else:
|
||||
self.decryptAesFile(aesKey,fdata,fname,tname,padding)
|
||||
|
||||
|
||||
Binary file not shown.
|
|
@ -0,0 +1,249 @@
|
|||
import jkasset
|
||||
import json
|
||||
import jkasset
|
||||
from pprint import pprint
|
||||
import random
|
||||
import sys, getopt
|
||||
import jkmedia
|
||||
import base64
|
||||
import tempfile
|
||||
import argparse
|
||||
from types import *
|
||||
import unicodedata
|
||||
|
||||
parser =''
|
||||
inputfiles = []
|
||||
|
||||
def help():
|
||||
parser.print_help()
|
||||
|
||||
|
||||
|
||||
def media_arg(string):
|
||||
#print 'media_arg:', string
|
||||
try:
|
||||
fname,ext = string.split('+')
|
||||
#print fname
|
||||
if fname == '':
|
||||
print "### No music file in command line: ", string
|
||||
raise argparse.ArgumentTypeError("Track file name empty")
|
||||
|
||||
inputfiles.append(string)
|
||||
except:
|
||||
if string:
|
||||
inputfiles.append(string)
|
||||
pass
|
||||
|
||||
return string
|
||||
|
||||
def loadTracksFromList(fileName):
|
||||
try:
|
||||
lines = [line.strip() for line in open(fileName)]
|
||||
#print lines
|
||||
global inputfiles
|
||||
inputfiles = lines
|
||||
except:
|
||||
print "Unable to open media filelist", fileName
|
||||
help()
|
||||
sys.exit(-1)
|
||||
|
||||
def process(argv):
|
||||
#print argv
|
||||
global parser
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='jkcreate',
|
||||
description='JamTrack Packaging Tool',
|
||||
epilog="Note: Meta file values may be update with title,sku,etc")
|
||||
|
||||
parser.add_argument("-D", "--verbosity",
|
||||
help="increase output verbosity",
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-t", "--title", metavar='title', type=str,
|
||||
help="Title of JamTrack. If not specified, the title in the metafile is used.")
|
||||
|
||||
parser.add_argument("-k", "--sku", type=str,
|
||||
help="The product SKU to use. If not specified, the SKU in the metafile is used.",required=True,)
|
||||
|
||||
parser.add_argument("-c", "--cover", metavar='coverArtFile', type=str,
|
||||
help="The cover art file. File should be JPEG or PNG.")
|
||||
|
||||
parser.add_argument("-p", "--pkey", metavar='pkey.pem',type=str,
|
||||
help="The output public key file. File should be .pem",required=True,)
|
||||
|
||||
parser.add_argument("-s", "--skey", metavar='skey.pem', type=str,
|
||||
help="The output private key file. File should be .pem",required=True,)
|
||||
|
||||
|
||||
parser.add_argument("-m", "--meta",metavar='trackMetaFile', type=str,
|
||||
help="The input JamTrack JSON metafile file. Optional")
|
||||
|
||||
parser.add_argument("-o", "--ofile", metavar='JamTrackPage', type=str,
|
||||
help="The output JamTrack file (.jkz)",required=True,)
|
||||
|
||||
parser.add_argument("-I", "--infilesList", metavar='musicTrackFileList', type=str,
|
||||
help=" -I 'file containing tracks'")
|
||||
|
||||
parser.add_argument("-i", "--infiles", metavar='musictrack', type=media_arg, nargs='*',
|
||||
help=" -i 'Lumme.ogg+Bass Guitar' -i 'Hydrate-Kenny_Beltrey.ogg+Bass Guitar'",)
|
||||
|
||||
|
||||
#parser.print_help()
|
||||
args = parser.parse_args(argv)
|
||||
#print args
|
||||
|
||||
try:
|
||||
if args.verbosity:
|
||||
jkasset.DEBUG_ENABLE = 1
|
||||
jkasset.COMPARE_PARSEFILE = True
|
||||
#args.sku = random.randint(1, 100000000)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
try:
|
||||
if args.infilesList:
|
||||
loadTracksFromList(args.infilesList)
|
||||
except:
|
||||
pass
|
||||
#create json struct from info
|
||||
metaJson={}
|
||||
try:
|
||||
if args.meta:
|
||||
#try to load json data
|
||||
try:
|
||||
json_data=open(args.meta).read()
|
||||
|
||||
metaJson = json.loads(json_data)
|
||||
if jkasset.DEBUG_ENABLE :
|
||||
pprint(metaJson)
|
||||
except:
|
||||
print 'Error processing json from file: ', args.meta
|
||||
help()
|
||||
sys.exit(-1)
|
||||
except:
|
||||
print 'No meta file specified'
|
||||
pass
|
||||
|
||||
jdata={}
|
||||
mdata=[]
|
||||
instdata={}
|
||||
|
||||
if any(metaJson):
|
||||
try:
|
||||
#pickup the instrument data passed in - if any
|
||||
instdata = metaJson["TrackInstrument"]
|
||||
except:
|
||||
pass
|
||||
|
||||
i = 0
|
||||
trackLength = {}
|
||||
trackLenStats=[]
|
||||
|
||||
#print inputfiles
|
||||
|
||||
if not any(inputfiles) :
|
||||
print 'No track files specified '
|
||||
help()
|
||||
sys.exit(-1)
|
||||
|
||||
for mediaFileInfo in inputfiles:
|
||||
#update track name and instrument name
|
||||
#print mediaFileInfo
|
||||
mediaFileInfo.strip();
|
||||
mlist = mediaFileInfo.split("+")
|
||||
mediaFileInfo = mlist[0]
|
||||
|
||||
trackName = 'track_%02d' % (i)
|
||||
i = i + 1
|
||||
mdata.append({"name" : mediaFileInfo, "trackName": trackName})
|
||||
|
||||
try:
|
||||
minfo = jkmedia.JKTrackInfo(mediaFileInfo) ;
|
||||
tinfo={};
|
||||
tinfo['bitrate']=minfo.bitrate
|
||||
tinfo['length'] = minfo.trackLength
|
||||
trackLenStats.append(minfo.trackLength)
|
||||
trackLength[trackName]= tinfo
|
||||
except:
|
||||
print("Cannot find file or read media information for '%s'"% mediaFileInfo)
|
||||
#help()
|
||||
sys.exit(-1)
|
||||
|
||||
try:
|
||||
instdata[trackName]=mlist[1]
|
||||
except:
|
||||
if instdata.has_key(trackName) == False:
|
||||
print "No instrument for track ",trackName
|
||||
pass
|
||||
|
||||
try:
|
||||
if args.title:
|
||||
try:
|
||||
title = base64.b64encode(args.title)
|
||||
metaJson['Title']=title
|
||||
except:
|
||||
print 'Error processing title : ', title
|
||||
help()
|
||||
sys.exit(-1)
|
||||
|
||||
if args.sku:
|
||||
try:
|
||||
metaJson['SKU']=args.sku
|
||||
except:
|
||||
print 'Error sku'
|
||||
help()
|
||||
sys.exit(-1)
|
||||
|
||||
metaJson['METADATA_VER'] = 1
|
||||
|
||||
except:
|
||||
#These are both optional..
|
||||
pass
|
||||
|
||||
if any(instdata):
|
||||
metaJson['TrackInstrument'] = instdata
|
||||
if len (instdata) > len(mdata):
|
||||
print "Number of instruments ", len (instdata)," in meta data greater than number of tracks ",len(mdata)
|
||||
help()
|
||||
sys.exit(-1)
|
||||
|
||||
if any(trackLength):
|
||||
metaJson['TrackData'] = trackLength
|
||||
|
||||
#dump the meta data to temp file
|
||||
|
||||
metaTmp = tempfile.NamedTemporaryFile();
|
||||
metaTmp.write(json.dumps(metaJson))
|
||||
metaTmp.seek(0)
|
||||
|
||||
jdata["tracks"] = mdata
|
||||
jdata["rsa_priv_file"]= args.skey
|
||||
jdata["rsa_pub_file"]= args.pkey
|
||||
jdata["container_file"]= args.ofile
|
||||
|
||||
#jdata["jamktrack_info"]= trackMetaFile
|
||||
jdata["jamktrack_info"]= metaTmp.name
|
||||
|
||||
try:
|
||||
jdata["coverart"]= args.cover
|
||||
except:
|
||||
print 'No cover art specified'
|
||||
|
||||
data = json.dumps(jdata)
|
||||
#pprint(data)
|
||||
|
||||
fname = 'jt_metadata.json'
|
||||
fo = open(fname, 'w')
|
||||
fo.write(data)
|
||||
fo.close()
|
||||
|
||||
jas = jkasset.JKasset(fname)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
random.seed()
|
||||
process(sys.argv[1:])
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
#!/usr/bin/env python
|
||||
import base64
|
||||
import os
|
||||
import binascii
|
||||
import json
|
||||
import sys
|
||||
from optparse import OptionParser
|
||||
#from import mutagen.ogg
|
||||
#from import mutagen.oggvorbis
|
||||
|
||||
class JKTrackInfo:
|
||||
trackLength =0
|
||||
bitrate = 0
|
||||
mediaFile='';
|
||||
|
||||
|
||||
def __init__(self, fileName):
|
||||
#get the file extension
|
||||
self.mediaFile = fileName
|
||||
fileName, fileExtension = os.path.splitext(self.mediaFile)
|
||||
audio = ''
|
||||
if fileExtension == '.ogg' :
|
||||
from mutagen.oggvorbis import OggVorbis
|
||||
audio = OggVorbis(self.mediaFile)
|
||||
elif fileExtension == '.wav' :
|
||||
from mutagen.wavpack import WavPack
|
||||
audio = WavPack(self.mediaFile)
|
||||
elif fileExtension == '.mp3' :
|
||||
from mutagen.mp3 import MP3
|
||||
audio = MP3(self.mediaFile)
|
||||
elif fileExtension == '.flac' :
|
||||
from mutagen.flac import FLAC
|
||||
audio = FLAC(self.mediaFile)
|
||||
else:
|
||||
print "Unsupported filetype '",fileExtension, "' for file ", self.mediaFile
|
||||
raise Exception("Unsupported filetype")
|
||||
|
||||
print audio.info.length, audio.info.bitrate
|
||||
self.bitrate = audio.info.bitrate
|
||||
self.trackLength = audio.info.length
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,194 @@
|
|||
# RSA Cipher
|
||||
# http://inventwithpython.com/hacking (BSD Licensed)
|
||||
|
||||
from Crypto.Cipher import PKCS1_OAEP
|
||||
from Crypto.PublicKey import RSA
|
||||
from Crypto import Random
|
||||
import base64
|
||||
import sys
|
||||
|
||||
class JKrsa:
|
||||
# IMPORTANT: The block size MUST be less than or equal to the key size!
|
||||
# (Note: The block size is in bytes, the key size is in bits. There
|
||||
# are 8 bits in 1 byte.)
|
||||
#DEFAULT_BLOCK_SIZE = 128-2 # 128 bytes
|
||||
DEFAULT_BLOCK_SIZE = 64 # 128 bytes
|
||||
|
||||
|
||||
RSA_KEYSIZE = 1024
|
||||
BYTE_SIZE = 256 # One byte has 256 different values.
|
||||
RSAKey='';
|
||||
PADDING = 0
|
||||
PADDING_CHARACTER =b'\0'
|
||||
encipher='';
|
||||
decipher=''
|
||||
|
||||
def __init__(self, operation='encode'):
|
||||
self.op = operation
|
||||
|
||||
def updatePadSize(self,dlen):
|
||||
self.PADDING = (self.DEFAULT_BLOCK_SIZE - dlen % self.DEFAULT_BLOCK_SIZE)
|
||||
|
||||
def getPadding(self):
|
||||
return self.PADDING
|
||||
|
||||
def pad(self,s):
|
||||
self.updatePadSize(len(s))
|
||||
pdata = self.PADDING * self.PADDING_CHARACTER
|
||||
if len(pdata) != self.PADDING :
|
||||
sys.exit('Pad data length %d does match %d. Check python pad character size!',
|
||||
(len(pdata), self.PADDING))
|
||||
s = s + pdata
|
||||
return s
|
||||
|
||||
def EncodeRSA(self,c, s):
|
||||
#print 'len=',len(s)
|
||||
estr = self.encipher.encrypt(s)
|
||||
#print 'elen=',len(estr)
|
||||
#print estr
|
||||
return estr
|
||||
|
||||
def DecodeRSA(self,c, e):
|
||||
#print 'len=',len(e)
|
||||
str = self.decipher.decrypt(e)
|
||||
return str
|
||||
|
||||
def generateKey(self, privateFileName='pri_Key.pem', publicFileName='pub_Key.pem'):
|
||||
self.RSAKey = RSA.generate(self.RSA_KEYSIZE)
|
||||
|
||||
public_key = self.RSAKey.publickey().exportKey("PEM")
|
||||
private_key = self.RSAKey.exportKey("PEM")
|
||||
|
||||
if privateFileName:
|
||||
f = open(privateFileName,'w')
|
||||
f.write(self.RSAKey.exportKey("PEM"))
|
||||
f.close()
|
||||
|
||||
f = open(privateFileName,'r')
|
||||
skey = RSA.importKey(f.read())
|
||||
self.decipher = PKCS1_OAEP.new(skey)
|
||||
f.close()
|
||||
|
||||
if publicFileName:
|
||||
f = open(publicFileName,'w')
|
||||
f.write(self.RSAKey.publickey().exportKey("PEM"))
|
||||
f.close()
|
||||
|
||||
f = open(publicFileName,'r')
|
||||
pkey = RSA.importKey(f.read())
|
||||
self.encipher = PKCS1_OAEP.new(pkey)
|
||||
f.close()
|
||||
|
||||
return private_key, public_key
|
||||
|
||||
def loadKey(self, fileName='pri_Key.pem'):
|
||||
f = open(fileName,'r')
|
||||
self.RSAKey = RSA.importKey(f.read())
|
||||
self.decipher = PKCS1_OAEP.new(self.RSAKey)
|
||||
f.close()
|
||||
|
||||
def WriteFileData(self,outfile,data):
|
||||
#ddata = base64.b64decode(data)
|
||||
fi = open(outfile,'wb')
|
||||
fi.write(data);
|
||||
|
||||
def LoadFileData(self, infile):
|
||||
fi = open(infile,'rb')
|
||||
data = fi.read();
|
||||
#edata = base64.b64encode(data)
|
||||
return data
|
||||
|
||||
def WriteRSAFileData(self, outfile,data):
|
||||
# These files are assumed to be in cypher text - so we won't b64 encode/decode them
|
||||
fo = open(outfile,'wb')
|
||||
#edata = base64.b64encode(data)
|
||||
fo.write(data)
|
||||
|
||||
|
||||
def LoadRSAFileData(self, infile):
|
||||
# These files are assumed to be in cypher text - so we won't b64 encode/decode them
|
||||
fi = open(infile,'rb')
|
||||
data = fi.read();
|
||||
return data
|
||||
|
||||
def getBlocksFromText(self,message, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
# Converts a string message to a list of block integers. Each integer
|
||||
# represents 128 (or whatever blockSize is set to) string characters.
|
||||
# messageBytes = message.encode('ascii') # convert the string to bytes
|
||||
blockInts = []
|
||||
blockInts = [message[i:i+blockSize] for i in range(0, len(message), blockSize)]
|
||||
return blockInts
|
||||
|
||||
|
||||
def encryptMesssage(self, message, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
keySize = self.RSAKey.size() + 1;
|
||||
|
||||
# Check that key size is greater than block size.
|
||||
if keySize < blockSize * 8: # * 8 to convert bytes to bits
|
||||
sys.exit('ERROR: Block size is %d bits and key size is %d bits.'
|
||||
' The RSA cipher requires the block size to be equal to'
|
||||
' or less than the key size. Either decrease the'
|
||||
' block size or use different keys.' % (blockSize * 8, keySize))
|
||||
|
||||
if len(message) % blockSize : # * 8 to convert bytes to bits
|
||||
sys.exit('ERROR: Block size is %d and data size is %d .'
|
||||
' The RSA cipher requires the block size to be equal to'
|
||||
' or less than the key size. Either decrease the'
|
||||
' block size or use different keys.' % (blockSize, len(message)))
|
||||
|
||||
|
||||
encryptedContent = []
|
||||
for block in self.getBlocksFromText(message, blockSize):
|
||||
encryptedContent_ = self.EncodeRSA(self.RSAKey,block);
|
||||
encryptedContent.extend(encryptedContent_)
|
||||
|
||||
return encryptedContent
|
||||
|
||||
def decryptMesssage(self, message):
|
||||
#print message
|
||||
#split in equal chunks
|
||||
decryptedContent = []
|
||||
for block in self.getBlocksFromText(message, self.DEFAULT_BLOCK_SIZE*2):
|
||||
decryptedContent_ = self.DecodeRSA(self.RSAKey,block);
|
||||
decryptedContent.extend(decryptedContent_)
|
||||
|
||||
return decryptedContent
|
||||
|
||||
|
||||
def encryptAndWriteToFile(self, keyFilename, inFile,outFilename, blockSize=DEFAULT_BLOCK_SIZE):
|
||||
# Using a key from a key file, encrypt the message and save it to a
|
||||
# file. Returns the encrypted message string.
|
||||
self.loadKey(keyFilename)
|
||||
keySize = self.RSAKey.size()+1;
|
||||
|
||||
# Check that key size is greater than block size.
|
||||
if keySize < blockSize * 8: # * 8 to convert bytes to bits
|
||||
sys.exit('ERROR: Block size is %s bits and key size is %s bits.'
|
||||
' The RSA cipher requires the block size to be equal to'
|
||||
' or less than the key size. Either decrease the'
|
||||
' block size or use different keys.' % (blockSize * 8, keySize))
|
||||
|
||||
# Encrypt the message
|
||||
message = self.LoadFileData(inFile);
|
||||
message = self.pad(message)
|
||||
|
||||
encryptedContent = self.encryptMesssage(message);
|
||||
self.WriteRSAFileData(outFilename,encryptedContent)
|
||||
# Also return the encrypted string.
|
||||
#return encryptedContent
|
||||
|
||||
|
||||
def readFromFileAndDecrypt(self, keyFilename, inFile, outFilename):
|
||||
# Using a key from a key file, read an encrypted message from a file
|
||||
# and then decrypt it. Returns the decrypted message string.
|
||||
self.loadKey(keyFilename)
|
||||
|
||||
# Read in the message length and the encrypted message from the file.
|
||||
message = self.LoadRSAFileData(inFile)
|
||||
|
||||
decryptMessage = self.decryptMesssage(message)
|
||||
self.WriteFileData(outFilename,decryptMessage)
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
import jkaes
|
||||
import tempfile
|
||||
from jkaes import JKaes
|
||||
import os
|
||||
class JKtrack:
|
||||
mediaFile = ''
|
||||
Name = ''
|
||||
aesInKeyFile=''
|
||||
aesCipher = ''
|
||||
outTmpFile =''
|
||||
outPutFile = ''
|
||||
def __init__(self, fileName, title='Unknown', inKeyFile=''):
|
||||
self.mediaFile = fileName
|
||||
self.Name = title
|
||||
self.aesInKeyFile = inKeyFile
|
||||
self.aesCipher = JKaes(self.mediaFile, self.aesInKeyFile)
|
||||
|
||||
def getOutputFileName(self):
|
||||
return self.outPutFile;
|
||||
|
||||
def getKeyStr(self):
|
||||
return self.aesCipher.getKeyStr();
|
||||
|
||||
def getEncryptPadding(self):
|
||||
return self.aesCipher.getPadding()
|
||||
|
||||
def setKeyStr(self,key):
|
||||
self.aesCipher.setKey(key);
|
||||
|
||||
def getKeyModeStr(self):
|
||||
return self.aesCipher.getKeyModeStr()
|
||||
|
||||
def getCoverEncryptFilePackageName(self,instance=-1):
|
||||
#preserve the extentsion on the original name
|
||||
fileName, fileExtension = os.path.splitext(self.mediaFile)
|
||||
if instance != -1:
|
||||
nm = "cover_%02d%s" % (instance,fileExtension)
|
||||
return nm
|
||||
else:
|
||||
nm = os.path.basename(self.mediaFile)
|
||||
return nm
|
||||
|
||||
def getEncryptFilePackageName(self,instance=-1):
|
||||
#preserve the extentsion on the original name
|
||||
fileName, fileExtension = os.path.splitext(self.mediaFile)
|
||||
if instance != -1:
|
||||
nm = "track_%02d%s" % (instance,fileExtension)
|
||||
return nm
|
||||
else:
|
||||
nm = os.path.basename(self.mediaFile)
|
||||
return nm
|
||||
|
||||
def Encode(self, outFile):
|
||||
self.outPutFile = outFile
|
||||
self.aesCipher.EncodeFileAndWrite( self.mediaFile, outFile)
|
||||
|
||||
def EncodeToTmpFile(self):
|
||||
self.outTmpFile = tempfile.NamedTemporaryFile()
|
||||
self.Encode(self.outTmpFile.name)
|
||||
|
||||
def EncodeWithKeyToFile(self,keyFile,outFile):
|
||||
self.aesCipher.readAesKeyFile(keyFile)
|
||||
self.Encode(outFile)
|
||||
|
||||
def Decode(self, outFile):
|
||||
self.outPutFile = outFile
|
||||
self.aesCipher.DecodeFileAndWrite( self.mediaFile, outFile)
|
||||
|
||||
def DecodeToTmpFile(self):
|
||||
self.outTmpFile = tempfile.NamedTemporaryFile()
|
||||
self.Decode(self.outTmpFile.name)
|
||||
|
||||
def DecodeWithKeyToFile(self,keyFile,outFile):
|
||||
self.aesCipher.readAesKeyFile(keyFile)
|
||||
self.Decode(outFile)
|
||||
|
||||
|
||||
def DecodeBufferToFile(self,msg,outfile,padding=0):
|
||||
dmsg = self.aesCipher.DecodeMsg(msg)
|
||||
fi = open(outfile,'wb')
|
||||
fi.write(dmsg);
|
||||
if padding > 0:
|
||||
#trunckage the file by
|
||||
fi.seek(-padding, os.SEEK_END)
|
||||
fi.truncate()
|
||||
fi.close()
|
||||
return dmsg
|
||||
|
||||
def DecodeU64Buffer(self,msg):
|
||||
return self.aesCipher.DecodeU64Msg(msg)
|
||||
|
||||
def setKey(self, keyFile):
|
||||
self.aesCipher.readAesKeyFile(keyFile)
|
||||
|
||||
def saveKey(self,keyFile):
|
||||
self.aesCipher.writeAesKeytoFile(keyFile)
|
||||
|
||||
def saveEncFileCopy(self,outfile):
|
||||
fi = open(self.outPutFile,'rb')
|
||||
fi.seek(0)
|
||||
dmsg = fi.read();
|
||||
fo = open(outfile,'wb')
|
||||
fo.write(dmsg);
|
||||
return dmsg
|
||||
Binary file not shown.
|
|
@ -0,0 +1,56 @@
|
|||
import jkasset
|
||||
import json
|
||||
import jkasset
|
||||
from pprint import pprint
|
||||
import random
|
||||
import sys, getopt
|
||||
import base64
|
||||
import tempfile
|
||||
import argparse
|
||||
from types import *
|
||||
import unicodedata
|
||||
|
||||
parser =''
|
||||
def help():
|
||||
parser.print_help()
|
||||
#print sys.argv[0],'[-D] -d -i <jamtrack.jkz> -s <privatekeyfile>'
|
||||
|
||||
|
||||
def process(argv):
|
||||
|
||||
global parser
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='jkunpack',
|
||||
description='JamTrack UnPackaging Tool',
|
||||
epilog="Note: Files may be overwritten during unpacking")
|
||||
|
||||
parser.add_argument("-D", "--verbosity",
|
||||
help="increase output verbosity",
|
||||
action="store_true")
|
||||
|
||||
parser.add_argument("-s", "--skey", metavar='skey.pem', type=str,
|
||||
help="The private key file. File should be .pem",required=True)
|
||||
|
||||
parser.add_argument("-i", "--ifile", metavar='JamTrackPage', type=str,
|
||||
help="The input JamTrack file (.jkz)",required=True)
|
||||
|
||||
parser.print_help()
|
||||
args = parser.parse_args(argv)
|
||||
print args
|
||||
|
||||
try:
|
||||
if args.verbosity:
|
||||
jkasset.DEBUG_ENABLE = 1
|
||||
jkasset.COMPARE_PARSEFILE = True
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
jas = jkasset.JKasset(args.ifile,'decode',args.skey)
|
||||
|
||||
if __name__ == "__main__":
|
||||
random.seed()
|
||||
process(sys.argv[1:])
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,98 @@
|
|||
#!/usr/bin/env ruby
|
||||
#
|
||||
# Usage: jkzify [path to JamTrack WAVs] [destination for jkz and key files]
|
||||
#
|
||||
# Please review the comments, this script needs improvement -- I just threw it together to help me validate jkcreate.py
|
||||
#
|
||||
|
||||
wd = Dir.getwd
|
||||
tracks_location = ARGV.shift
|
||||
output_location = ARGV.shift
|
||||
script_location = File.dirname(File.expand_path(__FILE__))
|
||||
|
||||
|
||||
|
||||
# first try to catch any issues with input arguments
|
||||
def halt msg; warn msg; exit; end
|
||||
halt "usage: jkzify path/to/wavs/ path/to/output" unless tracks_location && output_location
|
||||
halt "path not found" unless File.exist?(tracks_location) && File.exist?(output_location)
|
||||
# end
|
||||
|
||||
|
||||
|
||||
# step 1: gather metadata from the track/folder names (and user input)
|
||||
title = tracks_location.split('/').last.gsub(/'/,'')
|
||||
puts "i think this track is called \"#{title}\"..."
|
||||
shortname = title.gsub(/[aeiou\s]/,'').squeeze[0...8].downcase
|
||||
puts "i'll call it #{shortname} for now"
|
||||
puts "what sku do you want for this JamTrack? (press ENTER for '#{shortname}')"
|
||||
input = STDIN.gets.chomp.strip
|
||||
sku = input.empty? ? shortname : input
|
||||
|
||||
|
||||
|
||||
# step 2: move WAVs to our own workspace
|
||||
def renamed(t); t.gsub(/\s|'/,'_'); end #little helper
|
||||
|
||||
Dir.chdir wd
|
||||
`rm -rf #{shortname}` if File.exist? shortname
|
||||
`mkdir #{shortname}`
|
||||
|
||||
Dir.chdir tracks_location
|
||||
Dir.glob('*.wav') do |track|
|
||||
new_name = renamed track
|
||||
`cp "#{track}" "#{wd}/#{shortname}/#{new_name}"`
|
||||
puts "Copied from " + track + " to #{wd}/#{shortname}/" + new_name
|
||||
end
|
||||
Dir.chdir "#{wd}/#{shortname}"
|
||||
|
||||
|
||||
|
||||
# step 3: generate OGGs from WAVs
|
||||
oggs_location = title.downcase.gsub('\'','').split.join('_') + '_oggs/'
|
||||
puts "generating OGGs in a separate folder #{oggs_location} (this may take some time)"
|
||||
`mkdir #{oggs_location}` unless File.exist?(oggs_location)
|
||||
Dir.glob('*.wav') do |track|
|
||||
input = track
|
||||
output = "#{oggs_location}#{File.basename(track, '.wav')}.ogg"
|
||||
#puts "sox #{input} #{output}"
|
||||
`sox #{input} #{output}`
|
||||
end
|
||||
|
||||
|
||||
# step 4: get all track parameters (names and instruments)
|
||||
track_params = {}
|
||||
track_files = []
|
||||
suffix = '\.wav'
|
||||
Dir.foreach tracks_location do |track|
|
||||
next if track =~ /Master Mix/i
|
||||
next unless track =~ /#{suffix}$/i
|
||||
print '.'
|
||||
track.gsub!(/#{suffix}$/i, '')
|
||||
instrument = track.split('-').drop(1).map(&:strip).join(' ')
|
||||
parameter = "#{shortname}/#{oggs_location}#{renamed track}.ogg+#{instrument}"
|
||||
#parameter.gsub!(/ /, '\ ') #spaces in filenames
|
||||
track_params[instrument] = "-i '#{parameter}'"
|
||||
track_files << parameter
|
||||
end
|
||||
puts "OK, #{track_params.length} tracks found"
|
||||
|
||||
|
||||
|
||||
# step 5: create list of track titles
|
||||
Dir.chdir wd
|
||||
tracks_filename = "#{shortname}.txt"
|
||||
File.open(tracks_filename, 'w+') { |f| f.puts track_files }
|
||||
|
||||
|
||||
|
||||
# step 6: run jkcreate.py given all these parameters
|
||||
public_key = "#{output_location}#{shortname}-pub.pem"
|
||||
private_key = "#{output_location}#{shortname}-priv.pem"
|
||||
output_jkz = "#{output_location}#{shortname}.jkz"
|
||||
#puts "python jkcreate.py -D -k #{sku} -c art.png -p #{public_key} -s #{private_key} -I #{tracks_filename} -o #{output_jkz} -t '#{title}'"
|
||||
`python jkcreate.py -D -k #{sku} -c art.png -p #{public_key} -s #{private_key} -I #{tracks_filename} -o #{output_jkz} -t '#{title}'`
|
||||
|
||||
|
||||
|
||||
Dir.chdir wd
|
||||
Loading…
Reference in New Issue