The following video showcases the some of the engineering behind the aluminum can. Its impressive I tell you. Go watch!.
https://www.youtube.com/watch?v=hUhisi2FBuw
param(
[string]$keyfile=$(throw "Parameter keyfile required."),
[string]$infile=$(throw "Parameter infile required."),
[string]$outfile=$(throw "Parameter outfile required."),
[switch]$decrypt
)
# Encrypt Usage:
# powershell -ExecutionPolicy Unrestricted ./aesfile.ps1 -keyfile key.txt -infile data.txt -outfile data.txt.aes
# Decrypt Usage:
# powershell -ExecutionPolicy Unrestricted ./aesfile.ps1 -keyfile key.txt -infile data.txt.aes -outfile data.dec.txt -decrypt
# Read the key and the iv
# each is on one line and has its byte written in decimal ascii separated by ":"
[byte[]]$key = (Get-Content $keyfile)[0]| foreach {($_ -split ":")}
[byte[]]$iv = (Get-Content $keyfile)[1]| foreach {($_ -split ":")}
[Console]::Error.WriteLine("key=$key")
[Console]::Error.WriteLine("IV=$iv")
[Console]::Error.WriteLine("infile=$infile")
[Console]::Error.WriteLine("outdile=$outfile")
[Console]::Error.WriteLine("decrypt=$decrypt")
# Setup FileStreams
[System.IO.Stream]$instream = new-object System.IO.FileStream $infile, ([System.IO.FileMode]::Open)
[System.IO.Stream]$outstream = new-object System.IO.FileStream $outfile, ([System.IO.FileMode]::Create)
# Setup Encryption
$AesCSP = New-Object System.Security.Cryptography.AesCryptoServiceProvider
$AesCSP.Key = $key
$AesCSP.IV = $IV
if(!$decrypt) {$cryptor=$AesCSP.CreateEncryptor()}
else{$cryptor=$AesCSP.CreateDecryptor()}
$cstream = new-Object Security.Cryptography.CryptoStream $instream,$cryptor,"Read"
# Number of bytes to read with each chunks from the stream.
$BLOCK_BYTE_SIZE = $AesCSP.BlockSize/8
$NB_BLOCKS_READ = 100
$CHUNK_BYTE_SIZE = $BLOCK_BYTE_SIZE * $NB_BLOCKS_READ
#$cstream.CopyTo($outstream, $CHUNK_BYTE_SIZE) Only in .Net 4.0 :(
[byte[]]$buffer = new-object byte[] $CHUNK_BYTE_SIZE
while($byte_read=$cstream.Read($buffer, 0, $buffer.Length))
{
$outstream.Write($buffer, 0, $byte_read)
}
$cstream.Close()
$instream.Close()
$outstream.Close()
247:74:89:63:153:30:170:243:11:247:227:187:2:177:244:17:154:9:150:12:155:253:168:19:224:241:254:148:213:50:147:184
129:15:216:20:169:11:167:32:75:57:109:137:15:14:92:212
# My Maths def fA(x): print "In fA" return x+1 def fB(x): return x+2 def fC(x): print "In fC" return x+3 myInput = [1,2,3] ugly = ( fA(i) for i in ( i+2 for i in ( fC(i) for i in myInput))) print "About to process." ugly = list(ugly) # execution starts here print "ugly: %s" % ugly # Lamda makes generator expressions reusable with different inputs genA = lambda x : ( fA(i) for i in x) genB = lambda x : ( i+2 for i in x) genC = lambda x : ( fC(i) for i in x) lessUgly = genA(genB(genC(myInput))) lessUgly = list(lessUgly) print "lessUgly: %s" % lessUgly #or genCi = genC(myInput) genBi =genB(genCi) genAi = genA(genBi) # At least that way, generators appear in the "right" order result = list(genAi) print "result: %s" % result #In newer versions of python map returns an iterator # in older version take a look at imap in itertools # (I'm currently python 2.6) mapResult = map(fA, map(fB, map(fC, myInput))) print "mapResult: %s" % mapResult #or mapC = map(fC, myInput) mapB = map(fB, mapC) mapA = map(fA, mapB) mapResult = list(mapA) print "mapResult: %s" % mapResult # Now with a pipe! class Pipe: "Handles flow." def __init__ (self, source): self.lastIter = iter(source) def __iter__(self): return self.lastIter def __or__(self, right): try: it = iter(right) except: return NotImplemented self.lastIter = it return self p = Pipe(myInput) # Notice the generators appear in the order they are executed p | ( fC(i) for i in p) | ( i+2 for i in p) | ( fA(i) for i in p) result = list(p) print "Piperesult: %s" % result #or p = Pipe(myInput) p | ( fC(i) for i in p) p | ( i+2 for i in p) p | ( fA(i) for i in p) result = list(p) print "Piperesult: %s" % result # or with map p = Pipe(myInput) p | map(fC, p) p | map(fB, p) p | map(fA, p) result = list(p) print "Piperesult: %s" % result