Created
December 20, 2014 07:14
-
-
Save XMPPwocky/e7689cd19e78cf46390b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use core; | |
use core::prelude::*; | |
use collections; | |
pub struct ObfuscatedString { | |
crypted: &'static [u8], | |
key: &'static [u8] | |
} | |
impl ObfuscatedString { | |
pub fn dec_into(&self, dest: &mut [u8]) { | |
let &ObfuscatedString { crypted, key } = self; | |
for (d, (c, k)) in dest.iter_mut().zip(crypted.iter().zip(key.iter())) { | |
*d = *c ^ *k; | |
} | |
} | |
pub fn dec_vec(&self) -> collections::vec::Vec<u8> { | |
let len = self.crypted.len(); | |
let mut v = collections::vec::Vec::with_capacity(len); | |
unsafe { | |
// safe because of with_capacity | |
v.set_len(len); | |
} | |
self.dec_into(v.as_mut_slice()); | |
v | |
} | |
pub fn dec(&self) -> collections::string::String { | |
// this is safe, because all constructors of ObfuscatedString | |
// are unsafe; thus the invariant that decryption produces valid UTF-8 | |
// is maintained in safe code | |
unsafe { | |
collections::string::raw::from_utf8(self.dec_vec()) | |
} | |
} | |
} | |
impl core::cmp::PartialEq<str> for ObfuscatedString { | |
fn eq(&self, other: &str) -> bool { | |
let decrypted = self.crypted.iter().zip(self.key.iter()).map(|(&a, &b)| a ^ b); | |
core::iter::order::eq(decrypted, other.bytes()) | |
} | |
} | |
impl core::cmp::PartialEq<ObfuscatedString> for str { | |
fn eq(&self, other: &ObfuscatedString) -> bool { | |
other == self | |
} | |
} | |
impl<'a> core::cmp::PartialEq<ObfuscatedString> for &'a str { | |
fn eq(&self, other: &ObfuscatedString) -> bool { | |
other == *self | |
} | |
} | |
pub unsafe fn construct(crypted: &'static [u8], key: &'static [u8]) -> ObfuscatedString { | |
ObfuscatedString { | |
crypted: crypted, | |
key: key | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![crate_type="dylib"] | |
#![feature(plugin_registrar)] | |
extern crate syntax; | |
extern crate rustc; | |
use syntax::codemap::Span; | |
use syntax::parse::{str_lit, token}; | |
use syntax::ast; | |
use syntax::ast::{Expr, Lit_, TokenTree, TtToken}; | |
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr}; | |
use syntax::ext::build::AstBuilder; // trait for expr_uint | |
use syntax::ptr::P; | |
use rustc::plugin::Registry; | |
fn crypt(s: &str) -> (Vec<u8>, Vec<u8>) { | |
use std::rand; | |
use std::rand::Rng; | |
let s = s.as_bytes(); | |
let mut rng = rand::task_rng(); | |
let mut key = Vec::from_elem(s.len(), 0); | |
rng.fill_bytes(key.as_mut_slice()); | |
let mut crypted = s.to_vec(); | |
for (c, k) in crypted.iter_mut().zip(key.iter()) { | |
*c = *c ^ *k; | |
} | |
(crypted, key) | |
} | |
fn construct_binlit(cx: &mut ExtCtxt, sp: Span, bytes: Vec<u8>) -> P<Expr> { | |
let rcbytes = std::rc::Rc::new(bytes); | |
cx.expr_lit(sp, Lit_::LitBinary(rcbytes)) | |
} | |
fn construct_call(cx: &mut ExtCtxt, sp: Span, crypted: Vec<u8>, key: Vec<u8>) -> P<Expr> | |
{ | |
let crypted_expr = construct_binlit(cx, sp, crypted); | |
let key_expr = construct_binlit(cx, sp, key); | |
let constructor_path = vec![ | |
token::intern("obfustring").ident(), | |
token::intern("construct").ident() | |
]; | |
cx.expr_call_global(sp, constructor_path, | |
vec![crypted_expr, key_expr]) | |
} | |
fn wrap_in_unsafe_block(cx: &mut ExtCtxt, sp: Span, expr: P<Expr>) -> P<Expr> { | |
cx.expr_block(P(ast::Block { | |
view_items: vec![], | |
stmts: vec![], | |
expr: Some(expr), | |
id: ast::DUMMY_NODE_ID, | |
rules: ast::UnsafeBlock(ast::CompilerGenerated), | |
span: sp, | |
})) | |
} | |
fn expand_obf(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) | |
-> Box<MacResult + 'static> { | |
let text = match args { | |
[TtToken(_, token::Literal(token::Lit::Str_(n), _))] => n, | |
_ => { | |
cx.span_err(sp, "argument should be a string literal"); | |
return DummyResult::any(sp); | |
} | |
}; | |
let text = str_lit(text.as_str()); | |
let (crypted, key) = crypt(text.as_slice()); | |
let call_expr = construct_call(cx, sp, crypted, key); | |
MacExpr::new(wrap_in_unsafe_block(cx, sp, call_expr)) | |
} | |
#[plugin_registrar] | |
pub fn plugin_registrar(reg: &mut Registry) { | |
reg.register_macro("obf", expand_obf); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment