这周把License授权给改了,由8个文件变成了3个,由2个工具变成1个,1515行觥筹交错的代码变成了1175行秩序井然的代码,维护难度由没有维护的无穷大变成很容易看得懂,支持的license长度由117字节变成无限,支持的授权方式由文件变成文件和网络。
这标志着我们技术债务还得差不多了,很快都是容易维护的社会主义产物了。无债一身轻啊!无债一身轻啊!无债一身轻啊!重要的事情说三遍,重要的事情说三遍,重要的事情说三遍。
贴一段非关键代码对比下,RSA加密然后用BASE64加密,之前的代码估计是被车轮战碾压过了,每个人都改一次,改得都不知道要干啥了:
}
char* aes_encipher(const char *in_buf,
const char* password,
RSA* rsa_shield,
int random_salt)
{
char* out_buf = NULL;
int rsa_in_len = 0;
char* rsa_in_buf = NULL;
int rsa_out_len = 0;
char* rsa_out_buf = NULL;
char salt[PKCS5_SALT_LEN] = {0};
int in_buf_len = strlen(in_buf);
BIO* write_bio = NULL;
BIO* cipher_bio = NULL;
BIO *b64_bio = BIO_new(BIO_f_base64());
BIO *mem_bio = BIO_new(BIO_s_mem());
if (!mem_bio) {
error_log("BIO_new(BIO_s_mem()) error\n");
goto end;
}
if (!b64_bio) {
error_log("BIO_f_base64 can't be created\n");
goto end;
}
write_bio = BIO_push(b64_bio, mem_bio);
if (random_salt) {
if (RAND_pseudo_bytes((unsigned char*)salt, sizeof(salt)) < 0) {
error_log("PRNG error\n");
goto end;
}
} else {
strncpy(salt, magic, sizeof(salt));
}
if (!rsa_shield) {
if (!(BIO_write(write_bio, magic, magic_len) == magic_len
&& BIO_write(write_bio, (char *)salt, sizeof(salt)) == sizeof(salt))) {
error_log("error writing salt to output\n");
goto end;
}
} else {
//include the '\0' end of password
rsa_in_len = magic_len + PKCS5_SALT_LEN + strlen(password) + 1;
rsa_in_buf = (char*)OPENSSL_malloc(rsa_in_len);
memcpy(rsa_in_buf, magic, magic_len);
memcpy(rsa_in_buf + magic_len, salt, PKCS5_SALT_LEN);
strcpy(rsa_in_buf + magic_len + PKCS5_SALT_LEN, password);
if (rsa_encrypt_or_decrypt(rsa_shield, rsa_in_buf, rsa_in_len,
&rsa_out_buf, &rsa_out_len, ENCRYPT) != 0) {
error_log("rsa encrypt aes key error\n");
goto end;
}
if (!(BIO_write(write_bio, rsa_out_buf, rsa_out_len) == rsa_out_len)) {
error_log("write encrypted aes key error\n");
goto end;
}
}
cipher_bio = get_aes_cipher_bio(salt, password, ENCRYPT);
if (cipher_bio == NULL) {
error_log("get cipher bio error\n");
goto end;
}
/* chain wbio and cipher_bio filter BIO */
write_bio = BIO_push(cipher_bio, write_bio);
if (BIO_write(write_bio, in_buf, in_buf_len) != in_buf_len) {
error_log("error writing content to output\n");
goto end;
}
if (BIO_flush(write_bio) != 1) {
error_log("error flush to output\n");
goto end;
}
out_buf = copy_mem_bio_data(mem_bio);
end:
BIO_free_all(write_bio);
if (rsa_in_len) {
OPENSSL_free(rsa_in_buf);
}
if (rsa_out_buf) {
OPENSSL_free(rsa_out_buf);
}
return out_buf;
}
谁要是能看懂就真的要跪地上给磕头,当然license嘛,就是要看不懂防止破解——额,无语。这个代码的问题是:
{
后面,就是函数声明那里,竟然换了两行,其他地方就只有一行,这种就是随机的代码。rsa_shield
为NULL时,就用password,也就是这个函数其实有可能用rsa,有可能用aes,反正这个用什么是说不太清除的。end
标签,这种c语言的GOTO,其实用结构体保存指针,然后释放会好些(模拟C++的析构函数)。copy_mem_bio_data
,这种也算个函数?直接读就好了,就几行代码,不是看着几行代码凑齐了就搞个函数,那初中生的水平就知道怎么划分函数。write_bio
这种变量命名,像是个函数,动词加名词。好神奇的名字。而且类型作为后缀,真的是太初级了,我想起了vhost_list
,app_array
,refer_vector
长篇累牍的鬼名字。error_log
每个日志函数后面都加\n
,这种用宏定义展开自动加不好么?查查__VA_ARGS__
这个宏定义就知道了。char*
,要是有错误咋办?返回NULL
?咋知道是啥错误?应该用错误码的,输出的buf用指针嘛。总之,这种代码就是小学生的水平,或者是喝醉了的程序员写的吧。反正时代久远,也不知道谁写的了。
看水平高点的猴写的代码:
int SrsRsa::encrypt_hwinfo(string hwinfo, string& ehwinfo)
{
int ret = ERROR_SUCCESS;
if (bio) {
BIO_free_all(bio);
}
BIO* mem_bio = BIO_new(BIO_s_mem());
if (!mem_bio) {
ret = ERROR_LICENSE_GENERATION;
srs_error("BIO_new memory io failed. ret=%d", ret);
return ret;
}
bio = mem_bio;
BIO* b64_bio = BIO_new(BIO_f_base64());
if (!b64_bio) {
ret = ERROR_LICENSE_GENERATION;
srs_error("BIO_new base64 io failed. ret=%d", ret);
return ret;
}
bio = BIO_push(b64_bio, bio);
// encrypted by segment RSA.
string encrypted;
if ((ret = srs_segment_rsa_encrypt(rsa, hwinfo, encrypted, false)) != ERROR_SUCCESS) {
return ret;
}
// write to bio.
if (BIO_write(bio, encrypted.data(), encrypted.length()) != encrypted.length()) {
ret = ERROR_LICENSE_GENERATION;
srs_error("BIO_write failed. ret=%d", ret);
return ret;
}
if (BIO_flush(bio) != 1) {
ret = ERROR_LICENSE_GENERATION;
srs_error("BIO_flush failed. ret=%d", ret);
return ret;
}
BUF_MEM* raw;
BIO_get_mem_ptr(bio, &raw);
ehwinfo.append(raw->data, raw->length);
return ret;
}
卧草,不言自明吧?将硬件信息用RSA加密后用BASE64加密,就这么简单。维护这种清楚的代码,就是一种休闲,和游山玩水一样自在。一看到垃圾代码,就像吃垃圾一样,恶心头痛,腿抽筋。
各位看这个文章的程序猴们,能不能认真写好代码?提升水平,多看看经典的书,多学习,多改变?能不能不要一副年纪太大什么都懂,一听意见就狡辩?本人30岁了还学了go和scala,是在已经做完SRS之后(还没有骄傲自满),大学我就把经典的软件书籍都好好读了(MFC深入浅出我每个例子都敲过代码理解过,数据结构我都实现过,人月敏捷我认真读过,设计模式我都能画出来),你基础差我这么多,积累也差我这么多,有什么理由不好好学习?
不好好学习不长进的程序猴就是不要脸。