<commit_before># https://code.google.com/p/crypto-js
CryptoJS = require("crypto-js")
assert = require("assert")
ByteBuffer = require("../common/bytebuffer")
Long = ByteBuffer.Long
hash = require("../common/hash")

class Aes

    constructor: (@iv, @key) ->
        
    clear:->@iv = @key = undefined
    
    # TODO arg should be a binary type... HEX works best with crypto-js
    Aes.fromSha512 = (hash) ->
        assert.equal hash.length, 128, "A Sha512 in HEX should be 128 characters long, instead got #{hash.length}"
        #https://github.com/InvictusInnovations/fc/blob/978de7885a8065bc84b07bfb65b642204e894f55/src/crypto/aes.cpp#L330
        #Bitshares aes_decrypt uses part of the password hash as the initilization vector
        iv = CryptoJS.enc.Hex.parse(hash.substring(64, 96))
        key = CryptoJS.enc.Hex.parse(hash.substring(0, 64))
        new Aes(iv, key)
    
    Aes.fromSeed = (seed) ->
        throw new Error("seed is required") if seed is undefined
        _hash = hash.sha512 seed
        _hash = _hash.toString('hex')
        Aes.fromSha512(_hash)
    
    Aes.decrypt_with_checksum = (private_key, public_key, nonce, message) ->
        unless Buffer.isBuffer message
            message = new Buffer message
        
        S = private_key.get_shared_secret public_key
        aes = Aes.fromSeed Buffer.concat [
            new Buffer(nonce)
            new Buffer(S.toString('hex'))
        ]
        planebuffer = aes.decrypt message
        unless planebuffer.length >= 4
            throw new Error "Invalid key, could not decrypt message"
        
        #console.log('... planebuffer',planebuffer)
        checksum = planebuffer.slice 0, 4
        plaintext = planebuffer.slice(4).toString()
        
        #console.log('... checksum',checksum.toString('hex'))
        #console.log('... plaintext',plaintext)
        
        # reverse() converts to big-endian (matches the c++ memo)
        new_checksum = hash.sha256 plaintext
        new_checksum = new_checksum.slice 0, 4
        new_checksum = new_checksum.toString('binary').split("").reverse().join("")
        
        unless checksum.toString('binary') is new_checksum
            throw new Error "Invalid key, could not decrypt message"
        
        plaintext
    
    Aes.encrypt_with_checksum = (private_key, public_key, nonce, message) ->
        unless Buffer.isBuffer message
            message = new Buffer message
        
        S = private_key.get_shared_secret public_key
        aes = Aes.fromSeed Buffer.concat [
            new Buffer(nonce)
            new Buffer(S.toString('hex'))
        ]
        # reverse() converts to big-endian (matches the c++ memo)
        checksum = hash.sha256(message).slice 0,4
        checksum = checksum.toString('binary').split("").reverse().join("")
        checksum = new Buffer(checksum, 'binary')
        payload = Buffer.concat [checksum, message]
        aes.encrypt payload
    
    _decrypt_word_array: (cipher) ->
        # https://code.google.com/p/crypto-js/#Custom_Key_and_IV<commit_msg>Fixed nonce data type in memo encryption #34<commit_after># https://code.google.com/p/crypto-js
CryptoJS = require("crypto-js")
assert = require("assert")
ByteBuffer = require("../common/bytebuffer")
Long = ByteBuffer.Long
hash = require("../common/hash")

class Aes

    constructor: (@iv, @key) ->
        
    clear:->@iv = @key = undefined
    
    # TODO arg should be a binary type... HEX works best with crypto-js
    Aes.fromSha512 = (hash) ->
        assert.equal hash.length, 128, "A Sha512 in HEX should be 128 characters long, instead got #{hash.length}"
        #https://github.com/InvictusInnovations/fc/blob/978de7885a8065bc84b07bfb65b642204e894f55/src/crypto/aes.cpp#L330
        #Bitshares aes_decrypt uses part of the password hash as the initilization vector
        iv = CryptoJS.enc.Hex.parse(hash.substring(64, 96))
        key = CryptoJS.enc.Hex.parse(hash.substring(0, 64))
        new Aes(iv, key)
    
    Aes.fromSeed = (seed) ->
        throw new Error("seed is required") if seed is undefined
        _hash = hash.sha512 seed
        _hash = _hash.toString('hex')
        # DEBUG console.log('... Aes.fromSeed _hash',_hash)
        Aes.fromSha512(_hash)
    
    Aes.decrypt_with_checksum = (private_key, public_key, nonce, message) ->
        unless Buffer.isBuffer message
            message = new Buffer message
        
        S = private_key.get_shared_secret public_key
        aes = Aes.fromSeed Buffer.concat [
            new Buffer(""+nonce)
            new Buffer(S.toString('hex'))
        ]
        planebuffer = aes.decrypt message
        unless planebuffer.length >= 4
            throw new Error "Invalid key, could not decrypt message"
        
        #console.log('... planebuffer',planebuffer)
        checksum = planebuffer.slice 0, 4
        plaintext = planebuffer.slice(4).toString()
        
        #console.log('... checksum',checksum.toString('hex'))
        #console.log('... plaintext',plaintext)
        
        # reverse() converts to big-endian (matches the c++ memo)
        new_checksum = hash.sha256 plaintext
        new_checksum = new_checksum.slice 0, 4
        new_checksum = new_checksum.toString('binary').split("").reverse().join("")
        
        unless checksum.toString('binary') is new_checksum
            throw new Error "Invalid key, could not decrypt message"
        
        plaintext
    
    Aes.encrypt_with_checksum = (private_key, public_key, nonce, message) ->
        unless Buffer.isBuffer message
            message = new Buffer message
        
        S = private_key.get_shared_secret public_key
        aes = Aes.fromSeed Buffer.concat [
            new Buffer(""+nonce)
            new Buffer(S.toString('hex'))
        ]
        # DEBUG console.log('... S',S.toString('hex'))
        
        # reverse() converts to big-endian (matches the c++ memo)
        checksum = hash.sha256(message).slice 0,4
        checksum = checksum.toString('binary').split("").reverse().join("")
        checksum = new Buffer(checksum, 'binary')
        payload = Buffer.concat [checksum, message]
        aes.encrypt payload
    
    _decrypt_word_array: (cipher) ->
        # https://code.google.com/p/crypto-js/#Custom_Key_and_IV
{'fraction_non_alphanumeric': 0.11585657370517928, 'fraction_numerical': 0.02262948207171315, 'mean_word_length': 2.3814655172413794, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 19, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3474733', 'n_tokens_mistral': 1985, 'n_tokens_neox': 1861, 'n_words': 445}