{"id":1337,"date":"2012-12-14T05:56:23","date_gmt":"2012-12-14T12:56:23","guid":{"rendered":"http:\/\/wiebe-elsinga.com\/blog\/?p=1337"},"modified":"2012-12-14T05:56:23","modified_gmt":"2012-12-14T12:56:23","slug":"obfuscating-for-android-with-proguard","status":"publish","type":"post","link":"http:\/\/wiebe-elsinga.com\/blog\/obfuscating-for-android-with-proguard\/","title":{"rendered":"Obfuscating for Android with ProGuard"},"content":{"rendered":"<div class=\"wpsso-pinterest-pin-it-image\" style=\"display:none !important;\">\n<\/div><!-- .wpsso-pinterest-pin-it-image -->\n\n<p>Obfu-what? Right, Obfuscation, in general, describes a practice that is used to intentionally make something more difficult to understand.<br \/>\nThe nature of Java (the programming language for Android apps) is that the code is not compiled down to machine code; it is compiled to an intermediate format that is ready to be run on a variety of hardware platforms. While this allows great portability, it also leaves the code for Android apps, as present in the APK (Application PacKage file), available for extraction.<br \/>\nI&#8217;m going to describe a way for you to obfuscate your Android code to make it harder for others to reverse engineer. And also why not shrink the size of your Android applications and optimize them to make them run faster at the same time.<\/p>\n<p>Without a doubt, the simplest method to protect an app is to enable the obfuscation in <a href=\"http:\/\/proguard.sourceforge.net\/\" title=\"Proguard\" target=\"_blank\">ProGuard<\/a>. This freely available tool is already built into the Android toolkit.<\/p>\n<h3>Obfuscation<\/h3>\n<p>By default, compiled bytecode still contains a lot of debugging information: source file names, line numbers, field names, method names, argument names, variable names, etc. This information makes it straightforward to decompile the bytecode and reverse-engineer entire apps. Sometimes, this is not desirable. Obfuscators, such as ProGuard, can remove the debugging information and replace all names by meaningless character sequences, making it much harder to reverse-engineer the code. It further compacts the code as a bonus. The app remains functionally equivalent, except for the class names, method names, and line numbers given in exception stack traces.<\/p>\n<h3>Shrinking<\/h3>\n<p>Java source code (.java files) is typically compiled to bytecode (.class files). Bytecode is more compact than Java source code, but it may still contain a lot of unused code, especially if it includes program libraries. Shrinking programs such as ProGuard can analyze bytecode and remove unused classes, fields, and methods. The app remains functionally equivalent, including the information given in exception stack traces. <\/p>\n<p>For a realistic example, take the following code:<\/p>\n<div class=\"codecolorer-container java default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"java codecolorer\"><span class=\"kw1\">if<\/span><span class=\"br0\">&#40;<\/span>Config.<span class=\"me1\">LOGD<\/span><span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#123;<\/span><br \/>\n&nbsp;Log.<span class=\"me1\">d<\/span><span class=\"br0\">&#40;<\/span>TAG, <span class=\"st0\">&quot;Some text&quot;<\/span><span class=\"br0\">&#41;<\/span><span class=\"sy0\">;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>The code as shown above is a typical scenario during development. You create code like this to help debug and test your code. Before releasing the final product, though, you set Config.LOGD to false, so it doesn&#8217;t execute. The problem is, this code is still in your application. It makes it bigger, and may cause potential security issues by including code which should never be seen by a snooping hacker.<\/p>\n<p>Shrinking the code solves this problem beautifully. The code is completely removed from the final product, leaving the final package safer and smaller.<\/p>\n<h3>Optimizing<\/h3>\n<p>Apart from removing unused classes, fields, and methods in the shrinking step, ProGuard can also perform optimizations at the bytecode level, inside and across methods.<\/p>\n<h3>Proguard<\/h3>\n<p>So let&#8217;s have a look at the <i>proguard.cfg<\/i> file. I recommend you open up the <a href=\"https:\/\/github.com\/welsinga\/sample_proguard\" title=\"Sample code\" target=\"_blank\">sample code<\/a>, as I will be highlighting the key parts on this page.<\/p>\n<h4>Basic template<\/h4>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><div class=\"text codecolorer\">-dontpreverify<br \/>\n-repackageclasses ''<br \/>\n-allowaccessmodification<br \/>\n-optimizations !code\/simplification\/arithmetic<br \/>\n-keepattributes *Annotation*<br \/>\n<br \/>\n-keep public class * extends android.app.Activity<br \/>\n-keep public class * extends android.app.Application<br \/>\n-keep public class * extends android.app.Service<br \/>\n-keep public class * extends android.content.BroadcastReceiver<br \/>\n-keep public class * extends android.content.ContentProvider<br \/>\n<br \/>\n-keep public class * extends android.view.View {<br \/>\n&nbsp; &nbsp; public &lt;init&gt;(android.content.Context);<br \/>\n&nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet);<br \/>\n&nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);<br \/>\n&nbsp; &nbsp; public void set*(...);<br \/>\n}<br \/>\n<br \/>\n-keepclasseswithmembers class * {<br \/>\n&nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet);<br \/>\n}<br \/>\n<br \/>\n-keepclasseswithmembers class * {<br \/>\n&nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int);<br \/>\n}<br \/>\n<br \/>\n-keepclassmembers class * implements android.os.Parcelable {<br \/>\n&nbsp; &nbsp; static android.os.Parcelable$Creator CREATOR;<br \/>\n}<br \/>\n<br \/>\n-keepclassmembers class **.R$* {<br \/>\n&nbsp; &nbsp; public static &lt;fields&gt;;<br \/>\n}<\/div><\/div>\n<h4>Fragments<\/h4>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"text codecolorer\">-keep public class * extends android.support.v4.app.Fragment<br \/>\n-keep public class * extends android.app.Fragment<\/div><\/div>\n<h4>Serializables<\/h4>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"text codecolorer\">-keepnames class * implements java.io.Serializable<br \/>\n<br \/>\n-keepclassmembers class * implements java.io.Serializable {<br \/>\n&nbsp; &nbsp; static final long serialVersionUID;<br \/>\n&nbsp; &nbsp; private static final java.io.ObjectStreamField[] serialPersistentFields;<br \/>\n&nbsp; &nbsp; !static !transient &lt;fields&gt;;<br \/>\n&nbsp; &nbsp; !private &lt;fields&gt;;<br \/>\n&nbsp; &nbsp; !private &lt;methods&gt;;<br \/>\n&nbsp; &nbsp; private void writeObject(java.io.ObjectOutputStream);<br \/>\n&nbsp; &nbsp; private void readObject(java.io.ObjectInputStream);<br \/>\n&nbsp; &nbsp; java.lang.Object writeReplace();<br \/>\n&nbsp; &nbsp; java.lang.Object readResolve();<br \/>\n}<\/div><\/div>\n<h4>Removing Logging<\/h4>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"text codecolorer\">-assumenosideeffects class android.util.Log {<br \/>\n&nbsp; &nbsp; public static *** e(...);<br \/>\n&nbsp; &nbsp; public static *** w(...);<br \/>\n&nbsp; &nbsp; public static *** wtf(...);<br \/>\n&nbsp; &nbsp; public static *** d(...);<br \/>\n&nbsp; &nbsp; public static *** v(...);<br \/>\n}<\/div><\/div>\n<h4>Methods<\/h4>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"text codecolorer\">-keepclasseswithmembernames class * {<br \/>\n&nbsp; &nbsp; native &lt;methods&gt;;<br \/>\n}<br \/>\n-keepclassmembers class * {<br \/>\n&nbsp; &nbsp; public void *ButtonClicked(android.view.View);<br \/>\n}<\/div><\/div>\n<p>Now that we have added all our Proguard settings, we need to run Proguard during the build fase. I will use <i>Maven<\/i> to illustrate this.<\/p>\n<p>Within your <i>pom.xml<\/i> the <i>android-maven-plugin<\/i> should be defined. To this definition add the <i>proguard<\/i> setting like:<\/p>\n<div class=\"codecolorer-container xml default\" style=\"overflow:auto;white-space:nowrap;width:100%;height:100%;\"><div class=\"xml codecolorer\">&nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;plugin<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;groupId<span class=\"re2\">&gt;<\/span><\/span><\/span>com.jayway.maven.plugins.android.generation2<span class=\"sc3\"><span class=\"re1\">&lt;\/groupId<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;artifactId<span class=\"re2\">&gt;<\/span><\/span><\/span>android-maven-plugin<span class=\"sc3\"><span class=\"re1\">&lt;\/artifactId<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;version<span class=\"re2\">&gt;<\/span><\/span><\/span>3.0.0<span class=\"sc3\"><span class=\"re1\">&lt;\/version<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;extensions<span class=\"re2\">&gt;<\/span><\/span><\/span>true<span class=\"sc3\"><span class=\"re1\">&lt;\/extensions<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;configuration<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;sdk<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;platform<span class=\"re2\">&gt;<\/span><\/span><\/span>15<span class=\"sc3\"><span class=\"re1\">&lt;\/platform<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/sdk<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;dex<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;jvmArguments<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;argument<span class=\"re2\">&gt;<\/span><\/span><\/span>-Xms256m<span class=\"sc3\"><span class=\"re1\">&lt;\/argument<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;argument<span class=\"re2\">&gt;<\/span><\/span><\/span>-Xmx512m<span class=\"sc3\"><span class=\"re1\">&lt;\/argument<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/jvmArguments<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/dex<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;run<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;debug<span class=\"re2\">&gt;<\/span><\/span><\/span>true<span class=\"sc3\"><span class=\"re1\">&lt;\/debug<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/run<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;proguard<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;skip<span class=\"re2\">&gt;<\/span><\/span><\/span>false<span class=\"sc3\"><span class=\"re1\">&lt;\/skip<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;config<span class=\"re2\">&gt;<\/span><\/span><\/span>proguard.cfg<span class=\"sc3\"><span class=\"re1\">&lt;\/config<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/proguard<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/configuration<span class=\"re2\">&gt;<\/span><\/span><\/span><br \/>\n&nbsp; &nbsp; &nbsp; <span class=\"sc3\"><span class=\"re1\">&lt;\/plugin<span class=\"re2\">&gt;<\/span><\/span><\/span><\/div><\/div>\n<p>All that is left is to run Maven with<\/p>\n<div class=\"codecolorer-container dos default\" style=\"overflow:auto;white-space:nowrap;width:100%;\"><div class=\"dos codecolorer\">mvn clean install<\/div><\/div>\n<p>To check if the app has been obfuscated, install the apk on you Android device and when you run it, you shouldn&#8217;t see any logging in logcat.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Obfu-what? Right, Obfuscation, in general, describes a practice that is used to intentionally make something more difficult to understand. The nature of Java (the programming language for Android apps) is that the code is not compiled down to machine code; it is compiled to an intermediate format that is ready to be run on a variety of hardware platforms. While this allows great portability, it also leaves the code for Android apps, as present in the APK (Application PacKage file), available for extraction. I&#8217;m going to describe a way for you to obfuscate your Android code to make it harder for others to reverse engineer. And also why not shrink the size of your Android applications and optimize them to make them run faster at the same time. Without a doubt, the simplest method to protect an app is to enable the obfuscation in ProGuard. This freely available tool is already built into the Android toolkit. Obfuscation By default, compiled bytecode still contains a lot of debugging information: source file names, line numbers, field names, method names, argument names, variable names, etc. This information makes it straightforward to decompile the bytecode and reverse-engineer entire apps. Sometimes, this is not desirable. Obfuscators, such as ProGuard, can remove the debugging information and replace all names by meaningless character sequences, making it much harder to reverse-engineer the code. It further compacts the code as a bonus. The app remains functionally equivalent, except for the class names, method names, and line numbers given in exception stack traces. Shrinking Java source code (.java files) is typically compiled to bytecode (.class files). Bytecode is more compact than Java source code, but it may still contain a lot of unused code, especially if it includes program libraries. Shrinking programs such as ProGuard can analyze bytecode and remove unused classes, fields, and methods. The app remains functionally equivalent, including the information given in exception stack traces. For a realistic example, take the following code: if&#40;Config.LOGD&#41;&#41; &#123; &nbsp;Log.d&#40;TAG, &quot;Some text&quot;&#41;; &#125; The code as shown above is a typical scenario during development. You create code like this to help debug and test your code. Before releasing the final product, though, you set Config.LOGD to false, so it doesn&#8217;t execute. The problem is, this code is still in your application. It makes it bigger, and may cause potential security issues by including code which should never be seen by a snooping hacker. Shrinking the code solves this problem beautifully. The code is completely removed from the final product, leaving the final package safer and smaller. Optimizing Apart from removing unused classes, fields, and methods in the shrinking step, ProGuard can also perform optimizations at the bytecode level, inside and across methods. Proguard So let&#8217;s have a look at the proguard.cfg file. I recommend you open up the sample code, as I will be highlighting the key parts on this page. Basic template -dontpreverify -repackageclasses &#8221; -allowaccessmodification -optimizations !code\/simplification\/arithmetic -keepattributes *Annotation* -keep public class * extends android.app.Activity -keep public class * extends android.app.Application -keep public class * extends android.app.Service -keep public class * extends android.content.BroadcastReceiver -keep public class * extends android.content.ContentProvider -keep public class * extends android.view.View { &nbsp; &nbsp; public &lt;init&gt;(android.content.Context); &nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet); &nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int); &nbsp; &nbsp; public void set*(&#8230;); } -keepclasseswithmembers class * { &nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet); } -keepclasseswithmembers class * { &nbsp; &nbsp; public &lt;init&gt;(android.content.Context, android.util.AttributeSet, int); } -keepclassmembers class * implements android.os.Parcelable { &nbsp; &nbsp; static android.os.Parcelable$Creator CREATOR; } -keepclassmembers class **.R$* { &nbsp; &nbsp; public static &lt;fields&gt;; } Fragments -keep public class * extends android.support.v4.app.Fragment -keep public class * extends android.app.Fragment Serializables -keepnames class * implements java.io.Serializable -keepclassmembers class * implements java.io.Serializable { &nbsp; &nbsp; static final long serialVersionUID; &nbsp; &nbsp; private static final java.io.ObjectStreamField[] serialPersistentFields; &nbsp; &nbsp; !static !transient &lt;fields&gt;; &nbsp; &nbsp; !private &lt;fields&gt;; &nbsp; &nbsp; !private &lt;methods&gt;; &nbsp; &nbsp; private void writeObject(java.io.ObjectOutputStream); &nbsp; &nbsp; private void readObject(java.io.ObjectInputStream); &nbsp; &nbsp; java.lang.Object writeReplace(); &nbsp; &nbsp; java.lang.Object readResolve(); } Removing Logging -assumenosideeffects class android.util.Log { &nbsp; &nbsp; public static *** e(&#8230;); &nbsp; &nbsp; public static *** w(&#8230;); &nbsp; &nbsp; public static *** wtf(&#8230;); &nbsp; &nbsp; public static *** d(&#8230;); &nbsp; &nbsp; public static *** v(&#8230;); } Methods -keepclasseswithmembernames class * { &nbsp; &nbsp; native &lt;methods&gt;; } -keepclassmembers class * { &nbsp; &nbsp; public void *ButtonClicked(android.view.View); } Now that we have added all our Proguard settings, we need to run Proguard during the build fase. I will use Maven to illustrate this. Within your pom.xml the android-maven-plugin should be defined. To this definition add the proguard setting like: &nbsp; &nbsp; &nbsp; &lt;plugin&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;groupId&gt;com.jayway.maven.plugins.android.generation2&lt;\/groupId&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;artifactId&gt;android-maven-plugin&lt;\/artifactId&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;version&gt;3.0.0&lt;\/version&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;extensions&gt;true&lt;\/extensions&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;configuration&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;sdk&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;platform&gt;15&lt;\/platform&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/sdk&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;dex&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;jvmArguments&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;argument&gt;-Xms256m&lt;\/argument&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;argument&gt;-Xmx512m&lt;\/argument&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/jvmArguments&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/dex&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;run&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;debug&gt;true&lt;\/debug&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/run&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;proguard&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;skip&gt;false&lt;\/skip&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;config&gt;proguard.cfg&lt;\/config&gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/proguard&gt; &nbsp; &nbsp; &nbsp; &nbsp; &lt;\/configuration&gt; &nbsp; &nbsp; &nbsp; &lt;\/plugin&gt; All that is left is to run Maven with mvn clean install To check if the app has been obfuscated, install the apk on you Android device and when you run it, you shouldn&#8217;t see any logging in logcat.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[7,95],"tags":[154,131],"_links":{"self":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts\/1337"}],"collection":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/comments?post=1337"}],"version-history":[{"count":0,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/posts\/1337\/revisions"}],"wp:attachment":[{"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/media?parent=1337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/categories?post=1337"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/wiebe-elsinga.com\/blog\/wp-json\/wp\/v2\/tags?post=1337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}