Programming/node.js2016.12.27 20:33

NPM : https://github.com/voltrue2/in-app-purchase


var iap = require('in-app-purchase');
iap.config({
    //verbose: true,
    //googlePublicKeyStrSandbox: "", //LIVE 먼저 실행하고 에러나면 SandBox 테스트실행함
    googlePublicKeyStrLive: "MIIBIj............",
});


iap.setup(function (error) {
    if (error) {
        console.log(error);
    }
    var googleReceipt = {
        "data":'{"packageName":"kr.co.test","productId":"kr.co.test.is1","purchaseTime":155435321,
                 "purchaseState":0,"purchaseToken":"oksdf........"}', //{stringified data object}
        "signature": "qSVwa8E9z........."
    };
    iap.validate(iap.GOOGLE, googleReceipt, function (error, response) {
        if (error) {
            console.log(error);
        }
        console.log(iap.isValidated(response));
    });
});


유니티에서 받는 데이터 중  GoogleReceipt data 값 어떤 걸로 넣는지 찾는데 삽질 2시간 OTL....... 



Hash 검증 로직 : node_modules\in-app-purchase\lib\google.js 참고

function validatePublicKey(receipt, pkey, cb) {
    if (!receipt || !receipt.data) {
        return cb(new Error('missing receipt data'));
    }
    if (!pkey) {
        return cb(new Error('missing public key'));
    }
    if (typeof receipt.data !== 'string') {
        return cb(new Error('receipt.data must be a string'));
    }
    var validater = crypto.createVerify('SHA1');
    var valid;
    validater.update(receipt.data);
    try {
        valid = validater.verify(pkey, receipt.signature, 'base64');
    } catch (error) {
        return cb(error);
    }
    if (valid) {
        // validated successfully
        var data = JSON.parse(receipt.data);
        data.status = constants.VALIDATION.SUCCESS;
        return cb(null, data);
    }
    // failed to validate
    cb(new Error('failed to validate purchase'));
}


GooglePublicKey는 해당 어플리케이션 들어가서 확인 



Posted by 시니^^
Programming/node.js2016.12.22 11:01

https://github.com/expressjs/body-parser


A new body object containing the parsed data is populated on the request object after the middleware (i.e. req.body). This object will contain key-value pairs, where the value can be a string or array (when extended is false), or any type (when extended is true).


POST FORM (Content-Type:application/x-www-form-urlencoded)

$ curl --noproxy '*' -i -XPOST 'http://localhost/post_test' -d 'array[key1][key2]=233'
app.use(bodyParser.urlencoded({ extended: false }));
 // req.body : { 'array[key1][key2]': '233' }
app.use(bodyParser.urlencoded({ extended: true })); 
// req.body : { array: { key1: { key2: '233' } } }


Posted by 시니^^
Programming/node.js2016.12.20 14:28


Node.js 

const crypto = require("crypto");
const algo = 'aes-128-cbc';
const key = "security_key";
const iv = "iv_key";
const value = 'HelloWorld';
const keyBuffer = new Buffer(crypto.createHash('md5').update(key).digest('hex'),"hex");
const ivBuffer = new Buffer(crypto.createHash('md5').update(iv).digest('hex'),"hex");
const textBuffer = new Buffer(value);

let cipher = crypto.createCipheriv(algo, keyBuffer,ivBuffer); let encrypted = cipher.update(textBuffer); let encryptedFinal = cipher.final(); let encryptedText = encrypted.toString('base64') + encryptedFinal.toString('base64'); console.log(encryptedText); //xr046x2iGy4IDUHUm+p7lA==

let decipher = crypto.createDecipheriv(algo, keyBuffer,ivBuffer); decipher.setAutoPadding(true);//padding 처리가 언어별 달라서 확인필요 let decipheredContent = decipher.update(encryptedText,'base64','utf8'); decipheredContent += decipher.final('utf8'); console.log(decipheredContent); //HelloWorld


C# (Unity3D)

출처 : http://wyseburn.tistory.com/entry/AES-CBC-128BIT-PKCS5-%EC%95%94%EB%B3%B5%ED%98%B8%ED%99%94-1

using UnityEngine; using System; using System.Text; using System.IO; using System.Security.Cryptography; using System.Runtime.Remoting.Metadata.W3cXsd2001; public class Crypto { public static readonly string key = MD5Hash("security_key"); public static readonly string iv = MD5Hash("iv_key"); public static string MD5Hash(string str) { MD5 md5 = new MD5CryptoServiceProvider(); byte[] hash = md5.ComputeHash(Encoding.ASCII.GetBytes(str)); StringBuilder stringBuilder = new StringBuilder(); foreach (byte b in hash) { stringBuilder.AppendFormat("{0:x2}", b); } return stringBuilder.ToString(); } private static byte[] GetBytesFromHexString(string strInput) { byte[] bytArOutput = new byte[] { }; if ((!string.IsNullOrEmpty(strInput)) && strInput.Length % 2 == 0) { SoapHexBinary hexBinary = null; hexBinary = SoapHexBinary.Parse(strInput); bytArOutput = hexBinary.Value; } return bytArOutput; } //AES 암호화 public static string AES128Encrypt(string Input) { try { RijndaelManaged aes = new RijndaelManaged(); //aes.KeySize = 256; //AES256으로 사용시 aes.KeySize = 128; //AES128로 사용시 aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = GetBytesFromHexString(key); aes.IV = GetBytesFromHexString(iv); var encrypt = aes.CreateEncryptor(aes.Key, aes.IV); byte[] xBuff = null; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, encrypt, CryptoStreamMode.Write)) { byte[] xXml = Encoding.UTF8.GetBytes(Input); cs.Write(xXml, 0, xXml.Length); } xBuff = ms.ToArray(); } string Output = Convert.ToBase64String(xBuff); return Output; } catch (Exception ex) { Debug.LogError(ex.Message); return ex.Message; } } //AES 복호화 public static string AES128Decrypt(string Input) { try { RijndaelManaged aes = new RijndaelManaged(); //aes.KeySize = 256; //AES256으로 사용시 aes.KeySize = 128; //AES128로 사용시 aes.BlockSize = 128; aes.Mode = CipherMode.CBC; aes.Padding = PaddingMode.PKCS7; aes.Key = GetBytesFromHexString(key); aes.IV = GetBytesFromHexString(iv); var decrypt = aes.CreateDecryptor(); byte[] xBuff = null; using (var ms = new MemoryStream()) { using (var cs = new CryptoStream(ms, decrypt, CryptoStreamMode.Write)) { byte[] xXml = Convert.FromBase64String(Input); cs.Write(xXml, 0, xXml.Length); } xBuff = ms.ToArray(); } string Output = Encoding.UTF8.GetString(xBuff); return Output; } catch (Exception ex) { Debug.LogError(ex.Message); return string.Empty; } } }


Posted by 시니^^

티스토리 툴바