diff --git a/spec/test/utilSpec.js b/spec/test/utilSpec.js
--- a/spec/test/utilSpec.js
+++ b/spec/test/utilSpec.js
@@ -13,6 +13,15 @@ describe("Util",function(){
 		["\uD55C\uAD6D\uC5B4",[0xED,0x95,0x9C,0xEA,0xB5,0xAD,0xEC,0x96,0xB4]],
 		["\ud84c\udfb4",[0xf0,0xa3,0x8e,0xb4]]
 	];
+	let base64=[
+		[[],""],
+		[[102],"Zg=="],
+		[[102,111],"Zm8="],
+		[[102,111,111],"Zm9v"],
+		[[102,111,111,98],"Zm9vYg=="],
+		[[102,111,111,98,97],"Zm9vYmE="],
+		[[102,111,111,98,97,114],"Zm9vYmFy"]
+	];
 	
 	describe("bytes2int32s",function(){
 		it("should pack bytes into 32b integers",function(){
@@ -34,4 +43,17 @@ describe("Util",function(){
 			utf.forEach(couple=>expect(util.utf82str(couple[1])).toEqual(couple[0]));
 		});
 	});
+	
+	
+	describe("bytes2base64",function(){
+		it("should correctly encode bytes into base64",function(){
+			base64.forEach(couple=>expect(util.bytes2base64(couple[0])).toEqual(couple[1]));
+		});
+	});
+	
+	describe("base642bytes",function(){
+		it("should correctly decode bytes from base64",function(){
+			base64.forEach(couple=>expect(util.base642bytes(couple[1])).toEqual(couple[0]));
+		});
+	});
 });
diff --git a/src/util.js b/src/util.js
--- a/src/util.js
+++ b/src/util.js
@@ -96,3 +96,45 @@ export function utf82str(arr){
 	}
 	return res.map(x=>String.fromCodePoint(x)).join("");
 }
+
+const mapping="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split("");
+const remapping=new Array(128);
+mapping.forEach((c,i)=>{remapping[c.charCodeAt(0)]=i;});
+
+export function bytes2base64(byteArr){
+	let arr=byteArr.concat();
+	let out=[];
+	let rem=(3-arr.length%3)%3;
+	for(let i=0;i<rem;i++){arr.push(0);} // pad array to a multiple of 3
+	
+	for(let i=0;i<arr.length;i+=3){ // encode 3 bytes into 4 characters
+		out.push(mapping[arr[i]>>>2&63]);
+		out.push(mapping[((arr[i]&3)<<4)+(arr[i+1]>>>4&15)]);
+		out.push(mapping[((arr[i+1]&15)<<2)+(arr[i+2]>>>6&3)]);
+		out.push(mapping[arr[i+2]&63]);
+	}
+	
+	for(let i=0;i<rem;i++){out.pop();}
+	for(let i=0;i<rem;i++){out.push("=");}
+
+	return out.join("");
+}
+
+export function base642bytes(str){
+	let out=[];
+	
+	for(let i=0;i<str.length;i+=4){
+		let b1=remapping[str.charCodeAt(i)];
+		let b2=remapping[str.charCodeAt(i+1)];
+		let b3=remapping[str.charCodeAt(i+2)];
+		let b4=remapping[str.charCodeAt(i+3)];
+		
+		out.push((b1<<2)+(b2>>4&3));
+		out.push(((b2&15)<<4)+(b3>>2&15));
+		out.push(((b3&3)<<6)+b4);
+	}
+	
+	for(let i=1; i<3&&str[str.length-i]=="="; i++){out.pop();}
+
+	return out;
+}